ChangeSet 1.2231.1.159, 2005/03/28 20:00:38-08:00, [EMAIL PROTECTED]
[PATCH] ext2/3 file limits to avoid overflowing i_blocks
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 <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
ext2/super.c | 10 ++++++++--
ext3/super.c | 10 ++++++++--
2 files changed, 16 insertions(+), 4 deletions(-)
diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c
--- a/fs/ext2/super.c 2005-03-28 21:41:31 -08:00
+++ b/fs/ext2/super.c 2005-03-28 21:41:31 -08:00
@@ -518,12 +518,18 @@
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 -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c 2005-03-28 21:41:31 -08:00
+++ b/fs/ext3/super.c 2005-03-28 21:41:31 -08:00
@@ -1193,12 +1193,18 @@
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;
}
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html