mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
ext2: Fix underflow in ext2_max_size()
When ext2 filesystem is created with 64k block size, ext2_max_size() will return value less than 0. Also, we cannot write any file in this fs since the sb->maxbytes is less than 0. The core of the problem is that the size of block index tree for such large block size is more than i_blocks can carry. So fix the computation to count with this possibility. File size limits computed with the new function for the full range of possible block sizes look like: bits file_size 10 17247252480 11 275415851008 12 2196873666560 13 2197948973056 14 2198486220800 15 2198754754560 16 2198888906752 CC: stable@vger.kernel.org Reported-by: yangerkun <yangerkun@huawei.com> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
4bc74ba1c7
commit
1c2d14212b
@ -757,7 +757,8 @@ static loff_t ext2_max_size(int bits)
|
||||
{
|
||||
loff_t res = EXT2_NDIR_BLOCKS;
|
||||
int meta_blocks;
|
||||
loff_t upper_limit;
|
||||
unsigned int upper_limit;
|
||||
unsigned int ppb = 1 << (bits-2);
|
||||
|
||||
/* This is calculated to be the largest file size for a
|
||||
* dense, file such that the total number of
|
||||
@ -771,24 +772,34 @@ static loff_t ext2_max_size(int bits)
|
||||
/* total blocks in file system block size */
|
||||
upper_limit >>= (bits - 9);
|
||||
|
||||
|
||||
/* indirect blocks */
|
||||
meta_blocks = 1;
|
||||
/* double indirect blocks */
|
||||
meta_blocks += 1 + (1LL << (bits-2));
|
||||
/* tripple indirect blocks */
|
||||
meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2)));
|
||||
|
||||
upper_limit -= meta_blocks;
|
||||
upper_limit <<= bits;
|
||||
|
||||
/* Compute how many blocks we can address by block tree */
|
||||
res += 1LL << (bits-2);
|
||||
res += 1LL << (2*(bits-2));
|
||||
res += 1LL << (3*(bits-2));
|
||||
res <<= bits;
|
||||
if (res > upper_limit)
|
||||
res = upper_limit;
|
||||
/* Does block tree limit file size? */
|
||||
if (res < upper_limit)
|
||||
goto check_lfs;
|
||||
|
||||
res = upper_limit;
|
||||
/* How many metadata blocks are needed for addressing upper_limit? */
|
||||
upper_limit -= EXT2_NDIR_BLOCKS;
|
||||
/* indirect blocks */
|
||||
meta_blocks = 1;
|
||||
upper_limit -= ppb;
|
||||
/* double indirect blocks */
|
||||
if (upper_limit < ppb * ppb) {
|
||||
meta_blocks += 1 + DIV_ROUND_UP(upper_limit, ppb);
|
||||
res -= meta_blocks;
|
||||
goto check_lfs;
|
||||
}
|
||||
meta_blocks += 1 + ppb;
|
||||
upper_limit -= ppb * ppb;
|
||||
/* tripple indirect blocks for the rest */
|
||||
meta_blocks += 1 + DIV_ROUND_UP(upper_limit, ppb) +
|
||||
DIV_ROUND_UP(upper_limit, ppb*ppb);
|
||||
res -= meta_blocks;
|
||||
check_lfs:
|
||||
res <<= bits;
|
||||
if (res > MAX_LFS_FILESIZE)
|
||||
res = MAX_LFS_FILESIZE;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user