mirror of
https://github.com/utmapp/UTM.git
synced 2026-10-12 02:24:01 +00:00
Merge pull request #5919 from gnattu/main
fix: Add workarounds to prevent filesystem corruption on Apple Virtualization VMs.
This commit is contained in:
@@ -265,11 +265,13 @@ extension UTMAppleConfiguration {
|
||||
}
|
||||
if !ignoringDrives {
|
||||
vzconfig.storageDevices = try drives.compactMap { drive in
|
||||
guard let attachment = try drive.vzDiskImage() else {
|
||||
guard let attachment = try drive.vzDiskImage(useFsWorkAround: system.boot.operatingSystem == .linux) else {
|
||||
return nil
|
||||
}
|
||||
if #available(macOS 13, *), drive.isExternal {
|
||||
return VZUSBMassStorageDeviceConfiguration(attachment: attachment)
|
||||
} else if #available(macOS 14, *), drive.isNvme, system.boot.operatingSystem == .linux {
|
||||
return VZNVMExpressControllerDeviceConfiguration(attachment: attachment)
|
||||
} else {
|
||||
return VZVirtioBlockDeviceConfiguration(attachment: attachment)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive {
|
||||
var sizeMib: Int = 0
|
||||
var isReadOnly: Bool
|
||||
var isExternal: Bool
|
||||
var isNvme: Bool
|
||||
var imageURL: URL?
|
||||
var imageName: String?
|
||||
|
||||
@@ -36,6 +37,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive {
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case isReadOnly = "ReadOnly"
|
||||
case isNvme = "Nvme"
|
||||
case imageName = "ImageName"
|
||||
case bookmark = "Bookmark" // legacy only
|
||||
case identifier = "Identifier"
|
||||
@@ -55,12 +57,14 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive {
|
||||
sizeMib = newSize
|
||||
isReadOnly = false
|
||||
isExternal = false
|
||||
isNvme = false
|
||||
}
|
||||
|
||||
init(existingURL url: URL?, isExternal: Bool = false) {
|
||||
init(existingURL url: URL?, isExternal: Bool = false, isNvme: Bool = false) {
|
||||
self.imageURL = url
|
||||
self.isReadOnly = isExternal
|
||||
self.isExternal = isExternal
|
||||
self.isNvme = isNvme
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
@@ -83,6 +87,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive {
|
||||
isExternal = true
|
||||
}
|
||||
isReadOnly = try container.decodeIfPresent(Bool.self, forKey: .isReadOnly) ?? isExternal
|
||||
isNvme = try container.decodeIfPresent(Bool.self, forKey: .isNvme) ?? false
|
||||
id = try container.decode(String.self, forKey: .identifier)
|
||||
}
|
||||
|
||||
@@ -92,12 +97,18 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive {
|
||||
try container.encodeIfPresent(imageName, forKey: .imageName)
|
||||
}
|
||||
try container.encode(isReadOnly, forKey: .isReadOnly)
|
||||
try container.encode(isNvme, forKey: .isNvme)
|
||||
try container.encode(id, forKey: .identifier)
|
||||
}
|
||||
|
||||
func vzDiskImage() throws -> VZDiskImageStorageDeviceAttachment? {
|
||||
func vzDiskImage(useFsWorkAround: Bool = false) throws -> VZDiskImageStorageDeviceAttachment? {
|
||||
if let imageURL = imageURL {
|
||||
return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly)
|
||||
// Use cached caching mode for virtio drive to prevent fs corruption on linux when possible
|
||||
if #available(macOS 12.0, *), !isNvme, useFsWorkAround {
|
||||
return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly, cachingMode: .cached, synchronizationMode: .full)
|
||||
} else {
|
||||
return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly)
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@@ -107,6 +118,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive {
|
||||
imageName?.hash(into: &hasher)
|
||||
sizeMib.hash(into: &hasher)
|
||||
isReadOnly.hash(into: &hasher)
|
||||
isNvme.hash(into: &hasher)
|
||||
isExternal.hash(into: &hasher)
|
||||
id.hash(into: &hasher)
|
||||
}
|
||||
@@ -127,6 +139,7 @@ extension UTMAppleConfigurationDrive {
|
||||
sizeMib = oldDrive.sizeMib
|
||||
isReadOnly = oldDrive.isReadOnly
|
||||
isExternal = oldDrive.isExternal
|
||||
isNvme = false
|
||||
imageURL = oldDrive.imageURL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +135,7 @@ enum VMBootDevice: Int, Identifiable {
|
||||
@Published var sharingReadOnly: Bool = false
|
||||
@Published var name: String?
|
||||
@Published var isOpenSettingsAfterCreation: Bool = false
|
||||
@Published var useNvmeAsDiskInterface = false
|
||||
|
||||
/// SwiftUI BUG: on macOS 12, when VoiceOver is enabled and isBusy changes the disable state of a button being clicked,
|
||||
var isNeverDisabledWorkaround: Bool {
|
||||
@@ -342,7 +343,11 @@ enum VMBootDevice: Int, Identifiable {
|
||||
}
|
||||
}
|
||||
if !isSkipDiskCreate {
|
||||
config.drives.append(UTMAppleConfigurationDrive(newSize: storageSizeGib * bytesInGib / bytesInMib))
|
||||
var newDisk = UTMAppleConfigurationDrive(newSize: storageSizeGib * bytesInGib / bytesInMib)
|
||||
if #available(macOS 14, *), useNvmeAsDiskInterface {
|
||||
newDisk.isNvme = true
|
||||
}
|
||||
config.drives.append(newDisk)
|
||||
}
|
||||
if #available(macOS 12, *), let sharingDirectoryURL = sharingDirectoryURL {
|
||||
config.sharedDirectories = [UTMAppleConfigurationSharedDirectory(directoryURL: sharingDirectoryURL, isReadOnly: sharingReadOnly)]
|
||||
|
||||
@@ -1141,3 +1141,9 @@
|
||||
|
||||
// UTMQemuMonitor.m
|
||||
"Guest panic" = "ゲストがパニック状態に陥りました";
|
||||
|
||||
/* VMConfigAppleDriveDetailsView
|
||||
VMConfigAppleDriveCreateView*/
|
||||
"Use NVMe Interface" = "NVMe を使用します";
|
||||
"If checked, use NVMe instead of virtio as the disk interface, available on macOS 14+ for Linux guests only. This interface is slower but less likely to encounter filesystem errors." = "チェックされている場合、ディスクインターフェースとして virtio の代わりに NVMe を使用します。macOS 14+ では Linux ゲストのみ利用可能です。このインターフェースは遅いですが、ファイルシステムエラーが発生する可能性が低いです。";
|
||||
|
||||
|
||||
@@ -33,11 +33,17 @@ struct VMConfigAppleDriveCreateView: View {
|
||||
if newValue {
|
||||
config.sizeMib = 0
|
||||
config.isReadOnly = true
|
||||
config.isNvme = false
|
||||
} else {
|
||||
config.sizeMib = 10240
|
||||
config.isReadOnly = false
|
||||
}
|
||||
}
|
||||
if #available(macOS 14, *), !config.isExternal {
|
||||
Toggle(isOn: $config.isNvme.animation(), label: {
|
||||
Text("Use NVMe Interface")
|
||||
}).help("If checked, use NVMe instead of virtio as the disk interface, available on macOS 14+ for Linux guests only. This interface is slower but less likely to encounter filesystem errors.")
|
||||
}
|
||||
if !config.isExternal {
|
||||
SizeTextField($config.sizeMib)
|
||||
}
|
||||
|
||||
@@ -28,6 +28,12 @@ struct VMConfigAppleDriveDetailsView: View {
|
||||
TextField("Name", text: .constant(config.imageURL?.lastPathComponent ?? NSLocalizedString("(New Drive)", comment: "VMConfigAppleDriveDetailsView")))
|
||||
.disabled(true)
|
||||
Toggle("Read Only?", isOn: $config.isReadOnly)
|
||||
if #available(macOS 14, *), !config.isExternal {
|
||||
Toggle(isOn: $config.isNvme,
|
||||
label: {
|
||||
Text("Use NVMe Interface")
|
||||
}).help("If checked, use NVMe instead of virtio as the disk interface, available on macOS 14+ for Linux guests only. This interface is slower but less likely to encounter filesystem errors.")
|
||||
}
|
||||
if #unavailable(macOS 12) {
|
||||
Button {
|
||||
requestDriveDelete = config
|
||||
|
||||
@@ -2297,3 +2297,8 @@
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Zoom" = "縮放";
|
||||
|
||||
/* VMConfigAppleDriveDetailsView
|
||||
VMConfigAppleDriveCreateView*/
|
||||
"Use NVMe Interface" = "使用 NVMe 磁碟介面";
|
||||
"If checked, use NVMe instead of virtio as the disk interface, available on macOS 14+ for Linux guests only. This interface is slower but less likely to encounter filesystem errors." = "如果勾選,將使用 NVMe 而非 virtio 作為磁碟介面,僅在 macOS 14+ 中適用於 Linux 客戶機器。這個介面速度較慢,但較不容易遇到檔案系統錯誤。";
|
||||
|
||||
@@ -2297,3 +2297,8 @@
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Zoom" = "缩放";
|
||||
|
||||
/* VMConfigAppleDriveDetailsView
|
||||
VMConfigAppleDriveCreateView*/
|
||||
"Use NVMe Interface" = "使用 NVMe 磁盘接口";
|
||||
"If checked, use NVMe instead of virtio as the disk interface, available on macOS 14+ for Linux guests only. This interface is slower but less likely to encounter filesystem errors." = "如果选中,使用 NVMe 而不是 virtio 作为磁盘接口,仅适用于 macOS 14+ 上的 Linux 客户机。此接口速度较慢,但不太容易遇到文件系统错误。";
|
||||
|
||||
@@ -2002,3 +2002,8 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Zoom" = "縮放";
|
||||
|
||||
/* VMConfigAppleDriveDetailsView
|
||||
VMConfigAppleDriveCreateView*/
|
||||
"Use NVMe Interface" = "使用 NVMe 磁碟介面";
|
||||
"If checked, use NVMe instead of virtio as the disk interface, available on macOS 14+ for Linux guests only. This interface is slower but less likely to encounter filesystem errors." = "如果選取,將使用 NVMe 而非 virtio 作為磁碟介面,僅在 macOS 14+ 中適用於 Linux 客戶機器。這個介面速度較慢,但較不容易遇到檔案系統錯誤。";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user