From: "Stephen C. Tweedie" As discussed before, we can overflow i_blocks in ext2/ext3 inodes by growing a file up to 2TB. That gives us 2^32 sectors of data in the file; but once you add on the indirect tree and possible EA/ACL metadata, i_blocks will wrap beyond 2^32. Consensus seemed to be that the best way to avoid this was simply to stop files getting so large that this was a problem in the first place; anything else would lead to complications if a sparse file tried to overflow that 2^32 sector limit while filling in holes. I wrote a small program to calculate the total indirect tree overhead for any given file size, and 0x1ff7fffe000 turned out to be the largest file we can get without the total i_blocks overflowing 2^32. But in testing, that *just* wrapped --- we need to limit the file to be one page smaller than that to deal with the possibility of an EA/ACL block being accounted against i_blocks. So this patch has been tested, at least on ext3, by letting a file grow densely to its maximum size permitted by the kernel; at 0x1ff7fffe000, stat shows the file to have wrapped back exactly to 0 st_blocks, but with the limit at 0x1ff7fffd000, du shows it occupying the expected 2TB-blocksize bytes. Signed-off-by: Stephen Tweedie Signed-off-by: Andrew Morton --- 25-akpm/fs/ext2/super.c | 10 ++++++++-- 25-akpm/fs/ext3/super.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff -puN fs/ext2/super.c~ext2-3-file-limits-to-avoid-overflowing-i_blocks fs/ext2/super.c --- 25/fs/ext2/super.c~ext2-3-file-limits-to-avoid-overflowing-i_blocks 2005-03-18 00:12:07.000000000 -0800 +++ 25-akpm/fs/ext2/super.c 2005-03-18 00:12:07.000000000 -0800 @@ -518,12 +518,18 @@ static int ext2_check_descriptors (struc static loff_t ext2_max_size(int bits) { loff_t res = EXT2_NDIR_BLOCKS; + /* This constant is calculated to be the largest file size for a + * dense, 4k-blocksize file such that the total number of + * sectors in the file, including data and all indirect blocks, + * does not exceed 2^32. */ + const loff_t upper_limit = 0x1ff7fffd000LL; + res += 1LL << (bits-2); res += 1LL << (2*(bits-2)); res += 1LL << (3*(bits-2)); res <<= bits; - if (res > (512LL << 32) - (1 << bits)) - res = (512LL << 32) - (1 << bits); + if (res > upper_limit) + res = upper_limit; return res; } diff -puN fs/ext3/super.c~ext2-3-file-limits-to-avoid-overflowing-i_blocks fs/ext3/super.c --- 25/fs/ext3/super.c~ext2-3-file-limits-to-avoid-overflowing-i_blocks 2005-03-18 00:12:07.000000000 -0800 +++ 25-akpm/fs/ext3/super.c 2005-03-18 00:12:07.000000000 -0800 @@ -1193,12 +1193,18 @@ static void ext3_orphan_cleanup (struct static loff_t ext3_max_size(int bits) { loff_t res = EXT3_NDIR_BLOCKS; + /* This constant is calculated to be the largest file size for a + * dense, 4k-blocksize file such that the total number of + * sectors in the file, including data and all indirect blocks, + * does not exceed 2^32. */ + const loff_t upper_limit = 0x1ff7fffd000LL; + res += 1LL << (bits-2); res += 1LL << (2*(bits-2)); res += 1LL << (3*(bits-2)); res <<= bits; - if (res > (512LL << 32) - (1 << bits)) - res = (512LL << 32) - (1 << bits); + if (res > upper_limit) + res = upper_limit; return res; } _