ext2: Parse mount options into a dedicated structure
[sfrench/cifs-2.6.git] / fs / ext2 / super.c
index fc18edd81815d1307fe311032c849e583c431f5f..05eae20d133f2f72ec0c02a8ac8a6ec426c14490 100644 (file)
@@ -52,7 +52,7 @@ void ext2_error(struct super_block *sb, const char *function,
        struct ext2_sb_info *sbi = EXT2_SB(sb);
        struct ext2_super_block *es = sbi->s_es;
 
-       if (!(sb->s_flags & MS_RDONLY)) {
+       if (!sb_rdonly(sb)) {
                spin_lock(&sbi->s_lock);
                sbi->s_mount_state |= EXT2_ERROR_FS;
                es->s_state |= cpu_to_le16(EXT2_ERROR_FS);
@@ -151,7 +151,7 @@ static void ext2_put_super (struct super_block * sb)
                ext2_xattr_destroy_cache(sbi->s_ea_block_cache);
                sbi->s_ea_block_cache = NULL;
        }
-       if (!(sb->s_flags & MS_RDONLY)) {
+       if (!sb_rdonly(sb)) {
                struct ext2_super_block *es = sbi->s_es;
 
                spin_lock(&sbi->s_lock);
@@ -479,10 +479,10 @@ static const match_table_t tokens = {
        {Opt_err, NULL}
 };
 
-static int parse_options(char *options, struct super_block *sb)
+static int parse_options(char *options, struct super_block *sb,
+                        struct ext2_mount_options *opts)
 {
        char *p;
-       struct ext2_sb_info *sbi = EXT2_SB(sb);
        substring_t args[MAX_OPT_ARGS];
        int option;
        kuid_t uid;
@@ -499,16 +499,16 @@ static int parse_options(char *options, struct super_block *sb)
                token = match_token(p, tokens, args);
                switch (token) {
                case Opt_bsd_df:
-                       clear_opt (sbi->s_mount_opt, MINIX_DF);
+                       clear_opt (opts->s_mount_opt, MINIX_DF);
                        break;
                case Opt_minix_df:
-                       set_opt (sbi->s_mount_opt, MINIX_DF);
+                       set_opt (opts->s_mount_opt, MINIX_DF);
                        break;
                case Opt_grpid:
-                       set_opt (sbi->s_mount_opt, GRPID);
+                       set_opt (opts->s_mount_opt, GRPID);
                        break;
                case Opt_nogrpid:
-                       clear_opt (sbi->s_mount_opt, GRPID);
+                       clear_opt (opts->s_mount_opt, GRPID);
                        break;
                case Opt_resuid:
                        if (match_int(&args[0], &option))
@@ -519,7 +519,7 @@ static int parse_options(char *options, struct super_block *sb)
                                return 0;
 
                        }
-                       sbi->s_resuid = uid;
+                       opts->s_resuid = uid;
                        break;
                case Opt_resgid:
                        if (match_int(&args[0], &option))
@@ -529,51 +529,51 @@ static int parse_options(char *options, struct super_block *sb)
                                ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option);
                                return 0;
                        }
-                       sbi->s_resgid = gid;
+                       opts->s_resgid = gid;
                        break;
                case Opt_sb:
                        /* handled by get_sb_block() instead of here */
                        /* *sb_block = match_int(&args[0]); */
                        break;
                case Opt_err_panic:
-                       clear_opt (sbi->s_mount_opt, ERRORS_CONT);
-                       clear_opt (sbi->s_mount_opt, ERRORS_RO);
-                       set_opt (sbi->s_mount_opt, ERRORS_PANIC);
+                       clear_opt (opts->s_mount_opt, ERRORS_CONT);
+                       clear_opt (opts->s_mount_opt, ERRORS_RO);
+                       set_opt (opts->s_mount_opt, ERRORS_PANIC);
                        break;
                case Opt_err_ro:
-                       clear_opt (sbi->s_mount_opt, ERRORS_CONT);
-                       clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
-                       set_opt (sbi->s_mount_opt, ERRORS_RO);
+                       clear_opt (opts->s_mount_opt, ERRORS_CONT);
+                       clear_opt (opts->s_mount_opt, ERRORS_PANIC);
+                       set_opt (opts->s_mount_opt, ERRORS_RO);
                        break;
                case Opt_err_cont:
-                       clear_opt (sbi->s_mount_opt, ERRORS_RO);
-                       clear_opt (sbi->s_mount_opt, ERRORS_PANIC);
-                       set_opt (sbi->s_mount_opt, ERRORS_CONT);
+                       clear_opt (opts->s_mount_opt, ERRORS_RO);
+                       clear_opt (opts->s_mount_opt, ERRORS_PANIC);
+                       set_opt (opts->s_mount_opt, ERRORS_CONT);
                        break;
                case Opt_nouid32:
-                       set_opt (sbi->s_mount_opt, NO_UID32);
+                       set_opt (opts->s_mount_opt, NO_UID32);
                        break;
                case Opt_nocheck:
-                       clear_opt (sbi->s_mount_opt, CHECK);
+                       clear_opt (opts->s_mount_opt, CHECK);
                        break;
                case Opt_debug:
-                       set_opt (sbi->s_mount_opt, DEBUG);
+                       set_opt (opts->s_mount_opt, DEBUG);
                        break;
                case Opt_oldalloc:
-                       set_opt (sbi->s_mount_opt, OLDALLOC);
+                       set_opt (opts->s_mount_opt, OLDALLOC);
                        break;
                case Opt_orlov:
-                       clear_opt (sbi->s_mount_opt, OLDALLOC);
+                       clear_opt (opts->s_mount_opt, OLDALLOC);
                        break;
                case Opt_nobh:
-                       set_opt (sbi->s_mount_opt, NOBH);
+                       set_opt (opts->s_mount_opt, NOBH);
                        break;
 #ifdef CONFIG_EXT2_FS_XATTR
                case Opt_user_xattr:
-                       set_opt (sbi->s_mount_opt, XATTR_USER);
+                       set_opt (opts->s_mount_opt, XATTR_USER);
                        break;
                case Opt_nouser_xattr:
-                       clear_opt (sbi->s_mount_opt, XATTR_USER);
+                       clear_opt (opts->s_mount_opt, XATTR_USER);
                        break;
 #else
                case Opt_user_xattr:
@@ -584,10 +584,10 @@ static int parse_options(char *options, struct super_block *sb)
 #endif
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
                case Opt_acl:
-                       set_opt(sbi->s_mount_opt, POSIX_ACL);
+                       set_opt(opts->s_mount_opt, POSIX_ACL);
                        break;
                case Opt_noacl:
-                       clear_opt(sbi->s_mount_opt, POSIX_ACL);
+                       clear_opt(opts->s_mount_opt, POSIX_ACL);
                        break;
 #else
                case Opt_acl:
@@ -598,13 +598,13 @@ static int parse_options(char *options, struct super_block *sb)
 #endif
                case Opt_xip:
                        ext2_msg(sb, KERN_INFO, "use dax instead of xip");
-                       set_opt(sbi->s_mount_opt, XIP);
+                       set_opt(opts->s_mount_opt, XIP);
                        /* Fall through */
                case Opt_dax:
 #ifdef CONFIG_FS_DAX
                        ext2_msg(sb, KERN_WARNING,
                "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
-                       set_opt(sbi->s_mount_opt, DAX);
+                       set_opt(opts->s_mount_opt, DAX);
 #else
                        ext2_msg(sb, KERN_INFO, "dax option not supported");
 #endif
@@ -613,11 +613,11 @@ static int parse_options(char *options, struct super_block *sb)
 #if defined(CONFIG_QUOTA)
                case Opt_quota:
                case Opt_usrquota:
-                       set_opt(sbi->s_mount_opt, USRQUOTA);
+                       set_opt(opts->s_mount_opt, USRQUOTA);
                        break;
 
                case Opt_grpquota:
-                       set_opt(sbi->s_mount_opt, GRPQUOTA);
+                       set_opt(opts->s_mount_opt, GRPQUOTA);
                        break;
 #else
                case Opt_quota:
@@ -629,11 +629,11 @@ static int parse_options(char *options, struct super_block *sb)
 #endif
 
                case Opt_reservation:
-                       set_opt(sbi->s_mount_opt, RESERVATION);
+                       set_opt(opts->s_mount_opt, RESERVATION);
                        ext2_msg(sb, KERN_INFO, "reservations ON");
                        break;
                case Opt_noreservation:
-                       clear_opt(sbi->s_mount_opt, RESERVATION);
+                       clear_opt(opts->s_mount_opt, RESERVATION);
                        ext2_msg(sb, KERN_INFO, "reservations OFF");
                        break;
                case Opt_ignore:
@@ -830,6 +830,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        int i, j;
        __le32 features;
        int err;
+       struct ext2_mount_options opts;
 
        err = -ENOMEM;
        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
@@ -890,35 +891,39 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        /* Set defaults before we parse the mount options */
        def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
        if (def_mount_opts & EXT2_DEFM_DEBUG)
-               set_opt(sbi->s_mount_opt, DEBUG);
+               set_opt(opts.s_mount_opt, DEBUG);
        if (def_mount_opts & EXT2_DEFM_BSDGROUPS)
-               set_opt(sbi->s_mount_opt, GRPID);
+               set_opt(opts.s_mount_opt, GRPID);
        if (def_mount_opts & EXT2_DEFM_UID16)
-               set_opt(sbi->s_mount_opt, NO_UID32);
+               set_opt(opts.s_mount_opt, NO_UID32);
 #ifdef CONFIG_EXT2_FS_XATTR
        if (def_mount_opts & EXT2_DEFM_XATTR_USER)
-               set_opt(sbi->s_mount_opt, XATTR_USER);
+               set_opt(opts.s_mount_opt, XATTR_USER);
 #endif
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
        if (def_mount_opts & EXT2_DEFM_ACL)
-               set_opt(sbi->s_mount_opt, POSIX_ACL);
+               set_opt(opts.s_mount_opt, POSIX_ACL);
 #endif
        
        if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC)
-               set_opt(sbi->s_mount_opt, ERRORS_PANIC);
+               set_opt(opts.s_mount_opt, ERRORS_PANIC);
        else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE)
-               set_opt(sbi->s_mount_opt, ERRORS_CONT);
+               set_opt(opts.s_mount_opt, ERRORS_CONT);
        else
-               set_opt(sbi->s_mount_opt, ERRORS_RO);
+               set_opt(opts.s_mount_opt, ERRORS_RO);
 
-       sbi->s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid));
-       sbi->s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid));
+       opts.s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid));
+       opts.s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid));
        
