|
|
|
@ -162,6 +162,7 @@ enum { |
|
|
|
|
Opt_nointr, |
|
|
|
|
Opt_hb_none, |
|
|
|
|
Opt_hb_local, |
|
|
|
|
Opt_hb_global, |
|
|
|
|
Opt_data_ordered, |
|
|
|
|
Opt_data_writeback, |
|
|
|
|
Opt_atime_quantum, |
|
|
|
@ -190,6 +191,7 @@ static const match_table_t tokens = { |
|
|
|
|
{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"}, |
|
|
|
@ -608,6 +610,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) |
|
|
|
|
int ret = 0; |
|
|
|
|
struct mount_options parsed_options; |
|
|
|
|
struct ocfs2_super *osb = OCFS2_SB(sb); |
|
|
|
|
u32 tmp; |
|
|
|
|
|
|
|
|
|
lock_kernel(); |
|
|
|
|
|
|
|
|
@ -617,8 +620,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) != |
|
|
|
|
(parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL)) { |
|
|
|
|
tmp = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL | |
|
|
|
|
OCFS2_MOUNT_HB_NONE; |
|
|
|
|
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; |
|
|
|
@ -809,23 +813,29 @@ bail: |
|
|
|
|
|
|
|
|
|
static int ocfs2_verify_heartbeat(struct ocfs2_super *osb) |
|
|
|
|
{ |
|
|
|
|
if (ocfs2_mount_local(osb)) { |
|
|
|
|
if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { |
|
|
|
|
u32 hb_enabled = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL; |
|
|
|
|
|
|
|
|
|
if (osb->s_mount_opt & hb_enabled) { |
|
|
|
|
if (ocfs2_mount_local(osb)) { |
|
|
|
|
mlog(ML_ERROR, "Cannot heartbeat on a locally " |
|
|
|
|
"mounted device.\n"); |
|
|
|
|
return -EINVAL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ocfs2_userspace_stack(osb)) { |
|
|
|
|
if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { |
|
|
|
|
if (ocfs2_userspace_stack(osb)) { |
|
|
|
|
mlog(ML_ERROR, "Userspace stack expected, but " |
|
|
|
|
"o2cb heartbeat arguments passed to mount\n"); |
|
|
|
|
return -EINVAL; |
|
|
|
|
} |
|
|
|
|
if (((osb->s_mount_opt & OCFS2_MOUNT_HB_GLOBAL) && |
|
|
|
|
!ocfs2_cluster_o2cb_global_heartbeat(osb)) || |
|
|
|
|
((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) && |
|
|
|
|
ocfs2_cluster_o2cb_global_heartbeat(osb))) { |
|
|
|
|
mlog(ML_ERROR, "Mismatching o2cb heartbeat modes\n"); |
|
|
|
|
return -EINVAL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) { |
|
|
|
|
if (!(osb->s_mount_opt & hb_enabled)) { |
|
|
|
|
if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) && |
|
|
|
|
!ocfs2_userspace_stack(osb)) { |
|
|
|
|
mlog(ML_ERROR, "Heartbeat has to be started to mount " |
|
|
|
@ -1291,6 +1301,7 @@ static int ocfs2_parse_options(struct super_block *sb, |
|
|
|
|
{ |
|
|
|
|
int status; |
|
|
|
|
char *p; |
|
|
|
|
u32 tmp; |
|
|
|
|
|
|
|
|
|
mlog_entry("remount: %d, options: \"%s\"\n", is_remount, |
|
|
|
|
options ? options : "(none)"); |
|
|
|
@ -1322,7 +1333,10 @@ static int ocfs2_parse_options(struct super_block *sb, |
|
|
|
|
mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL; |
|
|
|
|
break; |
|
|
|
|
case Opt_hb_none: |
|
|
|
|
mopt->mount_opt &= ~OCFS2_MOUNT_HB_LOCAL; |
|
|
|
|
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)) { |
|
|
|
@ -1477,6 +1491,15 @@ static int ocfs2_parse_options(struct super_block *sb, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* 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: |
|
|
|
@ -1490,10 +1513,14 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) |
|
|
|
|
unsigned long opts = osb->s_mount_opt; |
|
|
|
|
unsigned int local_alloc_megs; |
|
|
|
|
|
|
|
|
|
if (opts & OCFS2_MOUNT_HB_LOCAL) |
|
|
|
|
seq_printf(s, ",_netdev,heartbeat=local"); |
|
|
|
|
else |
|
|
|
|
seq_printf(s, ",heartbeat=none"); |
|
|
|
|
if (opts & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL)) { |
|
|
|
|
seq_printf(s, ",_netdev"); |
|
|
|
|
if (opts & OCFS2_MOUNT_HB_LOCAL) |
|
|
|
|
seq_printf(s, ",%s", OCFS2_HB_LOCAL); |
|
|
|
|
else |
|
|
|
|
seq_printf(s, ",%s", OCFS2_HB_GLOBAL); |
|
|
|
|
} else |
|
|
|
|
seq_printf(s, ",%s", OCFS2_HB_NONE); |
|
|
|
|
|
|
|
|
|
if (opts & OCFS2_MOUNT_NOINTR) |
|
|
|
|
seq_printf(s, ",nointr"); |
|
|
|
|