2019-01-23 13:10:33

by yangerkun

[permalink] [raw]
Subject: [PATCH 0/2] fix a bug in ext2_max_size

When mkfs.ext2 with '-b 65536' and mount(arm 64KB page size),
function mount_fs will trigger WARNNING since 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.

Fix it by get the exact max file size.

yangerkun (2):
ext2: remove static of ext2_block_to_path
ext2: get the exact max filesize in ext2_max_size

fs/ext2/ext2.h | 1 +
fs/ext2/inode.c | 16 ++++----
fs/ext2/super.c | 115 ++++++++++++++++++++++++++++++++++++++++++++------------
3 files changed, 101 insertions(+), 31 deletions(-)

--
2.9.5



2019-01-23 13:10:38

by yangerkun

[permalink] [raw]
Subject: [PATCH 1/2] ext2: remove static of ext2_block_to_path

This function will be used to get exact size in ext2_max_size future.

Signed-off-by: yangerkun <[email protected]>
---
fs/ext2/ext2.h | 1 +
fs/ext2/inode.c | 16 ++++++++--------
2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index e770cd1..86d5be1 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -772,6 +772,7 @@ extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
extern struct inode *ext2_iget (struct super_block *, unsigned long);
extern int ext2_write_inode (struct inode *, struct writeback_control *);
extern void ext2_evict_inode(struct inode *);
+extern int ext2_block_to_path(struct super_block *sb, long i_block, int offsets[4], int *boundary);
extern int ext2_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern int ext2_setattr (struct dentry *, struct iattr *);
extern void ext2_set_inode_flags(struct inode *inode);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index e4bb938..f2833245 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -132,7 +132,6 @@ static inline int verify_chain(Indirect *from, Indirect *to)

/**
* ext2_block_to_path - parse the block number into array of offsets
- * @inode: inode in question (we are only interested in its superblock)
* @i_block: block number to be parsed
* @offsets: array to store the offsets in
* @boundary: set this non-zero if the referred-to block is likely to be
@@ -160,11 +159,11 @@ static inline int verify_chain(Indirect *from, Indirect *to)
* get there at all.
*/

