tree-wide: convert open calls to remove spaces to skip_spaces() lib function
[safe/jmp/linux-2.6] / fs / ext4 / super.c
index 3f7e701..827bde1 100644 (file)
 #define CREATE_TRACE_POINTS
 #include <trace/events/ext4.h>
 
-static int default_mb_history_length = 1000;
-
-module_param_named(default_mb_history_length, default_mb_history_length,
-                  int, 0644);
-MODULE_PARM_DESC(default_mb_history_length,
-                "Default number of entries saved for mb_history");
-
 struct proc_dir_entry *ext4_proc_root;
 static struct kset *ext4_kset;
 
@@ -610,10 +603,6 @@ static void ext4_put_super(struct super_block *sb)
        if (sb->s_dirt)
                ext4_commit_super(sb, 1);
 
-       ext4_release_system_zone(sb);
-       ext4_mb_release(sb);
-       ext4_ext_release(sb);
-       ext4_xattr_put_super(sb);
        if (sbi->s_journal) {
                err = jbd2_journal_destroy(sbi->s_journal);
                sbi->s_journal = NULL;
@@ -621,6 +610,12 @@ static void ext4_put_super(struct super_block *sb)
                        ext4_abort(sb, __func__,
                                   "Couldn't clean up the journal");
        }
+
+       ext4_release_system_zone(sb);
+       ext4_mb_release(sb);
+       ext4_ext_release(sb);
+       ext4_xattr_put_super(sb);
+
        if (!(sb->s_flags & MS_RDONLY)) {
                EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
                es->s_state = cpu_to_le16(sbi->s_mount_state);
@@ -711,6 +706,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
        spin_lock_init(&(ei->i_block_reservation_lock));
        INIT_LIST_HEAD(&ei->i_aio_dio_complete_list);
        ei->cur_aio_dio = NULL;
+       ei->i_sync_tid = 0;
+       ei->i_datasync_tid = 0;
 
        return &ei->vfs_inode;
 }
