Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[linux-block.git] / fs / ext4 / super.c
index 76d1ef0efbf4bb75161b25887588021d157839db..d03bf0ecf505283c48cd25c9ec261f0c1411f3ee 100644 (file)
@@ -1183,12 +1183,81 @@ static inline void ext4_quota_off_umount(struct super_block *sb)
 }
 #endif
 
+static int ext4_percpu_param_init(struct ext4_sb_info *sbi)
+{
+       ext4_fsblk_t block;
+       int err;
+
+       block = ext4_count_free_clusters(sbi->s_sb);
+       ext4_free_blocks_count_set(sbi->s_es, EXT4_C2B(sbi, block));
+       err = percpu_counter_init(&sbi->s_freeclusters_counter, block,
+                                 GFP_KERNEL);
+       if (!err) {
+               unsigned long freei = ext4_count_free_inodes(sbi->s_sb);
+               sbi->s_es->s_free_inodes_count = cpu_to_le32(freei);
+               err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
+                                         GFP_KERNEL);
+       }
+       if (!err)
+               err = percpu_counter_init(&sbi->s_dirs_counter,
+                                         ext4_count_dirs(sbi->s_sb), GFP_KERNEL);
+       if (!err)
+               err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
+                                         GFP_KERNEL);
+       if (!err)
+               err = percpu_counter_init(&sbi->s_sra_exceeded_retry_limit, 0,
+                                         GFP_KERNEL);
+       if (!err)
+               err = percpu_init_rwsem(&sbi->s_writepages_rwsem);
+
+       if (err)
+               ext4_msg(sbi->s_sb, KERN_ERR, "insufficient memory");
+
+       return err;
+}
+
+static void ext4_percpu_param_destroy(struct ext4_sb_info *sbi)
+{
+       percpu_counter_destroy(&sbi->s_freeclusters_counter);
+       percpu_counter_destroy(&sbi->s_freeinodes_counter);
+       percpu_counter_destroy(&sbi->s_dirs_counter);
+       percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
+       percpu_counter_destroy(&sbi->s_sra_exceeded_retry_limit);
+       percpu_free_rwsem(&sbi->s_writepages_rwsem);
+}
+
+static void ext4_group_desc_free(struct ext4_sb_info *sbi)
+{
+       struct buffer_head **group_desc;
+       int i;
+
+       rcu_read_lock();
+       group_desc = rcu_dereference(sbi->s_group_desc);
+       for (i = 0; i < sbi->s_gdb_count; i++)
+               brelse(group_desc[i]);
+       kvfree(group_desc);
+       rcu_read_unlock();
+}
+
+static void ext4_flex_groups_free(struct ext4_sb_info *sbi)
+{
+       struct flex_groups **flex_groups;
+       int i;
+
+       rcu_read_lock();
+       flex_groups = rcu_dereference(sbi->s_flex_groups);
+       if (flex_groups) {
+               for (i = 0; i < sbi->s_flex_groups_allocated; i++)
+                       kvfree(flex_groups[i]);
+               kvfree(flex_groups);
+       }
+       rcu_read_unlock();
+}
+
 static void ext4_put_super(struct super_block *sb)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
-       struct buffer_head **group_desc;
-       struct flex_groups **flex_groups;
        int aborted = 0;
        int i, err;
 
@@ -1238,24 +1307,9 @@ static void ext4_put_super(struct super_block *sb)
        if (!sb_rdonly(sb))
                ext4_commit_super(sb);
 
