]> Git Repo - linux.git/blobdiff - fs/ext2/super.c
Merge tag 'drm-next-2019-03-06' of git://anongit.freedesktop.org/drm/drm
[linux.git] / fs / ext2 / super.c
index 73b2d528237f21012ccd8933167d599791cfeafb..0128010a0874e0e558056cd6b74b30cff21f69c8 100644 (file)
@@ -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);
 
+       /* Compute how many blocks we can address by block tree */
+       res += 1LL << (bits-2);
+       res += 1LL << (2*(bits-2));
+       res += 1LL << (3*(bits-2));
+       /* 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 */
-       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));
+       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 > upper_limit)
-               res = upper_limit;
-
        if (res > MAX_LFS_FILESIZE)
                res = MAX_LFS_FILESIZE;
 
@@ -1024,8 +1035,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
        sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
 
-       if (EXT2_INODE_SIZE(sb) == 0)
-               goto cantfind_ext2;
        sbi->s_inodes_per_block = sb->s_blocksize / EXT2_INODE_SIZE(sb);
        if (sbi->s_inodes_per_block == 0 || sbi->s_inodes_per_group == 0)
                goto cantfind_ext2;
@@ -1087,12 +1096,14 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
                                           sizeof(struct buffer_head *),
                                           GFP_KERNEL);
        if (sbi->s_group_desc == NULL) {
+               ret = -ENOMEM;
                ext2_msg(sb, KERN_ERR, "error: not enough memory");
                goto failed_mount;
        }
        bgl_lock_init(sbi->s_blockgroup_lock);
        sbi->s_debts = kcalloc(sbi->s_groups_count, sizeof(*sbi->s_debts), GFP_KERNEL);
        if (!sbi->s_debts) {
+               ret = -ENOMEM;
                ext2_msg(sb, KERN_ERR, "error: not enough memory");
                goto failed_mount_group_desc;
        }
@@ -1148,6 +1159,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 #ifdef CONFIG_EXT2_FS_XATTR
        sbi->s_ea_block_cache = ext2_xattr_create_cache();
        if (!sbi->s_ea_block_cache) {
+               ret = -ENOMEM;
                ext2_msg(sb, KERN_ERR, "Failed to create ea_block_cache");
                goto failed_mount3;
        }
This page took 0.029197 seconds and 4 git commands to generate.