forked from luck/tmp_suning_uos_patched
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;
|
loff_t res = EXT2_NDIR_BLOCKS;
|
||||||
int meta_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
|
/* This is calculated to be the largest file size for a
|
||||||
* dense, file such that the total number of
|
* 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 */
|
/* total blocks in file system block size */
|
||||||
upper_limit >>= (bits - 9);
|
upper_limit >>= (bits - 9);
|
||||||
|
|
||||||
|
/* Compute how many blocks we can address by block tree */
|
||||||
/* 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;
|
|
||||||
|
|
||||||
res += 1LL << (bits-2);
|
res += 1LL << (bits-2);
|
||||||
res += 1LL << (2*(bits-2));
|
res += 1LL << (2*(bits-2));
|
||||||
res += 1LL << (3*(bits-2));
|
res += 1LL << (3*(bits-2));
|
||||||
res <<= bits;
|
/* Does block tree limit file size? */
|
||||||
if (res > upper_limit)
|
if (res < upper_limit)
|
||||||
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)
|
if (res > MAX_LFS_FILESIZE)
|
||||||
res = MAX_LFS_FILESIZE;
|
res = MAX_LFS_FILESIZE;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user