-       rcu_read_lock();
-       group_desc = rcu_dereference(sbi->s_group_desc);
-       for (i = 0; i < sbi->s_gdb_count; i++)
-               brelse(group_desc[i]);
-       kvfree(group_desc);
-       flex_groups = rcu_dereference(sbi->s_flex_groups);
-       if (flex_groups) {
-               for (i = 0; i < sbi->s_flex_groups_allocated; i++)
-                       kvfree(flex_groups[i]);
-               kvfree(flex_groups);
-       }
-       rcu_read_unlock();
-       percpu_counter_destroy(&sbi->s_freeclusters_counter);
-       percpu_counter_destroy(&sbi->s_freeinodes_counter);
-       percpu_counter_destroy(&sbi->s_dirs_counter);
-       percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
-       percpu_counter_destroy(&sbi->s_sra_exceeded_retry_limit);
-       percpu_free_rwsem(&sbi->s_writepages_rwsem);
+       ext4_group_desc_free(sbi);
+       ext4_flex_groups_free(sbi);
+       ext4_percpu_param_destroy(sbi);
 #ifdef CONFIG_QUOTA
        for (i = 0; i < EXT4_MAXQUOTAS; i++)
                kfree(get_qf_name(sb, sbi, i));
@@ -1325,9 +1379,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        inode_set_iversion(&ei->vfs_inode, 1);
        ei->i_flags = 0;
        spin_lock_init(&ei->i_raw_lock);
-       INIT_LIST_HEAD(&ei->i_prealloc_list);
+       ei->i_prealloc_node = RB_ROOT;
        atomic_set(&ei->i_prealloc_active, 0);
-       spin_lock_init(&ei->i_prealloc_lock);
+       rwlock_init(&ei->i_prealloc_lock);
        ext4_es_init_tree(&ei->i_es_tree);
        rwlock_init(&ei->i_es_lock);
        INIT_LIST_HEAD(&ei->i_es_list);
@@ -4587,6 +4641,8 @@ static int ext4_check_feature_compatibility(struct super_block *sb,
                                            struct ext4_super_block *es,
                                            int silent)
 {
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+
        if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV &&
            (ext4_has_compat_features(sb) ||
             ext4_has_ro_compat_features(sb) ||
@@ -4656,14 +4712,59 @@ static int ext4_check_feature_compatibility(struct super_block *sb,
        if (!ext4_feature_set_ok(sb, (sb_rdonly(sb))))
                return -EINVAL;
 
+       if (sbi->s_daxdev) {
+               if (sb->s_blocksize == PAGE_SIZE)
+                       set_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags);
+               else
+                       ext4_msg(sb, KERN_ERR, "unsupported blocksize for DAX\n");
+       }
+
+       if (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) {
+               if (ext4_has_feature_inline_data(sb)) {
+                       ext4_msg(sb, KERN_ERR, "Cannot use DAX on a filesystem"
+                                       " that may contain inline data");
+                       return -EINVAL;
+               }
+               if (!test_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags)) {
+                       ext4_msg(sb, KERN_ERR,
+                               "DAX unsupported by block device.");
+                       return -EINVAL;
+               }
+       }
+
+       if (ext4_has_feature_encrypt(sb) && es->s_encryption_level) {
+               ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d",
+                        es->s_encryption_level);
+               return -EINVAL;
+       }
+
        return 0;
 }
 
-static int ext4_geometry_check(struct super_block *sb,
+static int ext4_check_geometry(struct super_block *sb,
                               struct ext4_super_block *es)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        __u64 blocks_count;
+       int err;
+
+       if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (sb->s_blocksize / 4)) {
+               ext4_msg(sb, KERN_ERR,
+                        "Number of reserved GDT blocks insanely large: %d",
+                        le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks));
+               return -EINVAL;
+       }
+       /*
+        * Test whether we have more sectors than will fit in sector_t,
+        * and whether the max offset is addressable by the page cache.
+        */
+       err = generic_check_addressable(sb->s_blocksize_bits,
+                                       ext4_blocks_count(es));
+       if (err) {
+               ext4_msg(sb, KERN_ERR, "filesystem"
+                        " too large to mount safely on this system");
+               return err;
+       }
 
        /* check blocks count against device size */
        blocks_count = sb_bdev_nr_blocks(sb);
@@ -4719,19 +4820,6 @@ static int ext4_geometry_check(struct super_block *sb,
        return 0;
 }
 
