@@ -50,6 +50,15 @@ extension EXT4.Formatter {
5050 guard blocks >= EXT4 . MinJournalBlocks else {
5151 throw EXT4 . Formatter. Error. journalTooSmall ( size)
5252 }
53+ // A journal larger than half the filesystem is unlikely to be useful. In
54+ // writeback or ordered mode only metadata is journaled, so even the 1 GiB
55+ // default ceiling is generous. Only data=journal mode journals data blocks
56+ // too, and even then sizing beyond half the filesystem would be wasteful.
57+ // This is a policy limit, not a kernel hard limit; exceeding it would not
58+ // cause a mount failure.
59+ // Note: totalBlocks derives from minDiskSize; close() may expand the filesystem
60+ // slightly for block group alignment. The check is conservative — the final
61+ // filesystem can only be larger, so this guard never permits an oversized journal.
5362 guard blocks <= UInt64 ( totalBlocks) / 2 else {
5463 throw EXT4 . Formatter. Error. journalTooLarge ( size)
5564 }
@@ -61,9 +70,17 @@ extension EXT4.Formatter {
6170 // and 1 GiB for larger filesystems. The larger ceiling was introduced in e2fsprogs 1.43.2:
6271 // https://e2fsprogs.sourceforge.net/e2fsprogs-release.html#1.43.2
6372 let fsBytes = UInt64 ( totalBlocks) * UInt64( self . blockSize)
64- let scaledBytes = fsBytes / 64 // 1/64th of the filesystem, matching e2fsprogs defaults
73+ let halfFsBytes = fsBytes / 2
6574 let minBytes : UInt64 = UInt64 ( EXT4 . MinJournalBlocks) * UInt64( self . blockSize)
66- let maxBytes : UInt64 = fsBytes > 128 . gib ( ) ? 1 . gib ( ) : 128 . mib ( )
75+ // Note: totalBlocks derives from minDiskSize; close() may expand the filesystem
76+ // substantially if minDiskSize is small relative to content. This check is
77+ // conservative — the final filesystem can only be larger, so false positives
78+ // (rejecting a journal that would have fit) are possible but false negatives are not.
79+ guard minBytes <= halfFsBytes else {
80+ throw EXT4 . Formatter. Error. filesystemTooSmallForJournal
81+ }
82+ let scaledBytes = fsBytes / 64 // 1/64th of the filesystem, matching e2fsprogs defaults
83+ let maxBytes : UInt64 = min ( fsBytes > 128 . gib ( ) ? 1 . gib ( ) : 128 . mib ( ) , halfFsBytes)
6784 let clampedBytes = min ( max ( scaledBytes, minBytes) , maxBytes)
6885 // Safe: clampedBytes ≤ 1 GiB and blockSize ≥ 1, so the quotient fits in UInt32.
6986 return UInt32 ( clampedBytes / UInt64( self . blockSize) )
0 commit comments