ocfs2: convert to the new mount API

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>
This commit is contained in:
Eric Sandeen 2024-10-28 09:41:15 -05:00 committed by Andrew Morton
parent 94e0c28902
commit 9be53fe697
2 changed files with 275 additions and 330 deletions

View file

@ -1658,34 +1658,34 @@ TRACE_EVENT(ocfs2_remount,
); );
TRACE_EVENT(ocfs2_fill_super, TRACE_EVENT(ocfs2_fill_super,
TP_PROTO(void *sb, void *data, int silent), TP_PROTO(void *sb, void *fc, int silent),
TP_ARGS(sb, data, silent), TP_ARGS(sb, fc, silent),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(void *, sb) __field(void *, sb)
__field(void *, data) __field(void *, fc)
__field(int, silent) __field(int, silent)
), ),
TP_fast_assign( TP_fast_assign(
__entry->sb = sb; __entry->sb = sb;
__entry->data = data; __entry->fc = fc;
__entry->silent = silent; __entry->silent = silent;
), ),
TP_printk("%p %p %d", __entry->sb, TP_printk("%p %p %d", __entry->sb,
__entry->data, __entry->silent) __entry->fc, __entry->silent)
); );
TRACE_EVENT(ocfs2_parse_options, TRACE_EVENT(ocfs2_parse_options,
TP_PROTO(int is_remount, char *options), TP_PROTO(int is_remount, const char *option),
TP_ARGS(is_remount, options), TP_ARGS(is_remount, option),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(int, is_remount) __field(int, is_remount)
__string(options, options) __string(option, option)
), ),
TP_fast_assign( TP_fast_assign(
__entry->is_remount = is_remount; __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); DEFINE_OCFS2_POINTER_EVENT(ocfs2_put_super);

View file

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