-       set_opt(sbi->s_mount_opt, RESERVATION);
+       set_opt(opts.s_mount_opt, RESERVATION);
 
-       if (!parse_options((char *) data, sb))
+       if (!parse_options((char *) data, sb, &opts))
                goto failed_mount;
 
+       sbi->s_mount_opt = opts.s_mount_opt;
+       sbi->s_resuid = opts.s_resuid;
+       sbi->s_resgid = opts.s_resgid;
+
        sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
                ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ?
                 MS_POSIXACL : 0);
@@ -943,8 +948,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
                        le32_to_cpu(features));
                goto failed_mount;
        }
-       if (!(sb->s_flags & MS_RDONLY) &&
-           (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
+       if (!sb_rdonly(sb) && (features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
                ext2_msg(sb, KERN_ERR, "error: couldn't mount RDWR because of "
                       "unsupported optional features (%x)",
                       le32_to_cpu(features));
@@ -1173,7 +1177,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
                ext2_msg(sb, KERN_WARNING,
                        "warning: mounting ext3 filesystem as ext2");
-       if (ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY))
+       if (ext2_setup_super (sb, es, sb_rdonly(sb)))
                sb->s_flags |= MS_RDONLY;
        ext2_write_super(sb);
        return 0;
@@ -1305,7 +1309,7 @@ static int ext2_unfreeze(struct super_block *sb)
 
 static void ext2_write_super(struct super_block *sb)
 {
-       if (!(sb->s_flags & MS_RDONLY))
+       if (!sb_rdonly(sb))
                ext2_sync_fs(sb, 1);
 }
 
@@ -1313,46 +1317,36 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
 {
        struct ext2_sb_info * sbi = EXT2_SB(sb);
        struct ext2_super_block * es;
-       struct ext2_mount_options old_opts;
-       unsigned long old_sb_flags;
+       struct ext2_mount_options new_opts;
        int err;
 
        sync_filesystem(sb);
        spin_lock(&sbi->s_lock);
 
-       /* Store the old options */
-       old_sb_flags = sb->s_flags;
-       old_opts.s_mount_opt = sbi->s_mount_opt;
-       old_opts.s_resuid = sbi->s_resuid;
-       old_opts.s_resgid = sbi->s_resgid;
+       new_opts.s_mount_opt = sbi->s_mount_opt;
+       new_opts.s_resuid = sbi->s_resuid;
+       new_opts.s_resgid = sbi->s_resgid;
 
        /*
         * Allow the "check" option to be passed as a remount option.
         */
-       if (!parse_options(data, sb)) {
-               err = -EINVAL;
-               goto restore_opts;
+       if (!parse_options(data, sb, &new_opts)) {
+               spin_unlock(&sbi->s_lock);
+               return -EINVAL;
        }
 
-       sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
-               ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
-
        es = sbi->s_es;
-       if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT2_MOUNT_DAX) {
+       if ((sbi->s_mount_opt ^ new_opts.s_mount_opt) & EXT2_MOUNT_DAX) {
                ext2_msg(sb, KERN_WARNING, "warning: refusing change of "
                         "dax flag with busy inodes while remounting");
-               sbi->s_mount_opt ^= EXT2_MOUNT_DAX;
-       }
-       if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
-               spin_unlock(&sbi->s_lock);
-               return 0;
+               new_opts.s_mount_opt ^= EXT2_MOUNT_DAX;
        }
+       if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb))
+               goto out_set;
        if (*flags & MS_RDONLY) {
                if (le16_to_cpu(es->s_state) & EXT2_VALID_FS ||
-                   !(sbi->s_mount_state & EXT2_VALID_FS)) {
-                       spin_unlock(&sbi->s_lock);
-                       return 0;
-               }
+                   !(sbi->s_mount_state & EXT2_VALID_FS))
+                       goto out_set;
 
                /*
                 * OK, we are remounting a valid rw partition rdonly, so set
@@ -1363,22 +1357,20 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
                spin_unlock(&sbi->s_lock);
 
                err = dquot_suspend(sb, -1);
-               if (err < 0) {
-                       spin_lock(&sbi->s_lock);
-                       goto restore_opts;
-               }
+               if (err < 0)
+                       return err;
 
                ext2_sync_super(sb, es, 1);
        } else {
                __le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
                                               ~EXT2_FEATURE_RO_COMPAT_SUPP);
                if (ret) {
+                       spin_unlock(&sbi->s_lock);
                        ext2_msg(sb, KERN_WARNING,
                                "warning: couldn't remount RDWR because of "
                                "unsupported optional features (%x).",
                                le32_to_cpu(ret));
-                       err = -EROFS;
-                       goto restore_opts;
+                       return -EROFS;
                }
                /*
                 * Mounting a RDONLY partition read-write, so reread and
@@ -1395,14 +1387,16 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
                dquot_resume(sb, -1);
        }
 
-       return 0;
-restore_opts:
-       sbi->s_mount_opt = old_opts.s_mount_opt;
-       sbi->s_resuid = old_opts.s_resuid;
-       sbi->s_resgid = old_opts.s_resgid;
-       sb->s_flags = old_sb_flags;
+       spin_lock(&sbi->s_lock);
+out_set:
+       sbi->s_mount_opt = new_opts.s_mount_opt;
+       sbi->s_resuid = new_opts.s_resuid;
+       sbi->s_resgid = new_opts.s_resgid;
+       sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+               ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
        spin_unlock(&sbi->s_lock);
-       return err;
+
+       return 0;
 }
 
 static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)