ocfs2: convert to the new mount API
authorEric Sandeen <sandeen@redhat.com>
Mon, 28 Oct 2024 14:41:15 +0000 (09:41 -0500)
committerAndrew Morton <akpm@linux-foundation.org>
Mon, 13 Jan 2025 04:21:06 +0000 (20:21 -0800)
Convert ocfs2 to the new mount API.

Link: https://lkml.kernel.org/r/20241028144443.609151-3-sandeen@redhat.com
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Tested-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Acked-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Tested-by: Joseph Qi <joseph.qi@linux.alibaba.com>
Cc: Changwei Ge <gechangwei@live.cn>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Jun Piao <piaojun@huawei.com>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Cc: Mark Fasheh <mark@fasheh.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
fs/ocfs2/ocfs2_trace.h
fs/ocfs2/super.c

index 0511c69..54ed149 100644 (file)
@@ -1658,34 +1658,34 @@ TRACE_EVENT(ocfs2_remount,
 );
 
 TRACE_EVENT(ocfs2_fill_super,
-       TP_PROTO(void *sb, void *data, int silent),
-       TP_ARGS(sb, data, silent),
+       TP_PROTO(void *sb, void *fc, int silent),
+       TP_ARGS(sb, fc, silent),
        TP_STRUCT__entry(
                __field(void *, sb)
-               __field(void *, data)
+               __field(void *, fc)
                __field(int, silent)
        ),
        TP_fast_assign(
                __entry->sb = sb;
-               __entry->data = data;
+               __entry->fc = fc;
                __entry->silent = silent;
        ),
        TP_printk("%p %p %d", __entry->sb,
-                 __entry->data, __entry->silent)
+                 __entry->fc, __entry->silent)
 );
 
 TRACE_EVENT(ocfs2_parse_options,
-       TP_PROTO(int is_remount, char *options),
-       TP_ARGS(is_remount, options),
+       TP_PROTO(int is_remount, const char *option),
+       TP_ARGS(is_remount, option),
        TP_STRUCT__entry(
                __field(int, is_remount)
-               __string(options, options)
+               __string(option, option)
        ),
        TP_fast_assign(
                __entry->is_remount = is_remount;
-               __assign_str(options);
+               __assign_str(option);
        ),
-       TP_printk("%d %s", __entry->is_remount, __get_str(options))
+       TP_printk("%d %s", __entry->is_remount, __get_str(option))
 );
 
 DEFINE_OCFS2_POINTER_EVENT(ocfs2_put_super);
index c79b429..4319cb2 100644 (file)
 #include <linux/blkdev.h>
 #include <linux/socket.h>
 #include <linux/inet.h>
-#include <linux/parser.h>
+#include <linux/fs_parser.h>
+#include <linux/fs_context.h>
 #include <linux/crc32.h>
 #include <linux/debugfs.h>
-#include <linux/mount.h>
 #include <linux/seq_file.h>
 #include <linux/quotaops.h>
 #include <linux/signal.h>
@@ -80,17 +80,15 @@ struct mount_options
        unsigned int    resv_level;
        int             dir_resv_level;
        char            cluster_stack[OCFS2_STACK_LABEL_LEN + 1];
+       bool            user_stack;
 };
 
-static int ocfs2_parse_options(struct super_block *sb, char *options,
-                              struct mount_options *mopt,
-                              int is_remount);
+static int ocfs2_parse_param(struct fs_context *fc, struct fs_parameter *param);
 static int ocfs2_check_set_options(struct super_block *sb,
                                   struct mount_options *options);
 static int ocfs2_show_options(struct seq_file *s, struct dentry *root);
 static void ocfs2_put_super(struct super_block *sb);
 static int ocfs2_mount_volume(struct super_block *sb);
-static int ocfs2_remount(struct super_block *sb, int *flags, char *data);
 static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err);
 static int ocfs2_initialize_mem_caches(void);
 static void ocfs2_free_mem_caches(void);