-static int ext2_block_to_path(struct inode *inode,
+int ext2_block_to_path(struct super_block *sb,
long i_block, int offsets[4], int *boundary)
{
- int ptrs = EXT2_ADDR_PER_BLOCK(inode->i_sb);
- int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb);
+ int ptrs = EXT2_ADDR_PER_BLOCK(sb);
+ int ptrs_bits = EXT2_ADDR_PER_BLOCK_BITS(sb);
const long direct_blocks = EXT2_NDIR_BLOCKS,
indirect_blocks = ptrs,
double_blocks = (1 << (ptrs_bits * 2));
@@ -172,7 +171,7 @@ static int ext2_block_to_path(struct inode *inode,
int final = 0;

if (i_block < 0) {
- ext2_msg(inode->i_sb, KERN_WARNING,
+ ext2_msg(sb, KERN_WARNING,
"warning: %s: block < 0", __func__);
} else if (i_block < direct_blocks) {
offsets[n++] = i_block;
@@ -193,7 +192,7 @@ static int ext2_block_to_path(struct inode *inode,
offsets[n++] = i_block & (ptrs - 1);
final = ptrs;
} else {
- ext2_msg(inode->i_sb, KERN_WARNING,
+ ext2_msg(sb, KERN_WARNING,
"warning: %s: block is too big", __func__);
}
if (boundary)
@@ -637,7 +636,8 @@ static int ext2_get_blocks(struct inode *inode,

BUG_ON(maxblocks == 0);

- depth = ext2_block_to_path(inode,iblock,offsets,&blocks_to_boundary);
+ depth = ext2_block_to_path(inode->i_sb, iblock,
+ offsets, &blocks_to_boundary);

if (depth == 0)
return -EIO;
@@ -1194,7 +1194,7 @@ static void __ext2_truncate_blocks(struct inode *inode, loff_t offset)
WARN_ON(!rwsem_is_locked(&ei->dax_sem));
#endif

- n = ext2_block_to_path(inode, iblock, offsets, NULL);
+ n = ext2_block_to_path(inode->i_sb, iblock, offsets, NULL);
if (n == 0)
return;

--
2.9.5


2019-01-23 13:10:39

by yangerkun

[permalink] [raw]
Subject: [PATCH 2/2] ext2: get the exact max filesize in ext2_max_size

When mkfs.ext2 with '-b 65536' and mount(arm 64KB page size), function
mount_fs will trigger WARNING since 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.

Fix it by get the exact max file size. First, get the max depth for
indirect blocks and check does the max data blocks add indirect blocks
will execced upper_limit. If right, bisect to get exact data blocks
number which satisfy 'data blocks number + indirect blocks number ==
upper_limit'.

Signed-off-by: yangerkun <[email protected]>
---
fs/ext2/super.c | 115 ++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 92 insertions(+), 23 deletions(-)

diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 73b2d52..b3eb6e9 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -753,11 +753,16 @@ static int ext2_check_descriptors(struct super_block *sb)
* block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
* We need to be 1 filesystem block less than the 2^32 sector limit.
*/
-static loff_t ext2_max_size(int bits)
+static loff_t ext2_max_size(struct super_block *sb, int bits)
{
- loff_t res = EXT2_NDIR_BLOCKS;
- int meta_blocks;
+ loff_t res;
+ loff_t max_meta_blocks;
+ loff_t used_data_blocks;
+ loff_t max_data_blocks;
loff_t upper_limit;
+ int depth;
+ loff_t high, low;
+

/* This is calculated to be the largest file size for a
* dense, file such that the total number of
@@ -771,24 +776,88 @@ static loff_t ext2_max_size(int bits)
/* total blocks in file system block size */
upper_limit >>= (bits - 9);

+ /* Try to get max depth of metadata blocks */
+ depth = 0;
+ max_meta_blocks = 0;
+ used_data_blocks = 0;
+ max_data_blocks = EXT2_NDIR_BLOCKS;
+ if (max_meta_blocks + max_data_blocks > upper_limit)
+ goto bisect;
+
+ depth++;
+ max_meta_blocks = 1;
+ used_data_blocks = max_data_blocks;
+ max_data_blocks += 1LL << (bits - 2);
+ if (max_meta_blocks + max_data_blocks > upper_limit)
+ goto bisect;
+
+ depth++;
+ max_meta_blocks += 1 + (1LL << (bits - 2));
+ used_data_blocks = max_data_blocks;
+ max_data_blocks += 1LL << (2 * (bits - 2));
+ if (max_meta_blocks + max_data_blocks > upper_limit)
+ goto bisect;
+
+ depth++;
+ max_meta_blocks += 1 + (1LL << (bits - 2)) + (1LL << (2 * (bits - 2)));
+ used_data_blocks = max_data_blocks;
+ max_data_blocks += 1LL << (3 * (bits - 2));
+ if (max_meta_blocks + max_data_blocks > upper_limit)
+ goto bisect;
+
+ goto out;
+bisect:
+ low = 0;
+ if (depth == 0)
+ high = EXT2_NDIR_BLOCKS;
+ else
+ high = 1 << (depth * (bits - 2));
+ while (low <= high) {
+ int offsets[4];
+ loff_t mid = (low + high) >> 1;
+ depth = ext2_block_to_path(sb, mid + used_data_blocks - 1, offsets, NULL);
+ if (!depth)
+ return -EIO;
+
+ max_meta_blocks = 0;
+ if (depth == 1)
+ max_meta_blocks = 0;
+
+ if (depth == 2)
+ max_meta_blocks = 1;
+
+ if (depth == 3) {
+ /* Indirect blocks */
+ max_meta_blocks += 1;
+ /* Double indirect blocks */
+ max_meta_blocks += 1;
+ max_meta_blocks += offsets[1];
+ }

- /* 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 << (2*(bits-2));
- res += 1LL << (3*(bits-2));
- res <<= bits;
- if (res > upper_limit)
- res = upper_limit;
-
+ if (depth == 4) {
+ /* Indirect blocks */
+ max_meta_blocks += 1;
+ /* Double indirect blocks */
+ max_meta_blocks += 1 + (1 << (bits - 2));
+ /* Tripple indirect blocks */
+ max_meta_blocks += 1;
+ if (offsets[1])
+ max_meta_blocks += (offsets[1] - 1) * (1 << (bits - 2));
+
+ max_meta_blocks += 1;
+ max_meta_blocks += offsets[2];
+ }
+ if (max_meta_blocks + mid + used_data_blocks > upper_limit)
+ high = mid - 1;
+ if (max_meta_blocks + mid + used_data_blocks < upper_limit)
+ low = mid + 1;
+ if (max_meta_blocks + mid + used_data_blocks == upper_limit) {
+ max_data_blocks = mid + used_data_blocks;
+ break;
+ }
+ }
+out:
+ res = max_data_blocks << bits;
if (res > MAX_LFS_FILESIZE)
res = MAX_LFS_FILESIZE;

@@ -995,7 +1064,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
}
}

- sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
+ sbi->s_addr_per_block_bits =
+ ilog2 (EXT2_ADDR_PER_BLOCK(sb));
+ sb->s_maxbytes = ext2_max_size(sb, sb->s_blocksize_bits);
sb->s_max_links = EXT2_LINK_MAX;

if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
@@ -1035,8 +1106,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
sizeof (struct ext2_group_desc);
sbi->s_sbh = bh;
sbi->s_mount_state = le16_to_cpu(es->s_state);
- sbi->s_addr_per_block_bits =
- ilog2 (EXT2_ADDR_PER_BLOCK(sb));
sbi->s_desc_per_block_bits =
ilog2 (EXT2_DESC_PER_BLOCK(sb));

--
2.9.5


2019-01-29 16:42:12

by Jan Kara

[permalink] [raw]
Subject: Re: [PATCH 2/2] ext2: get the exact max filesize in ext2_max_size

On Wed 23-01-19 21:14:09, yangerkun wrote:
> When mkfs.ext2 with '-b 65536' and mount(arm 64KB page size), function
> mount_fs will trigger WARNING since 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.
>
> Fix it by get the exact max file size. First, get the max depth for
> indirect blocks and check does the max data blocks add indirect blocks
> will execced upper_limit. If right, bisect to get exact data blocks
> number which satisfy 'data blocks number + indirect blocks number ==
> upper_limit'.
>
> Signed-off-by: yangerkun <[email protected]>

Thanks for the patches but I was really looking for something simpler.
Something like the attached patch. Although your more precise function will
raise the maximum file size by couple of kilobytes I don't think the
complexity is really worth it...

Honza

> ---
> fs/ext2/super.c | 115 ++++++++++++++++++++++++++++++++++++++++++++------------
> 1 file changed, 92 insertions(+), 23 deletions(-)
>
> diff --git a/fs/ext2/super.c b/fs/ext2/super.c
> index 73b2d52..b3eb6e9 100644
> --- a/fs/ext2/super.c
> +++ b/fs/ext2/super.c
> @@ -753,11 +753,16 @@ static int ext2_check_descriptors(struct super_block *sb)
> * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
> * We need to be 1 filesystem block less than the 2^32 sector limit.
> */
> -static loff_t ext2_max_size(int bits)
> +static loff_t ext2_max_size(struct super_block *sb, int bits)
> {
> - loff_t res = EXT2_NDIR_BLOCKS;
> - int meta_blocks;
> + loff_t res;
> + loff_t max_meta_blocks;
> + loff_t used_data_blocks;
> + loff_t max_data_blocks;
> loff_t upper_limit;
> + int depth;
> + loff_t high, low;
> +
>
> /* This is calculated to be the largest file size for a
> * dense, file such that the total number of
> @@ -771,24 +776,88 @@ static loff_t ext2_max_size(int bits)
> /* total blocks in file system block size */
> upper_limit >>= (bits - 9);
>
> + /* Try to get max depth of metadata blocks */
> + depth = 0;
> + max_meta_blocks = 0;
> + used_data_blocks = 0;
> + max_data_blocks = EXT2_NDIR_BLOCKS;
> + if (max_meta_blocks + max_data_blocks > upper_limit)
> + goto bisect;
> +
> + depth++;
> + max_meta_blocks = 1;
> + used_data_blocks = max_data_blocks;
> + max_data_blocks += 1LL << (bits - 2);
> + if (max_meta_blocks + max_data_blocks > upper_limit)
> + goto bisect;
> +
> + depth++;
> + max_meta_blocks += 1 + (1LL << (bits - 2));
> + used_data_blocks = max_data_blocks;
> + max_data_blocks += 1LL << (2 * (bits - 2));
> + if (max_meta_blocks + max_data_blocks > upper_limit)
> + goto bisect;
> +
> + depth++;
> + max_meta_blocks += 1 + (1LL << (bits - 2)) + (1LL << (2 * (bits - 2)));
> + used_data_blocks = max_data_blocks;
> + max_data_blocks += 1LL << (3 * (bits - 2));
> + if (max_meta_blocks + max_data_blocks > upper_limit)
> + goto bisect;
> +
> + goto out;
> +bisect:
> + low = 0;
> + if (depth == 0)
> + high = EXT2_NDIR_BLOCKS;
> + else
> + high = 1 << (depth * (bits - 2));
> + while (low <= high) {
> + int offsets[4];
> + loff_t mid = (low + high) >> 1;
> + depth = ext2_block_to_path(sb, mid + used_data_blocks - 1, offsets, NULL);
> + if (!depth)
> + return -EIO;
> +
> + max_meta_blocks = 0;
> + if (depth == 1)
> + max_meta_blocks = 0;
> +
> + if (depth == 2)
> + max_meta_blocks = 1;
> +
> + if (depth == 3) {
> + /* Indirect blocks */
> + max_meta_blocks += 1;
> + /* Double indirect blocks */
> + max_meta_blocks += 1;
> + max_meta_blocks += offsets[1];
> + }
>
> - /* 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 << (2*(bits-2));
> - res += 1LL << (3*(bits-2));
> - res <<= bits;
> - if (res > upper_limit)
> - res = upper_limit;
> -
> + if (depth == 4) {
> + /* Indirect blocks */
> + max_meta_blocks += 1;
> + /* Double indirect blocks */
> + max_meta_blocks += 1 + (1 << (bits - 2));
> + /* Tripple indirect blocks */
> + max_meta_blocks += 1;
> + if (offsets[1])
> + max_meta_blocks += (offsets[1] - 1) * (1 << (bits - 2));
> +
> + max_meta_blocks += 1;
> + max_meta_blocks += offsets[2];
> + }
> + if (max_meta_blocks + mid + used_data_blocks > upper_limit)
> + high = mid - 1;
> + if (max_meta_blocks + mid + used_data_blocks < upper_limit)
> + low = mid + 1;
> + if (max_meta_blocks + mid + used_data_blocks == upper_limit) {
> + max_data_blocks = mid + used_data_blocks;
> + break;
> + }
> + }
> +out:
> + res = max_data_blocks << bits;
> if (res > MAX_LFS_FILESIZE)
> res = MAX_LFS_FILESIZE;
>
> @@ -995,7 +1064,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
> }
> }
>
> - sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
> + sbi->s_addr_per_block_bits =
> + ilog2 (EXT2_ADDR_PER_BLOCK(sb));
> + sb->s_maxbytes = ext2_max_size(sb, sb->s_blocksize_bits);
> sb->s_max_links = EXT2_LINK_MAX;
>
> if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
> @@ -1035,8 +1106,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
> sizeof (struct ext2_group_desc);
> sbi->s_sbh = bh;
> sbi->s_mount_state = le16_to_cpu(es->s_state);
> - sbi->s_addr_per_block_bits =
> - ilog2 (EXT2_ADDR_PER_BLOCK(sb));
> sbi->s_desc_per_block_bits =
> ilog2 (EXT2_DESC_PER_BLOCK(sb));
>
> --
> 2.9.5
>
--
Jan Kara <[email protected]>
SUSE Labs, CR


Attachments:
(No filename) (5.55 kB)
0001-ext2-Fix-underflow-in-ext2_max_size.patch (2.58 kB)
Download all attachments

2019-01-31 11:43:43

by yangerkun

[permalink] [raw]
Subject: Re: [PATCH 2/2] ext2: get the exact max filesize in ext2_max_size



Jan Kara wrote on 2019/1/30 0:42:
> On Wed 23-01-19 21:14:09, yangerkun wrote:
>> When mkfs.ext2 with '-b 65536' and mount(arm 64KB page size), function
>> mount_fs will trigger WARNING since 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.
>>
>> Fix it by get the exact max file size. First, get the max depth for
>> indirect blocks and check does the max data blocks add indirect blocks
>> will execced upper_limit. If right, bisect to get exact data blocks
>> number which satisfy 'data blocks number + indirect blocks number ==
>> upper_limit'.
>>
>> Signed-off-by: yangerkun <[email protected]>
>
> Thanks for the patches but I was really looking for something simpler.
> Something like the attached patch. Although your more precise function will
> raise the maximum file size by couple of kilobytes I don't think the
> complexity is really worth it...

Agree with you. A precise answer with so complexity function does not
make sense. Also i have review and test your without any problem. I
prefer your patch!

Reviewed-by: yangerkun <[email protected]>

Thanks a lot,
Kun.

>
> Honza
>
>> ---
>> fs/ext2/super.c | 115 ++++++++++++++++++++++++++++++++++++++++++++------------
>> 1 file changed, 92 insertions(+), 23 deletions(-)
>>
>> diff --git a/fs/ext2/super.c b/fs/ext2/super.c
>> index 73b2d52..b3eb6e9 100644
>> --- a/fs/ext2/super.c
>> +++ b/fs/ext2/super.c
>> @@ -753,11 +753,16 @@ static int ext2_check_descriptors(struct super_block *sb)
>> * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
>> * We need to be 1 filesystem block less than the 2^32 sector limit.
>> */
>> -static loff_t ext2_max_size(int bits)
>> +static loff_t ext2_max_size(struct super_block *sb, int bits)
>> {
>> - loff_t res = EXT2_NDIR_BLOCKS;
>> - int meta_blocks;
>> + loff_t res;
>> + loff_t max_meta_blocks;
>> + loff_t used_data_blocks;
>> + loff_t max_data_blocks;
>> loff_t upper_limit;
>> + int depth;
>> + loff_t high, low;
>> +
>>
>> /* This is calculated to be the largest file size for a
>> * dense, file such that the total number of
>> @@ -771,24 +776,88 @@ static loff_t ext2_max_size(int bits)
>> /* total blocks in file system block size */
>> upper_limit >>= (bits - 9);
>>
>> + /* Try to get max depth of metadata blocks */
>> + depth = 0;
>> + max_meta_blocks = 0;
>> + used_data_blocks = 0;
>> + max_data_blocks = EXT2_NDIR_BLOCKS;
>> + if (max_meta_blocks + max_data_blocks > upper_limit)
>> + goto bisect;
>> +
>> + depth++;
>> + max_meta_blocks = 1;
>> + used_data_blocks = max_data_blocks;
>> + max_data_blocks += 1LL << (bits - 2);
>> + if (max_meta_blocks + max_data_blocks > upper_limit)
>> + goto bisect;
>> +
>> + depth++;
>> + max_meta_blocks += 1 + (1LL << (bits - 2));
>> + used_data_blocks = max_data_blocks;
>> + max_data_blocks += 1LL << (2 * (bits - 2));
>> + if (max_meta_blocks + max_data_blocks > upper_limit)
>> + goto bisect;
>> +
>> + depth++;
>> + max_meta_blocks += 1 + (1LL << (bits - 2)) + (1LL << (2 * (bits - 2)));
>> + used_data_blocks = max_data_blocks;
>> + max_data_blocks += 1LL << (3 * (bits - 2));
>> + if (max_meta_blocks + max_data_blocks > upper_limit)
>> + goto bisect;
>> +
>> + goto out;
>> +bisect:
>> + low = 0;
>> + if (depth == 0)
>> + high = EXT2_NDIR_BLOCKS;
>> + else
>> + high = 1 << (depth * (bits - 2));
>> + while (low <= high) {
>> + int offsets[4];
>> + loff_t mid = (low + high) >> 1;
>> + depth = ext2_block_to_path(sb, mid + used_data_blocks - 1, offsets, NULL);
>> + if (!depth)
>> + return -EIO;
>> +
>> + max_meta_blocks = 0;
>> + if (depth == 1)
>> + max_meta_blocks = 0;
>> +
>> + if (depth == 2)
>> + max_meta_blocks = 1;
>> +
>> + if (depth == 3) {
>> + /* Indirect blocks */
>> + max_meta_blocks += 1;
>> + /* Double indirect blocks */
>> + max_meta_blocks += 1;
>> + max_meta_blocks += offsets[1];
>> + }
>>
>> - /* 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 << (2*(bits-2));
>> - res += 1LL << (3*(bits-2));
>> - res <<= bits;
>> - if (res > upper_limit)
>> - res = upper_limit;
>> -
>> + if (depth == 4) {
>> + /* Indirect blocks */
>> + max_meta_blocks += 1;
>> + /* Double indirect blocks */
>> + max_meta_blocks += 1 + (1 << (bits - 2));
>> + /* Tripple indirect blocks */
>> + max_meta_blocks += 1;
>> + if (offsets[1])
>> + max_meta_blocks += (offsets[1] - 1) * (1 << (bits - 2));
>> +
>> + max_meta_blocks += 1;
>> + max_meta_blocks += offsets[2];
>> + }
>> + if (max_meta_blocks + mid + used_data_blocks > upper_limit)
>> + high = mid - 1;
>> + if (max_meta_blocks + mid + used_data_blocks < upper_limit)
>> + low = mid + 1;
>> + if (max_meta_blocks + mid + used_data_blocks == upper_limit) {
>> + max_data_blocks = mid + used_data_blocks;
>> + break;
>> + }
>> + }
>> +out:
>> + res = max_data_blocks << bits;
>> if (res > MAX_LFS_FILESIZE)
>> res = MAX_LFS_FILESIZE;
>>
>> @@ -995,7 +1064,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
>> }
>> }
>>
>> - sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
>> + sbi->s_addr_per_block_bits =
>> + ilog2 (EXT2_ADDR_PER_BLOCK(sb));
>> + sb->s_maxbytes = ext2_max_size(sb, sb->s_blocksize_bits);
>> sb->s_max_links = EXT2_LINK_MAX;
>>
>> if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
>> @@ -1035,8 +1106,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
>> sizeof (struct ext2_group_desc);
>> sbi->s_sbh = bh;
>> sbi->s_mount_state = le16_to_cpu(es->s_state);
>> - sbi->s_addr_per_block_bits =
>> - ilog2 (EXT2_ADDR_PER_BLOCK(sb));
>> sbi->s_desc_per_block_bits =
>> ilog2 (EXT2_DESC_PER_BLOCK(sb));
>>
>> --
>> 2.9.5
>>