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,
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);

View file

@ -19,10 +19,10 @@
#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 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 = {
.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];
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, options ? options : "(none)");
trace_ocfs2_parse_options(is_remount, param->key);
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;
opt = fs_parse(fc, ocfs2_param_spec, param, &result);
if (opt < 0)
return opt;
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:
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;
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;
break;
default:
mlog(ML_ERROR,
"Unrecognized mount option \"%s\" "
"or missing value\n", p);
status = 0;
goto bail;
} 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;
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) {
/* 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;
return 0;
}
static int ocfs2_show_options(struct seq_file *s, struct dentry *root)