-static void ext4_group_desc_free(struct ext4_sb_info *sbi)
-{
-       struct buffer_head **group_desc;
-       int i;
-
-       rcu_read_lock();
-       group_desc = rcu_dereference(sbi->s_group_desc);
-       for (i = 0; i < sbi->s_gdb_count; i++)
-               brelse(group_desc[i]);
-       kvfree(group_desc);
-       rcu_read_unlock();
-}
-
 static int ext4_group_desc_init(struct super_block *sb,
                                struct ext4_super_block *es,
                                ext4_fsblk_t logical_sb_block,
@@ -4881,7 +4969,7 @@ out:
        return -EINVAL;
 }
 
-static int ext4_journal_data_mode_check(struct super_block *sb)
+static int ext4_check_journal_data_mode(struct super_block *sb)
 {
        if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
                printk_once(KERN_WARNING "EXT4-fs: Warning: mounting with "
@@ -5024,17 +5112,93 @@ out:
        return ret;
 }
 
+static void ext4_hash_info_init(struct super_block *sb)
+{
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct ext4_super_block *es = sbi->s_es;
+       unsigned int i;
+
+       for (i = 0; i < 4; i++)
+               sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
+
+       sbi->s_def_hash_version = es->s_def_hash_version;
+       if (ext4_has_feature_dir_index(sb)) {
+               i = le32_to_cpu(es->s_flags);
+               if (i & EXT2_FLAGS_UNSIGNED_HASH)
+                       sbi->s_hash_unsigned = 3;
+               else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
+#ifdef __CHAR_UNSIGNED__
+                       if (!sb_rdonly(sb))
+                               es->s_flags |=
+                                       cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
+                       sbi->s_hash_unsigned = 3;
+#else
+                       if (!sb_rdonly(sb))
+                               es->s_flags |=
+                                       cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
+#endif
+               }
+       }
+}
+
+static int ext4_block_group_meta_init(struct super_block *sb, int silent)
+{
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct ext4_super_block *es = sbi->s_es;
+       int has_huge_files;
+
+       has_huge_files = ext4_has_feature_huge_file(sb);
+       sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits,
+                                                     has_huge_files);
+       sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
+
+       sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
+       if (ext4_has_feature_64bit(sb)) {
+               if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
+                   sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
+                   !is_power_of_2(sbi->s_desc_size)) {
+                       ext4_msg(sb, KERN_ERR,
+                              "unsupported descriptor size %lu",
+                              sbi->s_desc_size);
+                       return -EINVAL;
+               }
+       } else
+               sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
+
+       sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
+       sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
+
+       sbi->s_inodes_per_block = sb->s_blocksize / EXT4_INODE_SIZE(sb);
+       if (sbi->s_inodes_per_block == 0 || sbi->s_blocks_per_group == 0) {
+               if (!silent)
+                       ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
+               return -EINVAL;
+       }
+       if (sbi->s_inodes_per_group < sbi->s_inodes_per_block ||
+           sbi->s_inodes_per_group > sb->s_blocksize * 8) {
+               ext4_msg(sb, KERN_ERR, "invalid inodes per group: %lu\n",
+                        sbi->s_inodes_per_group);
+               return -EINVAL;
+       }
+       sbi->s_itb_per_group = sbi->s_inodes_per_group /
+                                       sbi->s_inodes_per_block;
+       sbi->s_desc_per_block = sb->s_blocksize / EXT4_DESC_SIZE(sb);
+       sbi->s_mount_state = le16_to_cpu(es->s_state) & ~EXT4_FC_REPLAY;
+       sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
+       sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
+
+       return 0;
+}
+
 static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
 {
        struct ext4_super_block *es = NULL;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
-       struct flex_groups **flex_groups;
-       ext4_fsblk_t block;
        ext4_fsblk_t logical_sb_block;
        struct inode *root;
        int ret = -ENOMEM;
        unsigned int i;
-       int needs_recovery, has_huge_files;
+       int needs_recovery;
        int err = 0;
        ext4_group_t first_not_zeroed;
        struct ext4_fs_context *ctx = fc->fs_private;
@@ -5094,7 +5258,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
        if (ext4_encoding_init(sb, es))
                goto failed_mount;
 
-       if (ext4_journal_data_mode_check(sb))
+       if (ext4_check_journal_data_mode(sb))
                goto failed_mount;
 
        sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
@@ -5106,116 +5270,15 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
        if (ext4_check_feature_compatibility(sb, es, silent))
                goto failed_mount;
 
-       if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (sb->s_blocksize / 4)) {
-               ext4_msg(sb, KERN_ERR,
-                        "Number of reserved GDT blocks insanely large: %d",
-                        le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks));
+       if (ext4_block_group_meta_init(sb, silent))
                goto failed_mount;
