diff --git a/Sources/Containerization/ContainerManager.swift b/Sources/Containerization/ContainerManager.swift index 27e9fbe47..abd84e492 100644 --- a/Sources/Containerization/ContainerManager.swift +++ b/Sources/Containerization/ContainerManager.swift @@ -350,7 +350,7 @@ public struct ContainerManager: Sendable { format: "ext4", source: destination.absolutePath(), destination: "/", - options: [] + options: ["discard"] ) } throw err @@ -364,11 +364,14 @@ public struct ContainerManager: Sendable { } let filesystem = try EXT4.Formatter(FilePath(path), minDiskSize: size) try filesystem.close() + // The filesystem lives in a sparse file that only gives freed blocks + // back to the host when the guest discards them, so the mount asks + // for continuous discard from birth. return .block( format: "ext4", source: path, destination: "/", - options: [] + options: ["discard"] ) } } diff --git a/Sources/Containerization/Image/Unpacker/EXT4Unpacker.swift b/Sources/Containerization/Image/Unpacker/EXT4Unpacker.swift index f69449625..3bfc13ce8 100644 --- a/Sources/Containerization/Image/Unpacker/EXT4Unpacker.swift +++ b/Sources/Containerization/Image/Unpacker/EXT4Unpacker.swift @@ -139,11 +139,15 @@ public struct EXT4Unpacker: Unpacker { try await filesystem.unpack(reader: reader, progress: progress) } + // The filesystem lives in a sparse file that only gives freed blocks + // back to the host when the guest discards them, so the mount asks for + // continuous discard from birth. A read-only mount of it parses the + // option and leaves it idle. return .block( format: "ext4", source: cleanedPath, destination: "/", - options: [] + options: ["discard"] ) }