Skip to content

Commit 8c53f4d

Browse files
authored
Restore a configurable block size in the EXT4 formatter (apple#679)
Restores a configurable block size in the EXT4 formatter. apple#662 resolved a conflict between the hardcoded log block size and a user-provided block size, but removed the later. This PR restores the configurable block size without creating the conflict.
1 parent ceee3a6 commit 8c53f4d

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

Sources/ContainerizationEXT4/EXT4+Formatter.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ extension EXT4 {
2525
/// The `EXT4.Formatter` class provides methods to format a block device with the ext4 filesystem.
2626
/// It allows customization of block size and maximum disk size.
2727
public class Formatter {
28-
private let logBlockSize: UInt32 = 2
28+
private let logBlockSize: UInt32
2929
var blockSize: UInt32 { 1024 << logBlockSize }
3030
private var size: UInt64
3131
private let groupDescriptorSize: UInt32 = 32
@@ -62,6 +62,8 @@ extension EXT4 {
6262
///
6363
/// - Parameters:
6464
/// - devicePath: The path to the block device where the ext4 filesystem will be created.
65+
/// - blockSize: The filesystem block size in bytes. Must be a power of two in the set
66+
/// {1024, 2048, 4096}. Defaults to 4096.
6567
/// - minDiskSize: The minimum disk size required for the formatted filesystem.
6668
///
6769
/// - Note: This ext4 formatter is designed for creating block devices out of container images and does not support all the
@@ -70,7 +72,7 @@ extension EXT4 {
7072
///
7173
/// - Important: Ensure that the destination block device is accessible and has sufficient permissions
7274
/// for formatting. The formatting process will erase all existing data on the device.
73-
public init(_ devicePath: FilePath, minDiskSize: UInt64 = 256.kib()) throws {
75+
public init(_ devicePath: FilePath, blockSize: UInt32 = 4096, minDiskSize: UInt64 = 256.kib()) throws {
7476
/// The constructor performs the following steps:
7577
///
7678
/// 1. Creates the first 10 inodes:
@@ -88,6 +90,10 @@ extension EXT4 {
8890
/// 5. Creates a "/lost+found" directory to satisfy the requirements of e2fsck (ext2/3/4 filesystem
8991
/// checker).
9092

93+
guard blockSize >= 1024 && blockSize <= 4096 && blockSize.nonzeroBitCount == 1 else {
94+
throw Error.invalidBlockSize(blockSize)
95+
}
96+
self.logBlockSize = UInt32(blockSize.trailingZeroBitCount) - 10
9197
if !FileManager.default.fileExists(atPath: devicePath.description) {
9298
_ = FileManager.default.createFile(atPath: devicePath.description, contents: nil)
9399
}
@@ -1226,6 +1232,7 @@ extension EXT4 {
12261232
case cannotTruncateFile(_ path: FilePath)
12271233
case cannotCreateSparseFile(_ path: FilePath)
12281234
case cannotResizeFS(_ size: UInt64)
1235+
case invalidBlockSize(_ size: UInt32)
12291236
public var description: String {
12301237
switch self {
12311238
case .notDirectory(let path):
@@ -1258,6 +1265,8 @@ extension EXT4 {
12581265
return "cannot create sparse file at \(path)"
12591266
case .cannotResizeFS(let size):
12601267
return "cannot resize fs to \(size) bytes"
1268+
case .invalidBlockSize(let size):
1269+
return "invalid block size \(size): must be 1024, 2048, or 4096"
12611270
}
12621271
}
12631272
}

0 commit comments

Comments
 (0)