@@ -772,9 +769,22 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
 #if defined(CONFIG_QUOTA)
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
-       if (sbi->s_jquota_fmt)
-               seq_printf(seq, ",jqfmt=%s",
-               (sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0");
+       if (sbi->s_jquota_fmt) {
+               char *fmtname = "";
+
+               switch (sbi->s_jquota_fmt) {
+               case QFMT_VFS_OLD:
+                       fmtname = "vfsold";
+                       break;
+               case QFMT_VFS_V0:
+                       fmtname = "vfsv0";
+                       break;
+               case QFMT_VFS_V1:
+                       fmtname = "vfsv1";
+                       break;
+               }
+               seq_printf(seq, ",jqfmt=%s", fmtname);
+       }
 
        if (sbi->s_qf_names[USRQUOTA])
                seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
@@ -906,6 +916,12 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
        if (test_opt(sb, NO_AUTO_DA_ALLOC))
                seq_puts(seq, ",noauto_da_alloc");
 
+       if (test_opt(sb, DISCARD))
+               seq_puts(seq, ",discard");
+
+       if (test_opt(sb, NOLOAD))
+               seq_puts(seq, ",norecovery");
+
        ext4_show_quota_options(seq, sb);
 
        return 0;
@@ -1079,14 +1095,15 @@ enum {
        Opt_journal_update, Opt_journal_dev,
        Opt_journal_checksum, Opt_journal_async_commit,
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
-       Opt_data_err_abort, Opt_data_err_ignore, Opt_mb_history_length,
+       Opt_data_err_abort, Opt_data_err_ignore,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
-       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
-       Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
-       Opt_usrquota, Opt_grpquota, Opt_i_version,
+       Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
+       Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
+       Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version,
        Opt_stripe, Opt_delalloc, Opt_nodelalloc,
        Opt_block_validity, Opt_noblock_validity,
-       Opt_inode_readahead_blks, Opt_journal_ioprio
+       Opt_inode_readahead_blks, Opt_journal_ioprio,
+       Opt_discard, Opt_nodiscard,
 };
 
 static const match_table_t tokens = {
@@ -1111,6 +1128,7 @@ static const match_table_t tokens = {
        {Opt_acl, "acl"},
        {Opt_noacl, "noacl"},
        {Opt_noload, "noload"},
+       {Opt_noload, "norecovery"},
        {Opt_nobh, "nobh"},
        {Opt_bh, "bh"},
        {Opt_commit, "commit=%u"},
@@ -1126,13 +1144,13 @@ static const match_table_t tokens = {
        {Opt_data_writeback, "data=writeback"},
        {Opt_data_err_abort, "data_err=abort"},
        {Opt_data_err_ignore, "data_err=ignore"},
-       {Opt_mb_history_length, "mb_history_length=%u"},
        {Opt_offusrjquota, "usrjquota="},
        {Opt_usrjquota, "usrjquota=%s"},
        {Opt_offgrpjquota, "grpjquota="},
        {Opt_grpjquota, "grpjquota=%s"},
        {Opt_jqfmt_vfsold, "jqfmt=vfsold"},
        {Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
+       {Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
        {Opt_grpquota, "grpquota"},
        {Opt_noquota, "noquota"},
        {Opt_quota, "quota"},
@@ -1152,6 +1170,8 @@ static const match_table_t tokens = {
        {Opt_auto_da_alloc, "auto_da_alloc=%u"},
        {Opt_auto_da_alloc, "auto_da_alloc"},
        {Opt_noauto_da_alloc, "noauto_da_alloc"},
+       {Opt_discard, "discard"},
+       {Opt_nodiscard, "nodiscard"},
        {Opt_err, NULL},
 };
 
@@ -1308,9 +1328,11 @@ static int parse_options(char *options, struct super_block *sb,
                        *journal_devnum = option;
                        break;
                case Opt_journal_checksum:
-                       break;  /* Kept for backwards compatibility */
+                       set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
+                       break;
                case Opt_journal_async_commit:
                        set_opt(sbi->s_mount_opt, JOURNAL_ASYNC_COMMIT);
+                       set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM);
                        break;
                case Opt_noload:
                        set_opt(sbi->s_mount_opt, NOLOAD);
@@ -1367,13 +1389,6 @@ static int parse_options(char *options, struct super_block *sb,
                case Opt_data_err_ignore:
                        clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
                        break;
-               case Opt_mb_history_length:
-                       if (match_int(&args[0], &option))
-                               return 0;
-                       if (option < 0)
-                               return 0;
-                       sbi->s_mb_history_max = option;
-                       break;
 #ifdef CONFIG_QUOTA
                case Opt_usrjquota:
                        qtype = USRQUOTA;
@@ -1438,6 +1453,9 @@ clear_qf_name:
                        goto set_qf_format;
                case Opt_jqfmt_vfsv0:
                        qfmt = QFMT_VFS_V0;
+                       goto set_qf_format;
+               case Opt_jqfmt_vfsv1:
+                       qfmt = QFMT_VFS_V1;
 set_qf_format:
                        if (sb_any_quota_loaded(sb) &&
                            sbi->s_jquota_fmt != qfmt) {
@@ -1480,6 +1498,7 @@ set_qf_format:
                case Opt_offgrpjquota:
                case Opt_jqfmt_vfsold:
                case Opt_jqfmt_vfsv0:
+               case Opt_jqfmt_vfsv1:
                        ext4_msg(sb, KERN_ERR,
                                "journaled quota options not supported");
                        break;
@@ -1578,6 +1597,12 @@ set_qf_format:
                        else
                                set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC);
                        break;
+               case Opt_discard:
+                       set_opt(sbi->s_mount_opt, DISCARD);
+                       break;
+               case Opt_nodiscard:
+                       clear_opt(sbi->s_mount_opt, DISCARD);
+                       break;
                default:
                        ext4_msg(sb, KERN_ERR,
                               "Unrecognized mount option \"%s\" "
@@ -1673,13 +1698,6 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
                        EXT4_INODES_PER_GROUP(sb),
                        sbi->s_mount_opt);
 
-       if (EXT4_SB(sb)->s_journal) {
-               ext4_msg(sb, KERN_INFO, "%s journal on %s",
-                      EXT4_SB(sb)->s_journal->j_inode ? "internal" :
-                      "external", EXT4_SB(sb)->s_journal->j_devname);
-       } else {
-               ext4_msg(sb, KERN_INFO, "no journal");
-       }
        return res;
 }
 
@@ -1693,14 +1711,14 @@ static int ext4_fill_flex_info(struct super_block *sb)
        size_t size;
        int i;
 
-       if (!sbi->s_es->s_log_groups_per_flex) {
+       sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
+       groups_per_flex = 1 << sbi->s_log_groups_per_flex;
+
+       if (groups_per_flex < 2) {
                sbi->s_log_groups_per_flex = 0;
                return 1;
        }
 
-       sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
-       groups_per_flex = 1 << sbi->s_log_groups_per_flex;
-
        /* We allocate both existing and potentially added groups */
        flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
                        ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
@@ -2119,11 +2137,8 @@ static int parse_strtoul(const char *buf,
 {
        char *endp;
 
-       while (*buf && isspace(*buf))
-               buf++;
-       *value = simple_strtoul(buf, &endp, 0);
-       while (*endp && isspace(*endp))
-               endp++;
+       *value = simple_strtoul(skip_spaces(buf), &endp, 0);
+       endp = skip_spaces(endp);
        if (*endp || *value > max)
                return -EINVAL;
 
@@ -2442,7 +2457,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        sbi->s_commit_interval = JBD2_DEFAULT_MAX_COMMIT_AGE * HZ;
        sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME;
        sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME;
-       sbi->s_mb_history_max = default_mb_history_length;
 
        set_opt(sbi->s_mount_opt, BARRIER);
 
@@ -2742,26 +2756,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
            EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) {
                if (ext4_load_journal(sb, es, journal_devnum))
                        goto failed_mount3;
-               if (!(sb->s_flags & MS_RDONLY) &&
-                   EXT4_SB(sb)->s_journal->j_failed_commit) {
-                       ext4_msg(sb, KERN_CRIT, "error: "
-                              "ext4_fill_super: Journal transaction "
-                              "%u is corrupt",
-                              EXT4_SB(sb)->s_journal->j_failed_commit);
-                       if (test_opt(sb, ERRORS_RO)) {
-                               ext4_msg(sb, KERN_CRIT,
-                                      "Mounting filesystem read-only");
-                               sb->s_flags |= MS_RDONLY;
-                               EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
-                               es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
-                       }
-                       if (test_opt(sb, ERRORS_PANIC)) {
-                               EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
-                               es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
-                               ext4_commit_super(sb, 1);
-                               goto failed_mount4;
-                       }
-               }
        } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
              EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
                ext4_msg(sb, KERN_ERR, "required journal recovery "
@@ -2782,14 +2776,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                goto failed_mount4;
        }
 
-       jbd2_journal_set_features(sbi->s_journal,
-                                 JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
-       if (test_opt(sb, JOURNAL_ASYNC_COMMIT))
-               jbd2_journal_set_features(sbi->s_journal, 0, 0,
+       if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
+               jbd2_journal_set_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0,
                                JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
-       else
+       } else if (test_opt(sb, JOURNAL_CHECKSUM)) {
+               jbd2_journal_set_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0);
                jbd2_journal_clear_features(sbi->s_journal, 0, 0,
                                JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+       } else {
+               jbd2_journal_clear_features(sbi->s_journal,
+                               JBD2_FEATURE_COMPAT_CHECKSUM, 0,
+                               JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT);
+       }
 
        /* We have now updated the journal if required, so we can
         * validate the data journaling mode. */
@@ -2885,12 +2885,12 @@ no_journal:
                         "available");
        }
 
-       if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) {
+       if (test_opt(sb, DELALLOC) &&
+           (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)) {
                ext4_msg(sb, KERN_WARNING, "Ignoring delalloc option - "
                         "requested data journaling mode");
                clear_opt(sbi->s_mount_opt, DELALLOC);
-       } else if (test_opt(sb, DELALLOC))
-               ext4_msg(sb, KERN_INFO, "delayed allocation enabled");
+       }
 
        err = ext4_setup_system_zone(sb);
        if (err) {
@@ -3202,9 +3202,7 @@ static int ext4_load_journal(struct super_block *sb,
                        return -EINVAL;
        }
 
-       if (journal->j_flags & JBD2_BARRIER)
-               ext4_msg(sb, KERN_INFO, "barriers enabled");
-       else
+       if (!(journal->j_flags & JBD2_BARRIER))
                ext4_msg(sb, KERN_INFO, "barriers disabled");
 
        if (!really_read_only && test_opt(sb, UPDATE_JOURNAL)) {
@@ -3685,13 +3683,11 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
        buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter) -
                       percpu_counter_sum_positive(&sbi->s_dirtyblocks_counter);
-       ext4_free_blocks_count_set(es, buf->f_bfree);
        buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
        if (buf->f_bfree < ext4_r_blocks_count(es))
                buf->f_bavail = 0;
        buf->f_files = le32_to_cpu(es->s_inodes_count);
        buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
-       es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
        buf->f_namelen = EXT4_NAME_LEN;
        fsid = le64_to_cpup((void *)es->s_uuid) ^
               le64_to_cpup((void *)es->s_uuid + sizeof(u64));
@@ -3983,35 +3979,66 @@ static int ext4_get_sb(struct file_system_type *fs_type, int flags,
        return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt);
 }
 
-static struct file_system_type ext4_fs_type = {
+#if !defined(CONTIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+static struct file_system_type ext2_fs_type = {
        .owner          = THIS_MODULE,
-       .name           = "ext4",
+       .name           = "ext2",
        .get_sb         = ext4_get_sb,
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-#ifdef CONFIG_EXT4DEV_COMPAT
-static int ext4dev_get_sb(struct file_system_type *fs_type, int flags,
-                         const char *dev_name, void *data,struct vfsmount *mnt)
+static inline void register_as_ext2(void)
 {
-       printk(KERN_WARNING "EXT4-fs (%s): Update your userspace programs "
-              "to mount using ext4\n", dev_name);
-       printk(KERN_WARNING "EXT4-fs (%s): ext4dev backwards compatibility "
-              "will go away by 2.6.31\n", dev_name);
-       return get_sb_bdev(fs_type, flags, dev_name, data, ext4_fill_super,mnt);
+       int err = register_filesystem(&ext2_fs_type);
+       if (err)
+               printk(KERN_WARNING
+                      "EXT4-fs: Unable to register as ext2 (%d)\n", err);
+}
+
+static inline void unregister_as_ext2(void)
+{
+       unregister_filesystem(&ext2_fs_type);
 }
+#else
+static inline void register_as_ext2(void) { }
+static inline void unregister_as_ext2(void) { }
+#endif
 
-static struct file_system_type ext4dev_fs_type = {
+#if !defined(CONTIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)
+static struct file_system_type ext3_fs_type = {
        .owner          = THIS_MODULE,
-       .name           = "ext4dev",
-       .get_sb         = ext4dev_get_sb,
+       .name           = "ext3",
+       .get_sb         = ext4_get_sb,
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
-MODULE_ALIAS("ext4dev");
+
+static inline void register_as_ext3(void)
+{
+       int err = register_filesystem(&ext3_fs_type);
+       if (err)
+               printk(KERN_WARNING
+                      "EXT4-fs: Unable to register as ext3 (%d)\n", err);
+}
+
+static inline void unregister_as_ext3(void)
+{
+       unregister_filesystem(&ext3_fs_type);
+}
+#else
+static inline void register_as_ext3(void) { }
+static inline void unregister_as_ext3(void) { }
 #endif
 
+static struct file_system_type ext4_fs_type = {
+       .owner          = THIS_MODULE,
+       .name           = "ext4",
+       .get_sb         = ext4_get_sb,
+       .kill_sb        = kill_block_super,
+       .fs_flags       = FS_REQUIRES_DEV,
+};
+
 static int __init init_ext4_fs(void)
 {
        int err;
@@ -4033,18 +4060,15 @@ static int __init init_ext4_fs(void)
        err = init_inodecache();
        if (err)
                goto out1;
+       register_as_ext2();
+       register_as_ext3();
        err = register_filesystem(&ext4_fs_type);
        if (err)
                goto out;
-#ifdef CONFIG_EXT4DEV_COMPAT
-       err = register_filesystem(&ext4dev_fs_type);
-       if (err) {
-               unregister_filesystem(&ext4_fs_type);
-               goto out;
-       }
-#endif
        return 0;
 out:
+       unregister_as_ext2();
+       unregister_as_ext3();
        destroy_inodecache();
 out1:
        exit_ext4_xattr();
@@ -4060,10 +4084,9 @@ out4:
 
 static void __exit exit_ext4_fs(void)
 {
+       unregister_as_ext2();
+       unregister_as_ext3();
        unregister_filesystem(&ext4_fs_type);
-#ifdef CONFIG_EXT4DEV_COMPAT
-       unregister_filesystem(&ext4dev_fs_type);
-#endif
        destroy_inodecache();
        exit_ext4_xattr();
        exit_ext4_mballoc();