Support setting root disk synchronization mode (#875)

* Support setting root disk synchronization mode

Adds a new VMConfig parameter (tart get / tart set) called 'sync' which
can be set to 'full' (default), 'fsync', or 'none', corresponding with
the values of VZDiskImageSynchronizationMode and allowing a tradeoff
between data integrity and speed.

* Remove unused import

* Fix formatting

* Make root disk sync behaviour a commandline option
This commit is contained in:
Nicholas FitzRoy-Dale 2024-08-05 19:12:43 +10:00 committed by GitHub
parent 3f26baa341
commit 5f2199ef3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 5 deletions

View File

@ -12,6 +12,34 @@ var vm: VM?
struct IPNotFound: Error {
}
extension VZDiskImageSynchronizationMode : LosslessStringConvertible {
public init?(_ description: String) {
switch description {
case "none":
self = .none
case "fsync":
self = .fsync
case "full":
self = .full
default:
return nil
}
}
public var description: String {
switch self {
case .none:
return "none"
case .fsync:
return "fsync"
case .full:
return "full"
@unknown default:
return "unknown"
}
}
}
struct Run: AsyncParsableCommand {
static var configuration = CommandConfiguration(abstract: "Run a VM")
@ -140,6 +168,14 @@ struct Run: AsyncParsableCommand {
@Flag(help: ArgumentHelp("Restrict network access to the host-only network"))
var netHost: Bool = false
@Option(help: ArgumentHelp("Set the root disk synchronization mode (Linux images only). Possible values: none, fsync, full.",
discussion: """
'full' synchronizes data with the drive and ensures that it is written to permanent storage.
'fsync' synchronizes data with the drive but doesn't guarantee that it is written to permanent storage.
'none' doesn't synchronize data with the drive.
"""))
var sync: String = "full"
#if arch(arm64)
@Flag(help: ArgumentHelp("Disables audio and entropy devices and switches to only Mac-specific input devices.", discussion: "Useful for running a VM that can be suspended via \"tart suspend\"."))
#endif
@ -195,6 +231,10 @@ struct Run: AsyncParsableCommand {
throw ValidationError("Seems you have a disk targeting x86 architecture (hence amd64 in the name). Please use an 'arm64' version of the disk.")
}
}
if(VZDiskImageSynchronizationMode(sync) == nil) {
throw ValidationError("Invalid disk synchronization mode: \(sync)")
}
}
@MainActor
@ -247,7 +287,8 @@ struct Run: AsyncParsableCommand {
serialPorts: serialPorts,
suspendable: suspendable,
audio: !noAudio,
clipboard: !noClipboard
clipboard: !noClipboard,
sync: VZDiskImageSynchronizationMode(sync) ?? .full
)
let vncImpl: VNC? = try {

View File

@ -48,7 +48,8 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
serialPorts: [VZSerialPortConfiguration] = [],
suspendable: Bool = false,
audio: Bool = true,
clipboard: Bool = true
clipboard: Bool = true,
sync: VZDiskImageSynchronizationMode = .full
) throws {
name = vmDir.name
config = try VMConfig.init(fromURL: vmDir.configURL)
@ -66,7 +67,8 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
serialPorts: serialPorts,
suspendable: suspendable,
audio: audio,
clipboard: clipboard
clipboard: clipboard,
sync: sync
)
virtualMachine = VZVirtualMachine(configuration: configuration)
@ -294,7 +296,8 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
serialPorts: [VZSerialPortConfiguration],
suspendable: Bool = false,
audio: Bool = true,
clipboard: Bool = true
clipboard: Bool = true,
sync: VZDiskImageSynchronizationMode = .full
) throws -> VZVirtualMachineConfiguration {
let configuration = VZVirtualMachineConfiguration()
@ -350,7 +353,7 @@ class VM: NSObject, VZVirtualMachineDelegate, ObservableObject {
// Storage
let attachment: VZDiskImageStorageDeviceAttachment = vmConfig.os == .linux ?
// Use "cached" caching mode for virtio drive to prevent fs corruption on linux
try VZDiskImageStorageDeviceAttachment(url: diskURL, readOnly: false, cachingMode: .cached, synchronizationMode: .full) :
try VZDiskImageStorageDeviceAttachment(url: diskURL, readOnly: false, cachingMode: .cached, synchronizationMode: sync) :
try VZDiskImageStorageDeviceAttachment(url: diskURL, readOnly: false)
var device: VZStorageDeviceConfiguration