@@ -135,7 +133,6 @@ static const struct super_operations ocfs2_sops = {
        .evict_inode    = ocfs2_evict_inode,
        .sync_fs        = ocfs2_sync_fs,
        .put_super      = ocfs2_put_super,
-       .remount_fs     = ocfs2_remount,
        .show_options   = ocfs2_show_options,
        .quota_read     = ocfs2_quota_read,
        .quota_write    = ocfs2_quota_write,
@@ -144,15 +141,10 @@ static const struct super_operations ocfs2_sops = {
 
 enum {
        Opt_barrier,
-       Opt_err_panic,
-       Opt_err_ro,
+       Opt_errors,
        Opt_intr,
-       Opt_nointr,
-       Opt_hb_none,
-       Opt_hb_local,
-       Opt_hb_global,
-       Opt_data_ordered,
-       Opt_data_writeback,
+       Opt_heartbeat,
+       Opt_data,
        Opt_atime_quantum,
        Opt_slot,
        Opt_commit,
@@ -160,52 +152,64 @@ enum {
        Opt_localflocks,
        Opt_stack,
        Opt_user_xattr,
-       Opt_nouser_xattr,
        Opt_inode64,
        Opt_acl,
-       Opt_noacl,
        Opt_usrquota,
        Opt_grpquota,
-       Opt_coherency_buffered,
-       Opt_coherency_full,
+       Opt_coherency,
        Opt_resv_level,
        Opt_dir_resv_level,
        Opt_journal_async_commit,
-       Opt_err_cont,
-       Opt_err,
 };
 
-static const match_table_t tokens = {
-       {Opt_barrier, "barrier=%u"},
-       {Opt_err_panic, "errors=panic"},
-       {Opt_err_ro, "errors=remount-ro"},
-       {Opt_intr, "intr"},
-       {Opt_nointr, "nointr"},
-       {Opt_hb_none, OCFS2_HB_NONE},
-       {Opt_hb_local, OCFS2_HB_LOCAL},
-       {Opt_hb_global, OCFS2_HB_GLOBAL},
-       {Opt_data_ordered, "data=ordered"},
-       {Opt_data_writeback, "data=writeback"},
-       {Opt_atime_quantum, "atime_quantum=%u"},
-       {Opt_slot, "preferred_slot=%u"},
-       {Opt_commit, "commit=%u"},
-       {Opt_localalloc, "localalloc=%d"},
-       {Opt_localflocks, "localflocks"},
-       {Opt_stack, "cluster_stack=%s"},
-       {Opt_user_xattr, "user_xattr"},
-       {Opt_nouser_xattr, "nouser_xattr"},
-       {Opt_inode64, "inode64"},
-       {Opt_acl, "acl"},
-       {Opt_noacl, "noacl"},
-       {Opt_usrquota, "usrquota"},
-       {Opt_grpquota, "grpquota"},
-       {Opt_coherency_buffered, "coherency=buffered"},
-       {Opt_coherency_full, "coherency=full"},
-       {Opt_resv_level, "resv_level=%u"},
-       {Opt_dir_resv_level, "dir_resv_level=%u"},
-       {Opt_journal_async_commit, "journal_async_commit"},
-       {Opt_err_cont, "errors=continue"},
-       {Opt_err, NULL}
+static const struct constant_table ocfs2_param_errors[] = {
+       {"panic",       OCFS2_MOUNT_ERRORS_PANIC},
+       {"remount-ro",  OCFS2_MOUNT_ERRORS_ROFS},
+       {"continue",    OCFS2_MOUNT_ERRORS_CONT},
+       {}
+};
+
+static const struct constant_table ocfs2_param_heartbeat[] = {
+       {"local",       OCFS2_MOUNT_HB_LOCAL},
+       {"none",        OCFS2_MOUNT_HB_NONE},
+       {"global",      OCFS2_MOUNT_HB_GLOBAL},
+       {}
+};
+
+static const struct constant_table ocfs2_param_data[] = {
+       {"writeback",   OCFS2_MOUNT_DATA_WRITEBACK},
+       {"ordered",     0},
+       {}
+};
+
+static const struct constant_table ocfs2_param_coherency[] = {
+       {"buffered",    OCFS2_MOUNT_COHERENCY_BUFFERED},
+       {"full",        0},
+       {}
+};
+
+static const struct fs_parameter_spec ocfs2_param_spec[] = {
+       fsparam_u32     ("barrier",     Opt_barrier),
+       fsparam_enum    ("errors",      Opt_errors,     ocfs2_param_errors),
+       fsparam_flag_no ("intr",        Opt_intr),
+       fsparam_enum    ("heartbeat",   Opt_heartbeat,  ocfs2_param_heartbeat),
+       fsparam_enum    ("data",        Opt_data,       ocfs2_param_data),
+       fsparam_u32     ("atime_quantum", Opt_atime_quantum),
+       fsparam_u32     ("preferred_slot", Opt_slot),
+       fsparam_u32     ("commit",      Opt_commit),
+       fsparam_s32     ("localalloc",  Opt_localalloc),
+       fsparam_flag    ("localflocks", Opt_localflocks),
+       fsparam_string  ("cluster_stack", Opt_stack),
+       fsparam_flag_no ("user_xattr",  Opt_user_xattr),
+       fsparam_flag    ("inode64",     Opt_inode64),
+       fsparam_flag_no ("acl",         Opt_acl),
+       fsparam_flag    ("usrquota",    Opt_usrquota),
+       fsparam_flag    ("grpquota",    Opt_grpquota),
+       fsparam_enum    ("coherency",   Opt_coherency,  ocfs2_param_coherency),
+       fsparam_u32     ("resv_level",  Opt_resv_level),
+       fsparam_u32     ("dir_resv_level",      Opt_dir_resv_level),
+       fsparam_flag    ("journal_async_commit", Opt_journal_async_commit),
+       {}
 };
 
 #ifdef CONFIG_DEBUG_FS
@@ -600,32 +604,32 @@ static unsigned long long ocfs2_max_file_offset(unsigned int bbits,
        return (((unsigned long long)bytes) << bitshift) - trim;
 }
 
-static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
+static int ocfs2_reconfigure(struct fs_context *fc)
 {
        int incompat_features;
        int ret = 0;
-       struct mount_options parsed_options;
+       struct mount_options *parsed_options = fc->fs_private;
+       struct super_block *sb = fc->root->d_sb;
        struct ocfs2_super *osb = OCFS2_SB(sb);
        u32 tmp;
 
        sync_filesystem(sb);
 
-       if (!ocfs2_parse_options(sb, data, &parsed_options, 1) ||
-           !ocfs2_check_set_options(sb, &parsed_options)) {
+       if (!ocfs2_check_set_options(sb, parsed_options)) {
                ret = -EINVAL;
                goto out;
        }
 
        tmp = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL |
                OCFS2_MOUNT_HB_NONE;
-       if ((osb->s_mount_opt & tmp) != (parsed_options.mount_opt & tmp)) {
+       if ((osb->s_mount_opt & tmp) != (parsed_options->mount_opt & tmp)) {
                ret = -EINVAL;
                mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n");
                goto out;
        }
 
        if ((osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK) !=
-           (parsed_options.mount_opt & OCFS2_MOUNT_DATA_WRITEBACK)) {
+           (parsed_options->mount_opt & OCFS2_MOUNT_DATA_WRITEBACK)) {
                ret = -EINVAL;
                mlog(ML_ERROR, "Cannot change data mode on remount\n");
                goto out;
@@ -634,16 +638,16 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
        /* Probably don't want this on remount; it might
         * mess with other nodes */
        if (!(osb->s_mount_opt & OCFS2_MOUNT_INODE64) &&
-           (parsed_options.mount_opt & OCFS2_MOUNT_INODE64)) {
+           (parsed_options->mount_opt & OCFS2_MOUNT_INODE64)) {
                ret = -EINVAL;
                mlog(ML_ERROR, "Cannot enable inode64 on remount\n");
                goto out;
        }
 
        /* We're going to/from readonly mode. */
-       if ((bool)(*flags & SB_RDONLY) != sb_rdonly(sb)) {
+       if ((bool)(fc->sb_flags & SB_RDONLY) != sb_rdonly(sb)) {
                /* Disable quota accounting before remounting RO */
-               if (*flags & SB_RDONLY) {
+               if (fc->sb_flags & SB_RDONLY) {
                        ret = ocfs2_susp_quotas(osb, 0);
                        if (ret < 0)
                                goto out;
@@ -657,7 +661,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
                        goto unlock_osb;
                }
 
-               if (*flags & SB_RDONLY) {
+               if (fc->sb_flags & SB_RDONLY) {
                        sb->s_flags |= SB_RDONLY;
                        osb->osb_flags |= OCFS2_OSB_SOFT_RO;
                } else {
@@ -678,11 +682,11 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
                        sb->s_flags &= ~SB_RDONLY;
                        osb->osb_flags &= ~OCFS2_OSB_SOFT_RO;
                }
-               trace_ocfs2_remount(sb->s_flags, osb->osb_flags, *flags);
+               trace_ocfs2_remount(sb->s_flags, osb->osb_flags, fc->sb_flags);
 unlock_osb:
                spin_unlock(&osb->osb_lock);
                /* Enable quota accounting after remounting RW */
-               if (!ret && !(*flags & SB_RDONLY)) {
+               if (!ret && !(fc->sb_flags & SB_RDONLY)) {
                        if (sb_any_quota_suspended(sb))
                                ret = ocfs2_susp_quotas(osb, 1);
                        else
@@ -701,11 +705,11 @@ unlock_osb:
        if (!ret) {
                /* Only save off the new mount options in case of a successful
                 * remount. */
-               osb->s_mount_opt = parsed_options.mount_opt;
-               osb->s_atime_quantum = parsed_options.atime_quantum;
-               osb->preferred_slot = parsed_options.slot;
-               if (parsed_options.commit_interval)
-                       osb->osb_commit_interval = parsed_options.commit_interval;
+               osb->s_mount_opt = parsed_options->mount_opt;
+               osb->s_atime_quantum = parsed_options->atime_quantum;
+               osb->preferred_slot = parsed_options->slot;
+               if (parsed_options->commit_interval)
+                       osb->osb_commit_interval = parsed_options->commit_interval;
 
                if (!ocfs2_is_hard_readonly(osb))
                        ocfs2_set_journal_params(osb);
@@ -966,23 +970,18 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb)
        }
 }
 
-static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
+static int ocfs2_fill_super(struct super_block *sb, struct fs_context *fc)
 {
        struct dentry *root;
        int status, sector_size;
-       struct mount_options parsed_options;
+       struct mount_options *parsed_options = fc->fs_private;
        struct inode *inode = NULL;
        struct ocfs2_super *osb = NULL;
        struct buffer_head *bh = NULL;
        char nodestr[12];
        struct ocfs2_blockcheck_stats stats;
 
-       trace_ocfs2_fill_super(sb, data, silent);
-
-       if (!ocfs2_parse_options(sb, data, &parsed_options, 0)) {
-               status = -EINVAL;
-               goto out;
-       }
+       trace_ocfs2_fill_super(sb, fc, fc->sb_flags & SB_SILENT);
 
        /* probe for superblock */
        status = ocfs2_sb_probe(sb, &bh, &sector_size, &stats);
@@ -999,24 +998,24 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
        osb = OCFS2_SB(sb);
 
-       if (!ocfs2_check_set_options(sb, &parsed_options)) {
+       if (!ocfs2_check_set_options(sb, parsed_options)) {
                status = -EINVAL;
                goto out_super;
        }
-       osb->s_mount_opt = parsed_options.mount_opt;
-       osb->s_atime_quantum = parsed_options.atime_quantum;
-       osb->preferred_slot = parsed_options.slot;
-       osb->osb_commit_interval = parsed_options.commit_interval;
+       osb->s_mount_opt = parsed_options->mount_opt;
+       osb->s_atime_quantum = parsed_options->atime_quantum;
+       osb->preferred_slot = parsed_options->slot;
+       osb->osb_commit_interval = parsed_options->commit_interval;
 
-       ocfs2_la_set_sizes(osb, parsed_options.localalloc_opt);
-       osb->osb_resv_level = parsed_options.resv_level;
-       osb->osb_dir_resv_level = parsed_options.resv_level;
-       if (parsed_options.dir_resv_level == -1)
-               osb->osb_dir_resv_level = parsed_options.resv_level;
+       ocfs2_la_set_sizes(osb, parsed_options->localalloc_opt);
+       osb->osb_resv_level = parsed_options->resv_level;
+       osb->osb_dir_resv_level = parsed_options->resv_level;
+       if (parsed_options->dir_resv_level == -1)
+               osb->osb_dir_resv_level = parsed_options->resv_level;
        else
-               osb->osb_dir_resv_level = parsed_options.dir_resv_level;
+               osb->osb_dir_resv_level = parsed_options->dir_resv_level;
 
-       status = ocfs2_verify_userspace_stack(osb, &parsed_options);
+       status = ocfs2_verify_userspace_stack(osb, parsed_options);
        if (status)
                goto out_super;
 
@@ -1180,27 +1179,72 @@ out:
        return status;
 }
 
-static struct dentry *ocfs2_mount(struct file_system_type *fs_type,
-                       int flags,
-                       const char *dev_name,
-                       void *data)
+static int ocfs2_get_tree(struct fs_context *fc)
+{
+       return get_tree_bdev(fc, ocfs2_fill_super);
+}
+
+static void ocfs2_free_fc(struct fs_context *fc)
 {
-       return mount_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super);
+       kfree(fc->fs_private);
+}
+
+static const struct fs_context_operations ocfs2_context_ops = {
+       .parse_param    = ocfs2_parse_param,
+       .get_tree       = ocfs2_get_tree,
+       .reconfigure    = ocfs2_reconfigure,
+       .free           = ocfs2_free_fc,
+};
+
+static int ocfs2_init_fs_context(struct fs_context *fc)
+{
+       struct mount_options *mopt;
+
+       mopt = kzalloc(sizeof(struct mount_options), GFP_KERNEL);
+       if (!mopt)
+               return -EINVAL;
+
+       mopt->commit_interval = 0;
+       mopt->mount_opt = OCFS2_MOUNT_NOINTR;
+       mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
+       mopt->slot = OCFS2_INVALID_SLOT;
+       mopt->localalloc_opt = -1;
+       mopt->cluster_stack[0] = '\0';
+       mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL;
+       mopt->dir_resv_level = -1;
+
+       fc->fs_private = mopt;
+       fc->ops = &ocfs2_context_ops;
+
+       return 0;
 }
 
 static struct file_system_type ocfs2_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "ocfs2",
-       .mount          = ocfs2_mount,
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV|FS_RENAME_DOES_D_MOVE,
-       .next           = NULL
+       .next           = NULL,
+       .init_fs_context = ocfs2_init_fs_context,
+       .parameters     = ocfs2_param_spec,
 };
 MODULE_ALIAS_FS("ocfs2");
 
 static int ocfs2_check_set_options(struct super_block *sb,
                                   struct mount_options *options)
 {
+       if (options->user_stack == 0) {
+               u32 tmp;
+
+               /* Ensure only one heartbeat mode */
+               tmp = options->mount_opt & (OCFS2_MOUNT_HB_LOCAL |
+                                           OCFS2_MOUNT_HB_GLOBAL |
+                                           OCFS2_MOUNT_HB_NONE);
+               if (hweight32(tmp) != 1) {
+                       mlog(ML_ERROR, "Invalid heartbeat mount options\n");
+                       return 0;
+               }
+       }
        if (options->mount_opt & OCFS2_MOUNT_USRQUOTA &&
            !OCFS2_HAS_RO_COMPAT_FEATURE(sb,
                                         OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
@@ -1232,241 +1276,142 @@ static int ocfs2_check_set_options(struct super_block *sb,
        return 1;
 }
 
-static int ocfs2_parse_options(struct super_block *sb,
-                              char *options,
-                              struct mount_options *mopt,
-                              int is_remount)
+static int ocfs2_parse_param(struct fs_context *fc, struct fs_parameter *param)
 {
-       int status, user_stack = 0;
-       char *p;
-       u32 tmp;
-       int token, option;
-       substring_t args[MAX_OPT_ARGS];
-
-       trace_ocfs2_parse_options(is_remount, options ? options : "(none)");
-
-       mopt->commit_interval = 0;
-       mopt->mount_opt = OCFS2_MOUNT_NOINTR;
-       mopt->atime_quantum = OCFS2_DEFAULT_ATIME_QUANTUM;
-       mopt->slot = OCFS2_INVALID_SLOT;
-       mopt->localalloc_opt = -1;
-       mopt->cluster_stack[0] = '\0';
-       mopt->resv_level = OCFS2_DEFAULT_RESV_LEVEL;
-       mopt->dir_resv_level = -1;
-
-       if (!options) {
-               status = 1;
-               goto bail;
-       }
-
-       while ((p = strsep(&options, ",")) != NULL) {
-               if (!*p)
-                       continue;
-
-               token = match_token(p, tokens, args);
-               switch (token) {
-               case Opt_hb_local:
-                       mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL;
-                       break;
-               case Opt_hb_none:
-                       mopt->mount_opt |= OCFS2_MOUNT_HB_NONE;
-                       break;
-               case Opt_hb_global:
-                       mopt->mount_opt |= OCFS2_MOUNT_HB_GLOBAL;
-                       break;
-               case Opt_barrier:
-                       if (match_int(&args[0], &option)) {
-                               status = 0;
-                               goto bail;
-                       }
-                       if (option)
-                               mopt->mount_opt |= OCFS2_MOUNT_BARRIER;
-                       else
-                               mopt->mount_opt &= ~OCFS2_MOUNT_BARRIER;
-                       break;
-               case Opt_intr:
-                       mopt->mount_opt &= ~OCFS2_MOUNT_NOINTR;
-                       break;
-               case Opt_nointr:
+       struct fs_parse_result result;
+       int opt;
+       struct mount_options *mopt = fc->fs_private;
+       bool is_remount = (fc->purpose & FS_CONTEXT_FOR_RECONFIGURE);
+
+       trace_ocfs2_parse_options(is_remount, param->key);
+
+       opt = fs_parse(fc, ocfs2_param_spec, param, &result);
+       if (opt < 0)
+               return opt;
+
+       switch (opt) {
+       case Opt_heartbeat:
+               mopt->mount_opt |= result.uint_32;
+               break;
+       case Opt_barrier:
+               if (result.uint_32)
+                       mopt->mount_opt |= OCFS2_MOUNT_BARRIER;
+               else
+                       mopt->mount_opt &= ~OCFS2_MOUNT_BARRIER;
+               break;
+       case Opt_intr:
+               if (result.negated)
                        mopt->mount_opt |= OCFS2_MOUNT_NOINTR;
-                       break;
-               case Opt_err_panic:
-                       mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_CONT;
-                       mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_ROFS;
-                       mopt->mount_opt |= OCFS2_MOUNT_ERRORS_PANIC;
-                       break;
-               case Opt_err_ro:
-                       mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_CONT;
-                       mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_PANIC;
-                       mopt->mount_opt |= OCFS2_MOUNT_ERRORS_ROFS;
-                       break;
-               case Opt_err_cont:
-                       mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_ROFS;
-                       mopt->mount_opt &= ~OCFS2_MOUNT_ERRORS_PANIC;
-                       mopt->mount_opt |= OCFS2_MOUNT_ERRORS_CONT;
-                       break;
-               case Opt_data_ordered:
-                       mopt->mount_opt &= ~OCFS2_MOUNT_DATA_WRITEBACK;
-                       break;
-               case Opt_data_writeback:
-                       mopt->mount_opt |= OCFS2_MOUNT_DATA_WRITEBACK;
-                       break;
-               case Opt_user_xattr:
-                       mopt->mount_opt &= ~OCFS2_MOUNT_NOUSERXATTR;
-                       break;
-               case Opt_nouser_xattr:
+               else
+                       mopt->mount_opt &= ~OCFS2_MOUNT_NOINTR;
+               break;
+       case Opt_errors:
+               mopt->mount_opt &= ~(OCFS2_MOUNT_ERRORS_CONT |
+                                    OCFS2_MOUNT_ERRORS_ROFS |
+                                    OCFS2_MOUNT_ERRORS_PANIC);
+               mopt->mount_opt |= result.uint_32;
+               break;
+       case Opt_data:
+               mopt->mount_opt &= ~OCFS2_MOUNT_DATA_WRITEBACK;
+               mopt->mount_opt |= result.uint_32;
+               break;
+       case Opt_user_xattr:
+               if (result.negated)
                        mopt->mount_opt |= OCFS2_MOUNT_NOUSERXATTR;
-                       break;
-               case Opt_atime_quantum:
-                       if (match_int(&args[0], &option)) {
-                               status = 0;
-                               goto bail;
-                       }
-                       if (option >= 0)
-                               mopt->atime_quantum = option;
-                       break;
-               case Opt_slot:
-                       if (match_int(&args[0], &option)) {
-                               status = 0;
-                               goto bail;
-                       }
-                       if (option)
-                               mopt->slot = (u16)option;
-                       break;
-               case Opt_commit:
-                       if (match_int(&args[0], &option)) {
-                               status = 0;
-                               goto bail;
-                       }
-                       if (option < 0)
-                               return 0;
-                       if (option == 0)
-                               option = JBD2_DEFAULT_MAX_COMMIT_AGE;
-                       mopt->commit_interval = HZ * option;
-                       break;
-               case Opt_localalloc:
-                       if (match_int(&args[0], &option)) {
-                               status = 0;
-                               goto bail;
-                       }
-                       if (option >= 0)
-                               mopt->localalloc_opt = option;
-                       break;
-               case Opt_localflocks:
-                       /*
-                        * Changing this during remount could race
-                        * flock() requests, or "unbalance" existing
-                        * ones (e.g., a lock is taken in one mode but
-                        * dropped in the other). If users care enough
-                        * to flip locking modes during remount, we
-                        * could add a "local" flag to individual
-                        * flock structures for proper tracking of
-                        * state.
-                        */
-                       if (!is_remount)
-                               mopt->mount_opt |= OCFS2_MOUNT_LOCALFLOCKS;
-                       break;
-               case Opt_stack:
-                       /* Check both that the option we were passed
-                        * is of the right length and that it is a proper
-                        * string of the right length.
-                        */
-                       if (((args[0].to - args[0].from) !=
-                            OCFS2_STACK_LABEL_LEN) ||
-                           (strnlen(args[0].from,
-                                    OCFS2_STACK_LABEL_LEN) !=
-                            OCFS2_STACK_LABEL_LEN)) {
-                               mlog(ML_ERROR,
-                                    "Invalid cluster_stack option\n");
-                               status = 0;
-                               goto bail;
-                       }
-                       memcpy(mopt->cluster_stack, args[0].from,
-                              OCFS2_STACK_LABEL_LEN);
-                       mopt->cluster_stack[OCFS2_STACK_LABEL_LEN] = '\0';
-                       /*
-                        * Open code the memcmp here as we don't have
-                        * an osb to pass to
-                        * ocfs2_userspace_stack().
-                        */
-                       if (memcmp(mopt->cluster_stack,
-                                  OCFS2_CLASSIC_CLUSTER_STACK,
-                                  OCFS2_STACK_LABEL_LEN))
-                               user_stack = 1;
-                       break;
-               case Opt_inode64:
-                       mopt->mount_opt |= OCFS2_MOUNT_INODE64;
-                       break;
-               case Opt_usrquota:
-                       mopt->mount_opt |= OCFS2_MOUNT_USRQUOTA;
-                       break;
-               case Opt_grpquota:
-                       mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA;
-                       break;
-               case Opt_coherency_buffered:
-                       mopt->mount_opt |= OCFS2_MOUNT_COHERENCY_BUFFERED;
-                       break;
-               case Opt_coherency_full:
-                       mopt->mount_opt &= ~OCFS2_MOUNT_COHERENCY_BUFFERED;
-                       break;
-               case Opt_acl:
-                       mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL;
-                       mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL;
-                       break;
-               case Opt_noacl:
+               else
+                       mopt->mount_opt &= ~OCFS2_MOUNT_NOUSERXATTR;
+               break;
+       case Opt_atime_quantum:
+               mopt->atime_quantum = result.uint_32;
+               break;
+       case Opt_slot:
+               if (result.uint_32)
+                       mopt->slot = (u16)result.uint_32;
+               break;
+       case Opt_commit:
+               if (result.uint_32 == 0)
+                       mopt->commit_interval = HZ * JBD2_DEFAULT_MAX_COMMIT_AGE;
+               else
+                       mopt->commit_interval = HZ * result.uint_32;
+               break;
+       case Opt_localalloc:
+               if (result.int_32 >= 0)
+                       mopt->localalloc_opt = result.int_32;
+               break;
+       case Opt_localflocks:
+               /*
+                * Changing this during remount could race flock() requests, or
+                * "unbalance" existing ones (e.g., a lock is taken in one mode
+                * but dropped in the other). If users care enough to flip
+                * locking modes during remount, we could add a "local" flag to
+                * individual flock structures for proper tracking of state.
+                */
+               if (!is_remount)
+                       mopt->mount_opt |= OCFS2_MOUNT_LOCALFLOCKS;
+               break;
+       case Opt_stack:
+               /* Check both that the option we were passed is of the right
+                * length and that it is a proper string of the right length.
+                */
+               if (strlen(param->string) != OCFS2_STACK_LABEL_LEN) {
+                       mlog(ML_ERROR, "Invalid cluster_stack option\n");
+                       return -EINVAL;
+               }
+               memcpy(mopt->cluster_stack, param->string, OCFS2_STACK_LABEL_LEN);
+               mopt->cluster_stack[OCFS2_STACK_LABEL_LEN] = '\0';
+               /*
+                * Open code the memcmp here as we don't have an osb to pass
+                * to ocfs2_userspace_stack().
+                */
+               if (memcmp(mopt->cluster_stack,
+                          OCFS2_CLASSIC_CLUSTER_STACK,
+                          OCFS2_STACK_LABEL_LEN))
+                       mopt->user_stack = 1;
+               break;
+       case Opt_inode64:
+               mopt->mount_opt |= OCFS2_MOUNT_INODE64;
+               break;
+       case Opt_usrquota:
+               mopt->mount_opt |= OCFS2_MOUNT_USRQUOTA;
+               break;
+       case Opt_grpquota:
+               mopt->mount_opt |= OCFS2_MOUNT_GRPQUOTA;
+               break;
+       case Opt_coherency:
+               mopt->mount_opt &= ~OCFS2_MOUNT_COHERENCY_BUFFERED;
+               mopt->mount_opt |= result.uint_32;
+               break;
+       case Opt_acl:
+               if (result.negated) {
                        mopt->mount_opt |= OCFS2_MOUNT_NO_POSIX_ACL;
                        mopt->mount_opt &= ~OCFS2_MOUNT_POSIX_ACL;
+               } else {
+                       mopt->mount_opt |= OCFS2_MOUNT_POSIX_ACL;
+                       mopt->mount_opt &= ~OCFS2_MOUNT_NO_POSIX_ACL;
+               }
+               break;
+       case Opt_resv_level:
+               if (is_remount)
                        break;
-               case Opt_resv_level:
-                       if (is_remount)
-                               break;
-                       if (match_int(&args[0], &option)) {
-                               status = 0;
-                               goto bail;
-                       }
-                       if (option >= OCFS2_MIN_RESV_LEVEL &&
-                           option < OCFS2_MAX_RESV_LEVEL)
-                               mopt->resv_level = option;
-                       break;
-               case Opt_dir_resv_level:
-                       if (is_remount)
-                               break;
-                       if (match_int(&args[0], &option)) {
-                               status = 0;
-                               goto bail;
-                       }
-                       if (option >= OCFS2_MIN_RESV_LEVEL &&
-                           option < OCFS2_MAX_RESV_LEVEL)
-                               mopt->dir_resv_level = option;
-                       break;
-               case Opt_journal_async_commit:
-                       mopt->mount_opt |= OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT;
+               if (result.uint_32 >= OCFS2_MIN_RESV_LEVEL &&
+                   result.uint_32 < OCFS2_MAX_RESV_LEVEL)
+                       mopt->resv_level = result.uint_32;
+               break;
+       case Opt_dir_resv_level:
+               if (is_remount)
                        break;
-               default:
-                       mlog(ML_ERROR,
-                            "Unrecognized mount option \"%s\" "
-                            "or missing value\n", p);
-                       status = 0;
-                       goto bail;
-               }
-       }
-
-       if (user_stack == 0) {
-               /* Ensure only one heartbeat mode */
-               tmp = mopt->mount_opt & (OCFS2_MOUNT_HB_LOCAL |
-                                        OCFS2_MOUNT_HB_GLOBAL |
-                                        OCFS2_MOUNT_HB_NONE);
-               if (hweight32(tmp) != 1) {
-                       mlog(ML_ERROR, "Invalid heartbeat mount options\n");
-                       status = 0;
-                       goto bail;
-               }
+               if (result.uint_32 >= OCFS2_MIN_RESV_LEVEL &&
+                   result.uint_32 < OCFS2_MAX_RESV_LEVEL)
+                       mopt->dir_resv_level = result.uint_32;
+               break;
+       case Opt_journal_async_commit:
+               mopt->mount_opt |= OCFS2_MOUNT_JOURNAL_ASYNC_COMMIT;
+               break;
+       default:
+               return -EINVAL;
        }
 
-       status = 1;
-
-bail:
-       return status;
+       return 0;
 }
 
 static int ocfs2_show_options(struct seq_file *s, struct dentry *root)