Revert "ecryptfs: replace BUG_ON with error handling code"
[linux-2.6-microblaze.git] / fs / ext4 / super.c
index 3868377..7dc94f3 100644 (file)
@@ -667,9 +667,6 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
                        ext4_commit_super(sb);
        }
 
-       if (sb_rdonly(sb) || continue_fs)
-               return;
-
        /*
         * We force ERRORS_RO behavior when system is rebooting. Otherwise we
         * could panic during 'reboot -f' as the underlying device got already
@@ -679,6 +676,10 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,
                panic("EXT4-fs (device %s): panic forced after error\n",
                        sb->s_id);
        }
+
+       if (sb_rdonly(sb) || continue_fs)
+               return;
+
        ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
        /*
         * Make sure updated value of ->s_mount_flags will be visible before
@@ -1688,7 +1689,7 @@ enum {
        Opt_dioread_nolock, Opt_dioread_lock,
        Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,
        Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
-       Opt_prefetch_block_bitmaps,
+       Opt_no_prefetch_block_bitmaps, Opt_mb_optimize_scan,
 #ifdef CONFIG_EXT4_DEBUG
        Opt_fc_debug_max_replay, Opt_fc_debug_force
 #endif
@@ -1788,7 +1789,9 @@ static const match_table_t tokens = {
        {Opt_inlinecrypt, "inlinecrypt"},
        {Opt_nombcache, "nombcache"},
        {Opt_nombcache, "no_mbcache"},  /* for backward compatibility */
-       {Opt_prefetch_block_bitmaps, "prefetch_block_bitmaps"},
+       {Opt_removed, "prefetch_block_bitmaps"},
+       {Opt_no_prefetch_block_bitmaps, "no_prefetch_block_bitmaps"},
+       {Opt_mb_optimize_scan, "mb_optimize_scan=%d"},
        {Opt_removed, "check=none"},    /* mount option from ext2/3 */
        {Opt_removed, "nocheck"},       /* mount option from ext2/3 */
        {Opt_removed, "reservation"},   /* mount option from ext2/3 */
@@ -1821,6 +1824,8 @@ static ext4_fsblk_t get_sb_block(void **data)
 }
 
 #define DEFAULT_JOURNAL_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3))
+#define DEFAULT_MB_OPTIMIZE_SCAN       (-1)
+
 static const char deprecated_msg[] =
        "Mount option \"%s\" will be removed by %s\n"
        "Contact linux-ext4@vger.kernel.org if you think we should keep it.\n";
@@ -2007,8 +2012,9 @@ static const struct mount_opts {
        {Opt_max_dir_size_kb, 0, MOPT_GTE0},
        {Opt_test_dummy_encryption, 0, MOPT_STRING},
        {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
-       {Opt_prefetch_block_bitmaps, EXT4_MOUNT_PREFETCH_BLOCK_BITMAPS,
+       {Opt_no_prefetch_block_bitmaps, EXT4_MOUNT_NO_PREFETCH_BLOCK_BITMAPS,
         MOPT_SET},
+       {Opt_mb_optimize_scan, EXT4_MOUNT2_MB_OPTIMIZE_SCAN, MOPT_GTE0},
 #ifdef CONFIG_EXT4_DEBUG
        {Opt_fc_debug_force, EXT4_MOUNT2_JOURNAL_FAST_COMMIT,
         MOPT_SET | MOPT_2 | MOPT_EXT4_ONLY},
@@ -2090,9 +2096,15 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb,
        return 1;
 }
 
+struct ext4_parsed_options {
+       unsigned long journal_devnum;
+       unsigned int journal_ioprio;
+       int mb_optimize_scan;
+};
+
 static int handle_mount_opt(struct super_block *sb, char *opt, int token,
-                           substring_t *args, unsigned long *journal_devnum,
-                           unsigned int *journal_ioprio, int is_remount)
+                           substring_t *args, struct ext4_parsed_options *parsed_opts,
+                           int is_remount)
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        const struct mount_opts *m;
@@ -2249,7 +2261,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                                 "Cannot specify journal on remount");
                        return -1;
                }
-               *journal_devnum = arg;
+               parsed_opts->journal_devnum = arg;
        } else if (token == Opt_journal_path) {
                char *journal_path;
                struct inode *journal_inode;
@@ -2285,7 +2297,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                        return -1;
                }
 
-               *journal_devnum = new_encode_dev(journal_inode->i_rdev);
+               parsed_opts->journal_devnum = new_encode_dev(journal_inode->i_rdev);
                path_put(&path);
                kfree(journal_path);
        } else if (token == Opt_journal_ioprio) {
@@ -2294,7 +2306,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                                 " (must be 0-7)");
                        return -1;
                }
