Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / fs / ext4 / super.c
index faae0549347175eea372524ece2b0f7b7cf19d75..f43e526112ae837498c918637f50d7e15a004a0a 100644 (file)
@@ -2146,7 +2146,7 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
                return 0;
        case Opt_commit:
                if (result.uint_32 == 0)
-                       ctx->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE;
+                       result.uint_32 = JBD2_DEFAULT_MAX_COMMIT_AGE;
                else if (result.uint_32 > INT_MAX / HZ) {
                        ext4_msg(NULL, KERN_ERR,
                                 "Invalid commit interval %d, "
@@ -2883,7 +2883,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
 {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        struct ext4_super_block *es = sbi->s_es;
-       int def_errors, def_mount_opt = sbi->s_def_mount_opt;
+       int def_errors;
        const struct mount_opts *m;
        char sep = nodefs ? '\n' : ',';
 
@@ -2895,15 +2895,28 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
 
        for (m = ext4_mount_opts; m->token != Opt_err; m++) {
                int want_set = m->flags & MOPT_SET;
+               int opt_2 = m->flags & MOPT_2;
+               unsigned int mount_opt, def_mount_opt;
+
                if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
                    m->flags & MOPT_SKIP)
                        continue;
-               if (!nodefs && !(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
-                       continue; /* skip if same as the default */
+
+               if (opt_2) {
+                       mount_opt = sbi->s_mount_opt2;
+                       def_mount_opt = sbi->s_def_mount_opt2;
+               } else {
+                       mount_opt = sbi->s_mount_opt;
+                       def_mount_opt = sbi->s_def_mount_opt;
+               }
+               /* skip if same as the default */
+               if (!nodefs && !(m->mount_opt & (mount_opt ^ def_mount_opt)))
+                       continue;
+               /* select Opt_noFoo vs Opt_Foo */
                if ((want_set &&
-                    (sbi->s_mount_opt & m->mount_opt) != m->mount_opt) ||
-                   (!want_set && (sbi->s_mount_opt & m->mount_opt)))
-                       continue; /* select Opt_noFoo vs Opt_Foo */
+                    (mount_opt & m->mount_opt) != m->mount_opt) ||
+                   (!want_set && (mount_opt & m->mount_opt)))
+                       continue;
                SEQ_OPTS_PRINT("%s", token2str(m->token));
        }
 
@@ -2931,7 +2944,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
        if (nodefs || sbi->s_stripe)
                SEQ_OPTS_PRINT("stripe=%lu", sbi->s_stripe);
        if (nodefs || EXT4_MOUNT_DATA_FLAGS &
-                       (sbi->s_mount_opt ^ def_mount_opt)) {
+                       (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) {
                if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
                        SEQ_OPTS_PUTS("data=journal");
                else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
@@ -4727,7 +4740,6 @@ static int ext4_group_desc_init(struct super_block *sb,
        struct ext4_sb_info *sbi = EXT4_SB(sb);
        unsigned int db_count;
        ext4_fsblk_t block;
-       int ret;
        int i;
 
        db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
@@ -4767,8 +4779,7 @@ static int ext4_group_desc_init(struct super_block *sb,
                        ext4_msg(sb, KERN_ERR,
                               "can't read group descriptor %d", i);
                        sbi->s_gdb_count = i;
-                       ret = PTR_ERR(bh);
-                       goto out;
+                       return PTR_ERR(bh);
                }
                rcu_read_lock();
                rcu_dereference(sbi->s_group_desc)[i] = bh;
@@ -4777,13 +4788,10 @@ static int ext4_group_desc_init(struct super_block *sb,
        sbi->s_gdb_count = db_count;
        if (!ext4_check_descriptors(sb, logical_sb_block, first_not_zeroed)) {
                ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
-               ret = -EFSCORRUPTED;
-               goto out;
+               return -EFSCORRUPTED;
        }
+
        return 0;
-out:
-       ext4_group_desc_free(sbi);
-       return ret;
 }
 
 static int ext4_load_and_init_journal(struct super_block *sb,
@@ -5075,6 +5083,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
                goto failed_mount;
 
        sbi->s_def_mount_opt = sbi->s_mount_opt;
+       sbi->s_def_mount_opt2 = sbi->s_mount_opt2;
 
        err = ext4_check_opt_consistency(fc, sb);
        if (err < 0)
@@ -5209,14 +5218,14 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
        if (ext4_geometry_check(sb, es))
                goto failed_mount;
 
-       err = ext4_group_desc_init(sb, es, logical_sb_block, &first_not_zeroed);
-       if (err)
-               goto failed_mount;
-
        timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
        spin_lock_init(&sbi->s_error_lock);
        INIT_WORK(&sbi->s_error_work, flush_stashed_error_work);
 
+       err = ext4_group_desc_init(sb, es, logical_sb_block, &first_not_zeroed);
+       if (err)
+               goto failed_mount3;
+
        /* Register extent status tree shrinker */
        if (ext4_es_register_shrinker(sbi))
                goto failed_mount3;
@@ -5717,6 +5726,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
        return journal_inode;
 }
 
+static int ext4_journal_bmap(journal_t *journal, sector_t *block)
+{
+       struct ext4_map_blocks map;
+       int ret;
+
+       if (journal->j_inode == NULL)
+               return 0;
+
+       map.m_lblk = *block;
+       map.m_len = 1;
+       ret = ext4_map_blocks(NULL, journal->j_inode, &map, 0);
+       if (ret <= 0) {
+               ext4_msg(journal->j_inode->i_sb, KERN_CRIT,
+                        "journal bmap failed: block %llu ret %d\n",
+                        *block, ret);
+               jbd2_journal_abort(journal, ret ? ret : -EIO);
+               return ret;
+       }
+       *block = map.m_pblk;
+       return 0;
+}
+
 static journal_t *ext4_get_journal(struct super_block *sb,
                                   unsigned int journal_inum)
 {
@@ -5737,6 +5768,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
                return NULL;
        }
        journal->j_private = sb;
+       journal->j_bmap = ext4_journal_bmap;
        ext4_init_journal_params(sb, journal);
        return journal;
 }
@@ -5911,6 +5943,7 @@ static int ext4_load_journal(struct super_block *sb,
                err = jbd2_journal_wipe(journal, !really_read_only);
        if (!err) {
                char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
+
                if (save)
                        memcpy(save, ((char *) es) +
                               EXT4_S_ERR_START, EXT4_S_ERR_LEN);
@@ -5919,6 +5952,14 @@ static int ext4_load_journal(struct super_block *sb,
                        memcpy(((char *) es) + EXT4_S_ERR_START,
                               save, EXT4_S_ERR_LEN);
                kfree(save);
+               es->s_state |= cpu_to_le16(EXT4_SB(sb)->s_mount_state &
+                                          EXT4_ERROR_FS);
+               /* Write out restored error information to the superblock */
+               if (!bdev_read_only(sb->s_bdev)) {
+                       int err2;
+                       err2 = ext4_commit_super(sb);
+                       err = err ? : err2;
+               }
        }
 
        if (err) {
@@ -5937,8 +5978,11 @@ static int ext4_load_journal(struct super_block *sb,
        if (!really_read_only && journal_devnum &&
            journal_devnum != le32_to_cpu(es->s_journal_dev)) {
                es->s_journal_dev = cpu_to_le32(journal_devnum);
-
-               /* Make sure we flush the recovery flag to disk. */
+               ext4_commit_super(sb);
+       }
+       if (!really_read_only && journal_inum &&
+           journal_inum != le32_to_cpu(es->s_journal_inum)) {
+               es->s_journal_inum = cpu_to_le32(journal_inum);
                ext4_commit_super(sb);
        }
 
@@ -6145,11 +6189,13 @@ static int ext4_clear_journal_err(struct super_block *sb,
                errstr = ext4_decode_error(sb, j_errno, nbuf);
                ext4_warning(sb, "Filesystem error recorded "
                             "from previous mount: %s", errstr);
-               ext4_warning(sb, "Marking fs in need of filesystem check.");
 
                EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
                es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
-               ext4_commit_super(sb);
+               j_errno = ext4_commit_super(sb);
+               if (j_errno)
+                       return j_errno;
+               ext4_warning(sb, "Marked fs in need of filesystem check.");
 
                jbd2_journal_clear_err(journal);
                jbd2_journal_update_sb_errno(journal);