mirror of
https://github.com/apple/container.git
synced 2026-07-14 05:27:02 +00:00
420be748f1
- 0.16.1 changes an ext4 superblock setting that might have been causing problems. - #877 fixed an issue where the cache and sync settings for block filesystems weren't being passed down to the VZ virtual machine configuration. The default sync value getting passed down is `full`, which reduces I/O performance. Relax this to use `fsync` for now. ## Type of Change - [*] Bug fix - [ ] New feature - [ ] Breaking change - [ ] Documentation update ## Motivation and Context May address problems reported in #877. ## Testing - [x] Tested locally - [ ] Added/updated tests - [ ] Added/updated docs
183 lines
5.8 KiB
Swift
183 lines
5.8 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
// Copyright © 2025 Apple Inc. and the container project authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import Foundation
|
|
|
|
/// Options to pass to a mount call.
|
|
public typealias MountOptions = [String]
|
|
|
|
extension MountOptions {
|
|
/// Returns true if the Filesystem should be consumed as read-only.
|
|
public var readonly: Bool {
|
|
self.contains("ro")
|
|
}
|
|
}
|
|
|
|
/// A host filesystem that will be attached to the sandbox for use.
|
|
///
|
|
/// A filesystem will be mounted automatically when starting the sandbox
|
|
/// or container.
|
|
public struct Filesystem: Sendable, Codable {
|
|
/// Type of caching to perform at the host level.
|
|
public enum CacheMode: Sendable, Codable {
|
|
case on
|
|
case off
|
|
case auto
|
|
}
|
|
|
|
/// Sync mode to perform at the host level.
|
|
public enum SyncMode: Sendable, Codable {
|
|
case full
|
|
case fsync
|
|
case nosync
|
|
}
|
|
|
|
/// The type of filesystem attachment for the sandbox.
|
|
public enum FSType: Sendable, Codable, Equatable {
|
|
package enum VirtiofsType: String, Sendable, Codable, Equatable {
|
|
// This is a virtiofs share for the rootfs of a sandbox.
|
|
case rootfs
|
|
// Data share. This is what all virtiofs shares for anything besides
|
|
// the rootfs for a sandbox will be.
|
|
case data
|
|
}
|
|
|
|
case block(format: String, cache: CacheMode, sync: SyncMode)
|
|
case volume(name: String, format: String, cache: CacheMode, sync: SyncMode)
|
|
case virtiofs
|
|
case tmpfs
|
|
}
|
|
|
|
/// Type of the filesystem.
|
|
public var type: FSType
|
|
/// Source of the filesystem.
|
|
public var source: String
|
|
/// Destination where the filesystem should be mounted.
|
|
public var destination: String
|
|
/// Mount options applied when mounting the filesystem.
|
|
public var options: MountOptions
|
|
|
|
public init() {
|
|
self.type = .tmpfs
|
|
self.source = ""
|
|
self.destination = ""
|
|
self.options = []
|
|
}
|
|
|
|
public init(type: FSType, source: String, destination: String, options: MountOptions) {
|
|
self.type = type
|
|
self.source = source
|
|
self.destination = destination
|
|
self.options = options
|
|
}
|
|
|
|
/// A block based filesystem.
|
|
public static func block(
|
|
format: String, source: String, destination: String, options: MountOptions, cache: CacheMode = .auto,
|
|
sync: SyncMode = .fsync
|
|
) -> Filesystem {
|
|
.init(
|
|
type: .block(format: format, cache: cache, sync: sync),
|
|
source: URL(fileURLWithPath: source).absolutePath(),
|
|
destination: destination,
|
|
options: options
|
|
)
|
|
}
|
|
|
|
/// A named volume filesystem.
|
|
public static func volume(
|
|
name: String, format: String, source: String, destination: String, options: MountOptions,
|
|
cache: CacheMode = .auto, sync: SyncMode = .fsync
|
|
) -> Filesystem {
|
|
.init(
|
|
type: .volume(name: name, format: format, cache: cache, sync: sync),
|
|
source: URL(fileURLWithPath: source).absolutePath(),
|
|
destination: destination,
|
|
options: options
|
|
)
|
|
}
|
|
|
|
/// A vritiofs backed filesystem providing a directory.
|
|
public static func virtiofs(source: String, destination: String, options: MountOptions) -> Filesystem {
|
|
.init(
|
|
type: .virtiofs,
|
|
source: URL(fileURLWithPath: source).absolutePath(),
|
|
destination: destination,
|
|
options: options
|
|
)
|
|
}
|
|
|
|
public static func tmpfs(destination: String, options: MountOptions) -> Filesystem {
|
|
.init(
|
|
type: .tmpfs,
|
|
source: "tmpfs",
|
|
destination: destination,
|
|
options: options
|
|
)
|
|
}
|
|
|
|
/// Returns true if the Filesystem is backed by a block device.
|
|
public var isBlock: Bool {
|
|
switch type {
|
|
case .block(_, _, _): true
|
|
case .volume(_, _, _, _): true
|
|
default: false
|
|
}
|
|
}
|
|
|
|
/// Returns true if the Filesystem is a named volume.
|
|
public var isVolume: Bool {
|
|
switch type {
|
|
case .volume(_, _, _, _): true
|
|
default: false
|
|
}
|
|
}
|
|
|
|
/// Returns the volume name if this is a volume filesystem, nil otherwise.
|
|
public var volumeName: String? {
|
|
switch type {
|
|
case .volume(let name, _, _, _): name
|
|
default: nil
|
|
}
|
|
}
|
|
|
|
/// Returns true if the Filesystem is backed by a in-memory mount type.
|
|
public var isTmpfs: Bool {
|
|
switch type {
|
|
case .tmpfs: true
|
|
default: false
|
|
}
|
|
}
|
|
|
|
/// Returns true if the Filesystem is backed by virtioFS.
|
|
public var isVirtiofs: Bool {
|
|
switch type {
|
|
case .virtiofs: true
|
|
default: false
|
|
}
|
|
}
|
|
|
|
/// Clone the Filesystem to the provided path.
|
|
///
|
|
/// This uses `clonefile` to provide a copy-on-write copy of the Filesystem.
|
|
public func clone(to: String) throws -> Self {
|
|
let fm = FileManager.default
|
|
let src = self.source
|
|
try fm.copyItem(atPath: src, toPath: to)
|
|
return .init(type: self.type, source: to, destination: self.destination, options: self.options)
|
|
}
|
|
}
|