From: "Stephen C. Tweedie" <sct@redhat.com>

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 <sct@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 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;
 }
 
_