-       }
 
-       if (sbi->s_daxdev) {
-               if (sb->s_blocksize == PAGE_SIZE)
-                       set_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags);
-               else
-                       ext4_msg(sb, KERN_ERR, "unsupported blocksize for DAX\n");
-       }
-
-       if (sbi->s_mount_opt & EXT4_MOUNT_DAX_ALWAYS) {
-               if (ext4_has_feature_inline_data(sb)) {
-                       ext4_msg(sb, KERN_ERR, "Cannot use DAX on a filesystem"
-                                       " that may contain inline data");
-                       goto failed_mount;
-               }
-               if (!test_bit(EXT4_FLAGS_BDEV_IS_DAX, &sbi->s_ext4_flags)) {
-                       ext4_msg(sb, KERN_ERR,
-                               "DAX unsupported by block device.");
-                       goto failed_mount;
-               }
-       }
-
-       if (ext4_has_feature_encrypt(sb) && es->s_encryption_level) {
-               ext4_msg(sb, KERN_ERR, "Unsupported encryption level %d",
-                        es->s_encryption_level);
-               goto failed_mount;
-       }
-
-       has_huge_files = ext4_has_feature_huge_file(sb);
-       sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits,
-                                                     has_huge_files);
-       sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
-
-       sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
-       if (ext4_has_feature_64bit(sb)) {
-               if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
-                   sbi->s_desc_size > EXT4_MAX_DESC_SIZE ||
-                   !is_power_of_2(sbi->s_desc_size)) {
-                       ext4_msg(sb, KERN_ERR,
-                              "unsupported descriptor size %lu",
-                              sbi->s_desc_size);
-                       goto failed_mount;
-               }
-       } else
-               sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
-
-       sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
-       sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
-
-       sbi->s_inodes_per_block = sb->s_blocksize / EXT4_INODE_SIZE(sb);
-       if (sbi->s_inodes_per_block == 0 || sbi->s_blocks_per_group == 0) {
-               if (!silent)
-                       ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem");
-               goto failed_mount;
-       }
-       if (sbi->s_inodes_per_group < sbi->s_inodes_per_block ||
-           sbi->s_inodes_per_group > sb->s_blocksize * 8) {
-               ext4_msg(sb, KERN_ERR, "invalid inodes per group: %lu\n",
-                        sbi->s_inodes_per_group);
-               goto failed_mount;
-       }
-       sbi->s_itb_per_group = sbi->s_inodes_per_group /
-                                       sbi->s_inodes_per_block;
-       sbi->s_desc_per_block = sb->s_blocksize / EXT4_DESC_SIZE(sb);
-       sbi->s_mount_state = le16_to_cpu(es->s_state) & ~EXT4_FC_REPLAY;
-       sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
-       sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
-
-       for (i = 0; i < 4; i++)
-               sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
-       sbi->s_def_hash_version = es->s_def_hash_version;
-       if (ext4_has_feature_dir_index(sb)) {
-               i = le32_to_cpu(es->s_flags);
-               if (i & EXT2_FLAGS_UNSIGNED_HASH)
-                       sbi->s_hash_unsigned = 3;
-               else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {
-#ifdef __CHAR_UNSIGNED__
-                       if (!sb_rdonly(sb))
-                               es->s_flags |=
-                                       cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH);
-                       sbi->s_hash_unsigned = 3;
-#else
-                       if (!sb_rdonly(sb))
-                               es->s_flags |=
-                                       cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);
-#endif
-               }
-       }
+       ext4_hash_info_init(sb);
 
        if (ext4_handle_clustersize(sb))
                goto failed_mount;
 
