From 83d04219c247ea56c6581ec8aa25f3b76794600a Mon Sep 17 00:00:00 2001 From: osy <50960678+osy@users.noreply.github.com> Date: Fri, 27 Oct 2023 20:57:10 -0700 Subject: [PATCH 1/8] Revert "github: disable visionOS and build on Xcode 15.0" This reverts commit ab90be1a36c13f2c460d8dd25b88ec4490876665. --- .github/workflows/build.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8bb161b49..a4ee0ba18 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ on: default: 'false' env: - BUILD_XCODE_PATH: /Applications/Xcode_15.0.app + BUILD_XCODE_PATH: /Applications/Xcode_15.1.app RUNNER_IMAGE: macos-13 jobs: @@ -53,7 +53,7 @@ jobs: strategy: matrix: arch: [arm64] - platform: [ios, ios_simulator, ios-tci, macos] + platform: [ios, ios_simulator, ios-tci, macos, visionos, visionos_simulator, visionos-tci] include: # x86_64 supported only for macOS and simulators - arch: x86_64 @@ -153,7 +153,7 @@ jobs: strategy: matrix: arch: [arm64] - platform: [ios, ios_simulator, ios-tci, macos] + platform: [ios, ios_simulator, ios-tci, macos, visionos, visionos_simulator, visionos-tci] include: # x86_64 supported only for macOS and simulators - arch: x86_64 @@ -235,6 +235,8 @@ jobs: {platform: "ios-tci", mode: "ipa-se", name: "UTM-SE.ipa", path: "UTM SE.ipa"}, {platform: "ios", mode: "ipa-hv", name: "UTM-HV.ipa", path: "UTM.ipa"}, {platform: "ios", mode: "deb", name: "UTM.deb", path: "UTM.deb"}, + {platform: "visionos", mode: "ipa", name: "UTM-visionOS.ipa", path: "UTM.ipa"}, + {platform: "visionos-tci", mode: "ipa-se", name: "UTM-SE-visionOS.ipa", path: "UTM SE.ipa"} ] if: github.event_name == 'release' || github.event.inputs.test_release == 'true' steps: From d74131e585f00097b5f3c7d48861a73ec6fdfa92 Mon Sep 17 00:00:00 2001 From: osy <50960678+osy@users.noreply.github.com> Date: Fri, 27 Oct 2023 16:58:50 -0700 Subject: [PATCH 2/8] toolbar(visionOS): move toolbar to top of window --- .../visionOS/VMToolbarOrnamentModifier.swift | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/Platform/visionOS/VMToolbarOrnamentModifier.swift b/Platform/visionOS/VMToolbarOrnamentModifier.swift index b332e9ede..1831e642d 100644 --- a/Platform/visionOS/VMToolbarOrnamentModifier.swift +++ b/Platform/visionOS/VMToolbarOrnamentModifier.swift @@ -21,8 +21,8 @@ struct VMToolbarOrnamentModifier: ViewModifier { @EnvironmentObject private var session: VMSessionState func body(content: Content) -> some View { - content.toolbar { - ToolbarItem(placement: .bottomOrnament) { + content.ornament(attachmentAnchor: .scene(.top)) { + HStack { Button { if session.vm.state == .started { state.alert = .powerDown @@ -33,28 +33,20 @@ struct VMToolbarOrnamentModifier: ViewModifier { Label(state.isRunning ? "Power Off" : "Quit", systemImage: state.isRunning ? "power" : "xmark") } .disabled(state.isBusy) - } - ToolbarItem(placement: .bottomOrnament) { Button { session.pauseResume() } label: { Label(state.isRunning ? "Pause" : "Play", systemImage: state.isRunning ? "pause" : "play") } .disabled(state.isBusy) - } - ToolbarItem(placement: .bottomOrnament) { Button { state.alert = .restart } label: { Label("Restart", systemImage: "restart") } .disabled(state.isBusy) - } - ToolbarItem(placement: .bottomOrnament) { Divider() - } - if case .serial(_, _) = state.device { - ToolbarItem(placement: .bottomOrnament) { + if case .serial(_, _) = state.device { Button { let template = session.qemuConfig.serials[state.device!.configIndex].terminal?.resizeCommand state.toggleDisplayResize(command: template) @@ -63,24 +55,16 @@ struct VMToolbarOrnamentModifier: ViewModifier { } .disabled(state.isBusy) } - } - #if !WITH_QEMU_TCI - ToolbarItem(placement: .bottomOrnament) { + #if !WITH_QEMU_TCI if session.vm.hasUsbRedirection { VMToolbarUSBMenuView() .disabled(state.isBusy) } - } - #endif - ToolbarItem(placement: .bottomOrnament) { + #endif VMToolbarDriveMenuView(config: session.qemuConfig) .disabled(state.isBusy) - } - ToolbarItem(placement: .bottomOrnament) { VMToolbarDisplayMenuView(state: $state) .disabled(state.isBusy) - } - ToolbarItem(placement: .bottomOrnament) { Button { state.isKeyboardRequested = true } label: { @@ -88,6 +72,12 @@ struct VMToolbarOrnamentModifier: ViewModifier { } .disabled(state.isBusy) } + // the following was suggested by Apple via Feedback to look close to .toolbar() with .bottomOrnament + .buttonBorderShape(.capsule) + .buttonStyle(.borderless) + .labelStyle(.iconOnly) + .padding(12) + .glassBackgroundEffect() } } } From 9db60765236a4cd11109f8adf3c53ef233c1a791 Mon Sep 17 00:00:00 2001 From: osy <50960678+osy@users.noreply.github.com> Date: Fri, 27 Oct 2023 20:57:00 -0700 Subject: [PATCH 3/8] toolbar(visionOS): support hiding toolbar --- .../visionOS/VMToolbarOrnamentModifier.swift | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Platform/visionOS/VMToolbarOrnamentModifier.swift b/Platform/visionOS/VMToolbarOrnamentModifier.swift index 1831e642d..bc058a9de 100644 --- a/Platform/visionOS/VMToolbarOrnamentModifier.swift +++ b/Platform/visionOS/VMToolbarOrnamentModifier.swift @@ -19,9 +19,10 @@ import SwiftUI struct VMToolbarOrnamentModifier: ViewModifier { @Binding var state: VMWindowState @EnvironmentObject private var session: VMSessionState - + @AppStorage("ToolbarIsCollapsed") private var isCollapsed: Bool = false + func body(content: Content) -> some View { - content.ornament(attachmentAnchor: .scene(.top)) { + content.ornament(visibility: isCollapsed ? .hidden : .visible, attachmentAnchor: .scene(.top)) { HStack { Button { if session.vm.state == .started { @@ -71,13 +72,34 @@ struct VMToolbarOrnamentModifier: ViewModifier { Label("Keyboard", systemImage: "keyboard") } .disabled(state.isBusy) + Divider() + Button { + isCollapsed = true + } label: { + Label("Hide Controls", systemImage: "chevron.right") + } } - // the following was suggested by Apple via Feedback to look close to .toolbar() with .bottomOrnament + .modifier(ToolbarOrnamentViewModifier()) + } + .ornament(visibility: isCollapsed ? .visible : .hidden, attachmentAnchor: .scene(.topTrailing)) { + Button { + isCollapsed = false + } label: { + Label("Show Controls", systemImage: "chevron.left") + } + .modifier(ToolbarOrnamentViewModifier()) + } + } +} + +// the following was suggested by Apple via Feedback to look close to .toolbar() with .bottomOrnament +private struct ToolbarOrnamentViewModifier: ViewModifier { + func body(content: Content) -> some View { + content .buttonBorderShape(.capsule) .buttonStyle(.borderless) .labelStyle(.iconOnly) .padding(12) .glassBackgroundEffect() - } } } From 917f35759d9efafade6775adfef57389cbab4e29 Mon Sep 17 00:00:00 2001 From: osy <50960678+osy@users.noreply.github.com> Date: Sun, 29 Oct 2023 13:41:28 -0700 Subject: [PATCH 4/8] build: update ANGLE --- patches/sources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/sources b/patches/sources index 5447a6b33..123dd9c08 100644 --- a/patches/sources +++ b/patches/sources @@ -37,7 +37,7 @@ SPICE_CLIENT_SRC="https://www.spice-space.org/download/gtk/spice-gtk-0.40.tar.xz # Source files for GPU acceleration WEBKIT_REPO="https://github.com/utmapp/WebKit.git" -WEBKIT_COMMIT="59f88f623d5547039760848f188ac961b6cc85e2" +WEBKIT_COMMIT="9ce1f852e15f6f322cee0ce727c8fd73657705c9" WEBKIT_SUBDIRS="Source/ThirdParty/ANGLE Configurations Tools/ccache" EPOXY_REPO="https://github.com/utmapp/libepoxy.git" EPOXY_COMMIT="266d2290a437c655f7419e85af06bfbb73a720c4" From dacf074c8766cf655d05c4027c0f2f13d8956cb6 Mon Sep 17 00:00:00 2001 From: osy <50960678+osy@users.noreply.github.com> Date: Mon, 30 Oct 2023 20:02:20 -0700 Subject: [PATCH 5/8] vm(qemu): do not try to eject drives on non-disk interfaces Fixes #5845 --- Services/UTMQemuVirtualMachine.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Services/UTMQemuVirtualMachine.swift b/Services/UTMQemuVirtualMachine.swift index 2826ca278..c162e6a76 100644 --- a/Services/UTMQemuVirtualMachine.swift +++ b/Services/UTMQemuVirtualMachine.swift @@ -748,7 +748,7 @@ extension UTMQemuVirtualMachine { // an image bookmark was saved while QEMU was NOT running let url = try URL(resolvingPersistentBookmarkData: localBookmark) try await changeMedium(drive, to: url, isAccessOnly: !isMounting) - } else if isMounting { + } else if isMounting && (drive.imageType == .cd || drive.imageType == .disk) { // a placeholder image might have been mounted try await eject(drive) } From 3d5019ab4d6105148c3edaccf053685ed72633c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=98=E9=BB=98?= Date: Mon, 6 Nov 2023 14:02:31 +0800 Subject: [PATCH 6/8] fix linux virtual machine (ubuntu 23.10.1) report error " EXT4-fs error (device vda2): ext4_validate_block_bitmap:421: comm kworker/u20:0 bg 2230: bad block bitmap checksum EXT4-fs (vda2): Delayed block allocation failed for inode 14327754 at logical offset 0 with max blocks 47 with error 74 EXT4-fs (vda2): THis should not happen!! Data will be lost " the reason is virtual machine disk image is created as sparse file truncate command make a sparse file, the space will not alloc before really used this should be better at most time. but maybe not suitable for virtual machines, especially in the case of heavy IO loads this may give extra time delay and operational interruptions when system do really space alloc this behavior may cause later write completed before previous write the incorrect write order may cause file system corrputed --- .../Legacy/UTMLegacyAppleConfiguration.swift | 4 +++ .../UTMAppleConfigurationDrive.swift | 15 +++++++++ Configuration/UTMConfigurationDrive.swift | 31 +++++++++++++++++-- Configuration/UTMQemuConfigurationDrive.swift | 7 +++++ Platform/Shared/VMWizardDrivesView.swift | 12 ++++++- Platform/Shared/VMWizardState.swift | 8 ++++- .../macOS/VMConfigAppleDriveCreateView.swift | 11 +++++++ Platform/zh-Hans.lproj/Localizable.strings | 2 ++ 8 files changed, 85 insertions(+), 5 deletions(-) diff --git a/Configuration/Legacy/UTMLegacyAppleConfiguration.swift b/Configuration/Legacy/UTMLegacyAppleConfiguration.swift index c5570dbda..4d331bfcd 100644 --- a/Configuration/Legacy/UTMLegacyAppleConfiguration.swift +++ b/Configuration/Legacy/UTMLegacyAppleConfiguration.swift @@ -313,6 +313,7 @@ struct DiskImage: Codable, Hashable, Identifiable { var sizeMib: Int var isReadOnly: Bool + var isSparse: Bool var isExternal: Bool var imageURL: URL? private var uuid = UUID() // for identifiable @@ -320,6 +321,7 @@ struct DiskImage: Codable, Hashable, Identifiable { private enum CodingKeys: String, CodingKey { case sizeMib case isReadOnly + case isSparse case isExternal case imagePath case imageBookmark @@ -344,6 +346,7 @@ struct DiskImage: Codable, Hashable, Identifiable { let container = try decoder.container(keyedBy: CodingKeys.self) sizeMib = try container.decode(Int.self, forKey: .sizeMib) isReadOnly = try container.decode(Bool.self, forKey: .isReadOnly) + isSparse = try container.decode(Bool.self, forKey: .isSparse) isExternal = try container.decode(Bool.self, forKey: .isExternal) if !isExternal, let imagePath = try container.decodeIfPresent(String.self, forKey: .imagePath) { imageURL = dataURL.appendingPathComponent(imagePath) @@ -357,6 +360,7 @@ struct DiskImage: Codable, Hashable, Identifiable { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(sizeMib, forKey: .sizeMib) try container.encode(isReadOnly, forKey: .isReadOnly) + try container.encode(isSparse, forKey: .isSparse) try container.encode(isExternal, forKey: .isExternal) if !isExternal { try container.encodeIfPresent(imageURL?.lastPathComponent, forKey: .imagePath) diff --git a/Configuration/UTMAppleConfigurationDrive.swift b/Configuration/UTMAppleConfigurationDrive.swift index ef53dbbf6..d3bc6c952 100644 --- a/Configuration/UTMAppleConfigurationDrive.swift +++ b/Configuration/UTMAppleConfigurationDrive.swift @@ -24,6 +24,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive { var sizeMib: Int = 0 var isReadOnly: Bool + var isSparse: Bool var isExternal: Bool var imageURL: URL? var imageName: String? @@ -36,6 +37,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive { private enum CodingKeys: String, CodingKey { case isReadOnly = "ReadOnly" + case isSparse = "Sparse" case imageName = "ImageName" case bookmark = "Bookmark" // legacy only case identifier = "Identifier" @@ -54,13 +56,22 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive { init(newSize: Int) { sizeMib = newSize isReadOnly = false + isSparse = true isExternal = false } + init(newSize: Int, isSparse: Bool = true) { + sizeMib = newSize + isReadOnly = false + isExternal = false + self.isSparse = isSparse + } + init(existingURL url: URL?, isExternal: Bool = false) { self.imageURL = url self.isReadOnly = isExternal self.isExternal = isExternal + self.isSparse = true } init(from decoder: Decoder) throws { @@ -83,6 +94,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive { isExternal = true } isReadOnly = try container.decodeIfPresent(Bool.self, forKey: .isReadOnly) ?? isExternal + isSparse = try container.decodeIfPresent(Bool.self, forKey: .isSparse) ?? true id = try container.decode(String.self, forKey: .identifier) } @@ -92,6 +104,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive { try container.encodeIfPresent(imageName, forKey: .imageName) } try container.encode(isReadOnly, forKey: .isReadOnly) + try container.encode(isSparse, forKey: .isSparse) try container.encode(id, forKey: .identifier) } @@ -107,6 +120,7 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive { imageName?.hash(into: &hasher) sizeMib.hash(into: &hasher) isReadOnly.hash(into: &hasher) + isSparse.hash(into: &hasher) isExternal.hash(into: &hasher) id.hash(into: &hasher) } @@ -126,6 +140,7 @@ extension UTMAppleConfigurationDrive { init(migrating oldDrive: DiskImage) { sizeMib = oldDrive.sizeMib isReadOnly = oldDrive.isReadOnly + isSparse = oldDrive.isSparse isExternal = oldDrive.isExternal imageURL = oldDrive.imageURL } diff --git a/Configuration/UTMConfigurationDrive.swift b/Configuration/UTMConfigurationDrive.swift index 61103ac98..4c611b87e 100644 --- a/Configuration/UTMConfigurationDrive.swift +++ b/Configuration/UTMConfigurationDrive.swift @@ -28,6 +28,9 @@ protocol UTMConfigurationDrive: Codable, Hashable, Identifiable { /// If true, the drive image will be mounted as read-only. var isReadOnly: Bool { get } + /// If true, the drive image is sparse file. + var isSparse: Bool { get } + /// If true, a bookmark is stored in the package. var isExternal: Bool { get } @@ -77,7 +80,7 @@ extension UTMConfigurationDrive { throw UTMConfigurationError.driveAlreadyExists(newURL) } if isRawImage { - try await createRawImage(at: newURL, size: sizeMib) + try await createRawImage(at: newURL, size: sizeMib, sparse: isSparse) } else { try await createQcow2Image(at: newURL, size: sizeMib) } @@ -90,14 +93,36 @@ extension UTMConfigurationDrive { } } - private func createRawImage(at newURL: URL, size sizeMib: Int) async throws { + private func createRawImage(at newURL: URL, size sizeMib: Int, sparse isSparse: Bool) async throws { let size = UInt64(sizeMib) * bytesInMib try await Task.detached { guard FileManager.default.createFile(atPath: newURL.path, contents: nil, attributes: nil) else { throw UTMConfigurationError.cannotCreateDiskImage } let handle = try FileHandle(forWritingTo: newURL) - try handle.truncate(atOffset: size) + if(isSparse) { + /* truncate command make a sparse file, the space will not alloc before really used + * this should be better at most time. + * but maybe not suitable for virtual machines, especially in the case of heavy IO loads + * this may give extra time delay and operational interruptions when system do really space alloc + * this behavior may cause later write completed before previous write + * the incorrect write order may cause file system corrputed + */ + try handle.truncate(atOffset: size) + } else { + var val = 0 + let scale = 100; // write large block will be faster, but too large may cause OOM + let data = NSMutableData(length: NSNumber(value: bytesInMib).intValue * scale) // 100MB + while val < (sizeMib / scale) { + try handle.write(contentsOf: data!) + val += 1; + } + val = sizeMib % scale + if(val > 0) { + val = val * NSNumber(value: bytesInMib).intValue + try handle.write(contentsOf: data!.subdata(with: NSRange(location: 0, length: val))) + } + } try handle.close() }.value } diff --git a/Configuration/UTMQemuConfigurationDrive.swift b/Configuration/UTMQemuConfigurationDrive.swift index 3c0dea901..fea8f11da 100644 --- a/Configuration/UTMQemuConfigurationDrive.swift +++ b/Configuration/UTMQemuConfigurationDrive.swift @@ -29,6 +29,9 @@ struct UTMQemuConfigurationDrive: UTMConfigurationDrive { /// If true, the drive image will be mounted as read-only. var isReadOnly: Bool = false + /// If true, the drive image is sparse file. + var isSparse: Bool = true + /// If true, a bookmark is stored in the package. var isExternal: Bool = false @@ -60,6 +63,7 @@ struct UTMQemuConfigurationDrive: UTMConfigurationDrive { case interfaceVersion = "InterfaceVersion" case identifier = "Identifier" case isReadOnly = "ReadOnly" + case isSparse = "Sparse" } init() { @@ -78,6 +82,7 @@ struct UTMQemuConfigurationDrive: UTMConfigurationDrive { isExternal = true } isReadOnly = try values.decodeIfPresent(Bool.self, forKey: .isReadOnly) ?? isExternal + isSparse = try values.decodeIfPresent(Bool.self, forKey: .isSparse) ?? true imageType = try values.decode(QEMUDriveImageType.self, forKey: .imageType) interface = try values.decode(QEMUDriveInterface.self, forKey: .interface) interfaceVersion = try values.decodeIfPresent(Int.self, forKey: .interfaceVersion) ?? 0 @@ -90,6 +95,7 @@ struct UTMQemuConfigurationDrive: UTMConfigurationDrive { try container.encodeIfPresent(imageURL?.lastPathComponent, forKey: .imageName) } try container.encode(isReadOnly, forKey: .isReadOnly) + try container.encode(isSparse, forKey: .isSparse) try container.encode(imageType, forKey: .imageType) if imageType == .cd || imageType == .disk { try container.encode(interface, forKey: .interface) @@ -104,6 +110,7 @@ struct UTMQemuConfigurationDrive: UTMConfigurationDrive { imageName?.hash(into: &hasher) sizeMib.hash(into: &hasher) isReadOnly.hash(into: &hasher) + isSparse.hash(into: &hasher) isExternal.hash(into: &hasher) id.hash(into: &hasher) imageType.hash(into: &hasher) diff --git a/Platform/Shared/VMWizardDrivesView.swift b/Platform/Shared/VMWizardDrivesView.swift index 28782c2e7..31c11a230 100644 --- a/Platform/Shared/VMWizardDrivesView.swift +++ b/Platform/Shared/VMWizardDrivesView.swift @@ -18,7 +18,14 @@ import SwiftUI struct VMWizardDrivesView: View { @ObservedObject var wizardState: VMWizardState - + var allocNow: Binding { + return Binding(get: { + return wizardState.allocateAllDiskSpaceNow + }, set: { newValue in + wizardState.allocateAllDiskSpaceNow = newValue + }) + } + var body: some View { VMWizardContent("Storage") { Section { @@ -34,6 +41,9 @@ struct VMWizardDrivesView: View { .frame(maxWidth: 50) Text("GB") } + Toggle(isOn: allocNow, label: { + Text("Allocate all disk space now") + }).help("If checked, allocate all disk space immediately rather than allow the disk space to gradually grow to the maximum amount.") } header: { Text("Size") } diff --git a/Platform/Shared/VMWizardState.swift b/Platform/Shared/VMWizardState.swift index 893811bd3..9d6e3293d 100644 --- a/Platform/Shared/VMWizardState.swift +++ b/Platform/Shared/VMWizardState.swift @@ -109,6 +109,8 @@ enum VMWizardOS: String, Identifiable { @Published var systemMemoryMib: Int = 512 @Published var storageSizeGib: Int = 8 #endif + @Published var allocateAllDiskSpaceNow = false + @Published var systemCpuCount: Int = 0 @Published var isGLEnabled: Bool = false @Published var sharingDirectoryURL: URL? @@ -231,6 +233,10 @@ enum VMWizardOS: String, Identifiable { } } } + // for AppleVirtualization set allocateAllDiskSpaceNow true + if useAppleVirtualization && nextPage == .drives { + allocateAllDiskSpaceNow = true; + } case .drives: nextPage = .sharing if useAppleVirtualization { @@ -311,7 +317,7 @@ enum VMWizardOS: String, Identifiable { } } if !isSkipDiskCreate { - config.drives.append(UTMAppleConfigurationDrive(newSize: storageSizeGib * bytesInGib / bytesInMib)) + config.drives.append(UTMAppleConfigurationDrive(newSize: storageSizeGib * bytesInGib / bytesInMib, isSparse: !allocateAllDiskSpaceNow)) } if #available(macOS 12, *), let sharingDirectoryURL = sharingDirectoryURL { config.sharedDirectories = [UTMAppleConfigurationSharedDirectory(directoryURL: sharingDirectoryURL, isReadOnly: sharingReadOnly)] diff --git a/Platform/macOS/VMConfigAppleDriveCreateView.swift b/Platform/macOS/VMConfigAppleDriveCreateView.swift index 5d5244c74..032cd3e84 100644 --- a/Platform/macOS/VMConfigAppleDriveCreateView.swift +++ b/Platform/macOS/VMConfigAppleDriveCreateView.swift @@ -22,13 +22,24 @@ struct VMConfigAppleDriveCreateView: View { @Binding var config: UTMAppleConfigurationDrive @State private var isGiB: Bool = true + var allocNow: Binding { + return Binding(get: { + return !config.isSparse + }, set: { newValue in + config.isSparse = !newValue + }) + } var body: some View { + Form { VStack { Toggle(isOn: $config.isExternal.animation(), label: { Text("Removable") }).help("If checked, the drive image will be stored with the VM.") + Toggle(isOn: allocNow, label: { + Text("Allocate all disk space now") + }).help("If checked, allocate all disk space immediately rather than allow the disk space to gradually grow to the maximum amount.") .onChange(of: config.isExternal) { newValue in if newValue { config.sizeMib = 0 diff --git a/Platform/zh-Hans.lproj/Localizable.strings b/Platform/zh-Hans.lproj/Localizable.strings index 85c2e7145..b577e9cac 100644 --- a/Platform/zh-Hans.lproj/Localizable.strings +++ b/Platform/zh-Hans.lproj/Localizable.strings @@ -779,6 +779,8 @@ /* VMRemovableDrivesView */ "Removable" = "可移除"; +"Allocate all disk space now" = "立即分配所有磁盘空间"; +"If checked, allocate all disk space immediately rather than allow the disk space to gradually grow to the maximum amount." = "立即分配所有磁盘空间,而不是允许磁盘空间逐渐增长到最大。"; /* No comment provided by engineer. */ "Removable Drive" = "可移除驱动器"; From e922f43a5619125eaebb38b55af0c8631c800aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=98=E9=BB=98?= Date: Thu, 23 Nov 2023 12:15:10 +0800 Subject: [PATCH 7/8] virtual disk cache mode have bugs,when it is enabled or set to auto (default value),may cause linux file system corrputed, especially in the case of heavy IO loads --- Configuration/UTMAppleConfigurationDrive.swift | 11 ++++++++++- Platform/Shared/VMWizardState.swift | 4 ---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Configuration/UTMAppleConfigurationDrive.swift b/Configuration/UTMAppleConfigurationDrive.swift index d3bc6c952..004ec06c5 100644 --- a/Configuration/UTMAppleConfigurationDrive.swift +++ b/Configuration/UTMAppleConfigurationDrive.swift @@ -110,7 +110,16 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive { func vzDiskImage() throws -> VZDiskImageStorageDeviceAttachment? { if let imageURL = imageURL { - return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly) + if #available(macOS 12, *) { + /* + * virtual disk cache mode have bugs, + * when it is enabled or set to auto (default value) + * may cause linux file system corrputed, especially in the case of heavy IO loads + */ + return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly, cachingMode:VZDiskImageCachingMode.uncached, synchronizationMode: VZDiskImageSynchronizationMode.full) + } else { + return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly) + } } else { return nil } diff --git a/Platform/Shared/VMWizardState.swift b/Platform/Shared/VMWizardState.swift index 6037dfed2..380c0e4a7 100644 --- a/Platform/Shared/VMWizardState.swift +++ b/Platform/Shared/VMWizardState.swift @@ -247,10 +247,6 @@ enum VMWizardOS: String, Identifiable { } } } - // for AppleVirtualization set allocateAllDiskSpaceNow true - if useAppleVirtualization && nextPage == .drives { - allocateAllDiskSpaceNow = true; - } case .drives: nextPage = .sharing if useAppleVirtualization { From b2d62e6ef263983f2c255e219b788f7799c6ffe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=98=E9=BB=98?= Date: Tue, 5 Dec 2023 14:11:52 +0800 Subject: [PATCH 8/8] set cache model enabled --- Configuration/UTMAppleConfigurationDrive.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Configuration/UTMAppleConfigurationDrive.swift b/Configuration/UTMAppleConfigurationDrive.swift index 004ec06c5..e9b070bd2 100644 --- a/Configuration/UTMAppleConfigurationDrive.swift +++ b/Configuration/UTMAppleConfigurationDrive.swift @@ -113,10 +113,10 @@ struct UTMAppleConfigurationDrive: UTMConfigurationDrive { if #available(macOS 12, *) { /* * virtual disk cache mode have bugs, - * when it is enabled or set to auto (default value) + * when it is disabled or set to auto (default value) * may cause linux file system corrputed, especially in the case of heavy IO loads */ - return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly, cachingMode:VZDiskImageCachingMode.uncached, synchronizationMode: VZDiskImageSynchronizationMode.full) + return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly, cachingMode:VZDiskImageCachingMode.cached, synchronizationMode: VZDiskImageSynchronizationMode.full) } else { return try VZDiskImageStorageDeviceAttachment(url: imageURL, readOnly: isReadOnly) }