-               *journal_ioprio =
+               parsed_opts->journal_ioprio =
                        IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);
        } else if (token == Opt_test_dummy_encryption) {
                return ext4_set_test_dummy_encryption(sb, opt, &args[0],
@@ -2384,6 +2396,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                sbi->s_mount_opt |= m->mount_opt;
        } else if (token == Opt_data_err_ignore) {
                sbi->s_mount_opt &= ~m->mount_opt;
+       } else if (token == Opt_mb_optimize_scan) {
+               if (arg != 0 && arg != 1) {
+                       ext4_msg(sb, KERN_WARNING,
+                                "mb_optimize_scan should be set to 0 or 1.");
+                       return -1;
+               }
+               parsed_opts->mb_optimize_scan = arg;
        } else {
                if (!args->from)
                        arg = 1;
@@ -2411,8 +2430,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
 }
 
 static int parse_options(char *options, struct super_block *sb,
-                        unsigned long *journal_devnum,
-                        unsigned int *journal_ioprio,
+                        struct ext4_parsed_options *ret_opts,
                         int is_remount)
 {
        struct ext4_sb_info __maybe_unused *sbi = EXT4_SB(sb);
@@ -2432,8 +2450,8 @@ static int parse_options(char *options, struct super_block *sb,
                 */
                args[0].to = args[0].from = NULL;
                token = match_token(p, tokens, args);
-               if (handle_mount_opt(sb, p, token, args, journal_devnum,
-                                    journal_ioprio, is_remount) < 0)
+               if (handle_mount_opt(sb, p, token, args, ret_opts,
+                                    is_remount) < 0)
                        return 0;
        }
 #ifdef CONFIG_QUOTA
@@ -3023,9 +3041,6 @@ static void ext4_orphan_cleanup(struct super_block *sb,
                sb->s_flags &= ~SB_RDONLY;
        }
 #ifdef CONFIG_QUOTA
-       /* Needed for iput() to work correctly and not trash data */
-       sb->s_flags |= SB_ACTIVE;
-
        /*
         * Turn on quotas which were not enabled for read-only mounts if
         * filesystem has quota feature, so that they are updated correctly.
@@ -3691,11 +3706,11 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,
 
        elr->lr_super = sb;
        elr->lr_first_not_zeroed = start;
-       if (test_opt(sb, PREFETCH_BLOCK_BITMAPS))
-               elr->lr_mode = EXT4_LI_MODE_PREFETCH_BBITMAP;
-       else {
+       if (test_opt(sb, NO_PREFETCH_BLOCK_BITMAPS)) {
                elr->lr_mode = EXT4_LI_MODE_ITABLE;
                elr->lr_next_group = start;
+       } else {
+               elr->lr_mode = EXT4_LI_MODE_PREFETCH_BBITMAP;
        }
 
        /*
@@ -3726,7 +3741,7 @@ int ext4_register_li_request(struct super_block *sb,
                goto out;
        }
 
-       if (!test_opt(sb, PREFETCH_BLOCK_BITMAPS) &&
+       if (test_opt(sb, NO_PREFETCH_BLOCK_BITMAPS) &&
            (first_not_zeroed == ngroups || sb_rdonly(sb) ||
             !test_opt(sb, INIT_INODE_TABLE)))
                goto out;
@@ -4015,7 +4030,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        ext4_fsblk_t sb_block = get_sb_block(&data);
        ext4_fsblk_t logical_sb_block;
        unsigned long offset = 0;
-       unsigned long journal_devnum = 0;
        unsigned long def_mount_opts;
        struct inode *root;
        const char *descr;
@@ -4026,8 +4040,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        int needs_recovery, has_huge_files;
        __u64 blocks_count;
        int err = 0;
-       unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
        ext4_group_t first_not_zeroed;
+       struct ext4_parsed_options parsed_opts;
+
+       /* Set defaults for the variables that will be set during parsing */
+       parsed_opts.journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
+       parsed_opts.journal_devnum = 0;
+       parsed_opts.mb_optimize_scan = DEFAULT_MB_OPTIMIZE_SCAN;
 
        if ((data && !orig_data) || !sbi)
                goto out_free_base;
@@ -4273,8 +4292,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                                              GFP_KERNEL);
                if (!s_mount_opts)
                        goto failed_mount;
-               if (!parse_options(s_mount_opts, sb, &journal_devnum,
-                                  &journal_ioprio, 0)) {
+               if (!parse_options(s_mount_opts, sb, &parsed_opts, 0)) {
                        ext4_msg(sb, KERN_WARNING,
                                 "failed to parse options in superblock: %s",
                                 s_mount_opts);
@@ -4282,8 +4300,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                kfree(s_mount_opts);
        }
        sbi->s_def_mount_opt = sbi->s_mount_opt;
-       if (!parse_options((char *) data, sb, &journal_devnum,
-                          &journal_ioprio, 0))
+       if (!parse_options((char *) data, sb, &parsed_opts, 0))
                goto failed_mount;
 
 #ifdef CONFIG_UNICODE
@@ -4292,12 +4309,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                struct unicode_map *encoding;
                __u16 encoding_flags;
 
-               if (ext4_has_feature_encrypt(sb)) {
-                       ext4_msg(sb, KERN_ERR,
-                                "Can't mount with encoding and encryption");
-                       goto failed_mount;
-               }
-
                if (ext4_sb_read_encoding(es, &encoding_info,
                                          &encoding_flags)) {
                        ext4_msg(sb, KERN_ERR,
@@ -4774,7 +4785,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
         * root first: it may be modified in the journal!
         */
        if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) {
-               err = ext4_load_journal(sb, es, journal_devnum);
+               err = ext4_load_journal(sb, es, parsed_opts.journal_devnum);
                if (err)
                        goto failed_mount3a;
        } else if (test_opt(sb, NOLOAD) && !sb_rdonly(sb) &&
@@ -4874,7 +4885,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount_wq;
        }
 
-       set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
+       set_task_ioprio(sbi->s_journal->j_task, parsed_opts.journal_ioprio);
 
        sbi->s_journal->j_submit_inode_data_buffers =
                ext4_journal_submit_inode_data_buffers;
@@ -4980,6 +4991,19 @@ no_journal:
        ext4_fc_replay_cleanup(sb);
 
        ext4_ext_init(sb);
+
+       /*
+        * Enable optimize_scan if number of groups is > threshold. This can be
+        * turned off by passing "mb_optimize_scan=0". This can also be
+        * turned on forcefully by passing "mb_optimize_scan=1".
+        */
+       if (parsed_opts.mb_optimize_scan == 1)
+               set_opt2(sb, MB_OPTIMIZE_SCAN);
+       else if (parsed_opts.mb_optimize_scan == 0)
+               clear_opt2(sb, MB_OPTIMIZE_SCAN);
+       else if (sbi->s_groups_count >= MB_DEFAULT_LINEAR_SCAN_THRESHOLD)
+               set_opt2(sb, MB_OPTIMIZE_SCAN);
+
        err = ext4_mb_init(sb);
        if (err) {
                ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
@@ -4996,7 +5020,7 @@ no_journal:
                        ext4_journal_commit_callback;
 
        block = ext4_count_free_clusters(sb);
-       ext4_free_blocks_count_set(sbi->s_es, 
+       ext4_free_blocks_count_set(sbi->s_es,
                                   EXT4_C2B(sbi, block));
        err = percpu_counter_init(&sbi->s_freeclusters_counter, block,
                                  GFP_KERNEL);
@@ -5561,8 +5585,10 @@ static int ext4_commit_super(struct super_block *sb)
        struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
        int error = 0;
 
-       if (!sbh || block_device_ejected(sb))
-               return error;
+       if (!sbh)
+               return -EINVAL;
+       if (block_device_ejected(sb))
+               return -ENODEV;
 
        ext4_update_super(sb);
 
@@ -5813,13 +5839,16 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
        struct ext4_mount_options old_opts;
        int enable_quota = 0;
        ext4_group_t g;
-       unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
        int err = 0;
 #ifdef CONFIG_QUOTA
        int i, j;
        char *to_free[EXT4_MAXQUOTAS];
 #endif
        char *orig_data = kstrdup(data, GFP_KERNEL);
+       struct ext4_parsed_options parsed_opts;
+
+       parsed_opts.journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
+       parsed_opts.journal_devnum = 0;
 
        if (data && !orig_data)
                return -ENOMEM;
@@ -5850,7 +5879,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                        old_opts.s_qf_names[i] = NULL;
 #endif
        if (sbi->s_journal && sbi->s_journal->j_task->io_context)
-               journal_ioprio = sbi->s_journal->j_task->io_context->ioprio;
+               parsed_opts.journal_ioprio =
+                       sbi->s_journal->j_task->io_context->ioprio;
 
        /*
         * Some options can be enabled by ext4 and/or by VFS mount flag
@@ -5860,7 +5890,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
        vfs_flags = SB_LAZYTIME | SB_I_VERSION;
        sb->s_flags = (sb->s_flags & ~vfs_flags) | (*flags & vfs_flags);
 
-       if (!parse_options(data, sb, NULL, &journal_ioprio, 1)) {
+       if (!parse_options(data, sb, &parsed_opts, 1)) {
                err = -EINVAL;
                goto restore_opts;
        }
@@ -5910,7 +5940,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
 
        if (sbi->s_journal) {
                ext4_init_journal_params(sb, sbi->s_journal);
-               set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);
+               set_task_ioprio(sbi->s_journal->j_task, parsed_opts.journal_ioprio);
        }
 
        /* Flush outstanding errors before changing fs state */