-       /*
-        * Test whether we have more sectors than will fit in sector_t,
-        * and whether the max offset is addressable by the page cache.
-        */
-       err = generic_check_addressable(sb->s_blocksize_bits,
-                                       ext4_blocks_count(es));
-       if (err) {
-               ext4_msg(sb, KERN_ERR, "filesystem"
-                        " too large to mount safely on this system");
-               goto failed_mount;
-       }
-
-       if (ext4_geometry_check(sb, es))
+       if (ext4_check_geometry(sb, es))
                goto failed_mount;
 
        timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
@@ -5440,33 +5503,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
                sbi->s_journal->j_commit_callback =
                        ext4_journal_commit_callback;
 
-       block = ext4_count_free_clusters(sb);
-       ext4_free_blocks_count_set(sbi->s_es,
-                                  EXT4_C2B(sbi, block));
-       err = percpu_counter_init(&sbi->s_freeclusters_counter, block,
-                                 GFP_KERNEL);
-       if (!err) {
-               unsigned long freei = ext4_count_free_inodes(sb);
-               sbi->s_es->s_free_inodes_count = cpu_to_le32(freei);
-               err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
-                                         GFP_KERNEL);
-       }
-       if (!err)
-               err = percpu_counter_init(&sbi->s_dirs_counter,
-                                         ext4_count_dirs(sb), GFP_KERNEL);
-       if (!err)
-               err = percpu_counter_init(&sbi->s_dirtyclusters_counter, 0,
-                                         GFP_KERNEL);
-       if (!err)
-               err = percpu_counter_init(&sbi->s_sra_exceeded_retry_limit, 0,
-                                         GFP_KERNEL);
-       if (!err)
-               err = percpu_init_rwsem(&sbi->s_writepages_rwsem);
-
-       if (err) {
-               ext4_msg(sb, KERN_ERR, "insufficient memory");
+       if (ext4_percpu_param_init(sbi))
                goto failed_mount6;
-       }
 
        if (ext4_has_feature_flex_bg(sb))
                if (!ext4_fill_flex_info(sb)) {
@@ -5548,20 +5586,8 @@ failed_mount7:
        ext4_unregister_li_request(sb);
 failed_mount6:
        ext4_mb_release(sb);
-       rcu_read_lock();
-       flex_groups = rcu_dereference(sbi->s_flex_groups);
-       if (flex_groups) {
-               for (i = 0; i < sbi->s_flex_groups_allocated; i++)
-                       kvfree(flex_groups[i]);
-               kvfree(flex_groups);
-       }
-       rcu_read_unlock();
-       percpu_counter_destroy(&sbi->s_freeclusters_counter);
-       percpu_counter_destroy(&sbi->s_freeinodes_counter);
-       percpu_counter_destroy(&sbi->s_dirs_counter);
-       percpu_counter_destroy(&sbi->s_dirtyclusters_counter);
-       percpu_counter_destroy(&sbi->s_sra_exceeded_retry_limit);
-       percpu_free_rwsem(&sbi->s_writepages_rwsem);
+       ext4_flex_groups_free(sbi);
+       ext4_percpu_param_destroy(sbi);
 failed_mount5:
        ext4_ext_release(sb);
        ext4_release_system_zone(sb);
@@ -6870,23 +6896,6 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
                sb_dqopt(sb)->flags &= ~DQUOT_NOLIST_DIRTY;
        }
 
-       /*
-        * When we journal data on quota file, we have to flush journal to see
-        * all updates to the file when we bypass pagecache...
-        */
-       if (EXT4_SB(sb)->s_journal &&
-           ext4_should_journal_data(d_inode(path->dentry))) {
-               /*
-                * We don't need to lock updates but journal_flush() could
-                * otherwise be livelocked...
-                */
-               jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
-               err = jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0);
-               jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
-               if (err)
-                       return err;
-       }
-
        lockdep_set_quota_inode(path->dentry->d_inode, I_DATA_SEM_QUOTA);
        err = dquot_quota_on(sb, type, format_id, path);
        if (!err) {