Commit 2c442719 authored by Sunil Mushran's avatar Sunil Mushran

ocfs2: Add support for heartbeat=global mount option

Adds support for heartbeat=global mount option. It ensures that the heartbeat
mode passed matches the one enabled on disk.
Signed-off-by: default avatarSunil Mushran <sunil.mushran@oracle.com>
parent 98f486f2
...@@ -243,7 +243,7 @@ enum ocfs2_local_alloc_state ...@@ -243,7 +243,7 @@ enum ocfs2_local_alloc_state
enum ocfs2_mount_options enum ocfs2_mount_options
{ {
OCFS2_MOUNT_HB_LOCAL = 1 << 0, /* Heartbeat started in local mode */ OCFS2_MOUNT_HB_LOCAL = 1 << 0, /* Local heartbeat */
OCFS2_MOUNT_BARRIER = 1 << 1, /* Use block barriers */ OCFS2_MOUNT_BARRIER = 1 << 1, /* Use block barriers */
OCFS2_MOUNT_NOINTR = 1 << 2, /* Don't catch signals */ OCFS2_MOUNT_NOINTR = 1 << 2, /* Don't catch signals */
OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */ OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */
...@@ -256,6 +256,8 @@ enum ocfs2_mount_options ...@@ -256,6 +256,8 @@ enum ocfs2_mount_options
control lists */ control lists */
OCFS2_MOUNT_USRQUOTA = 1 << 10, /* We support user quotas */ OCFS2_MOUNT_USRQUOTA = 1 << 10, /* We support user quotas */
OCFS2_MOUNT_GRPQUOTA = 1 << 11, /* We support group quotas */ OCFS2_MOUNT_GRPQUOTA = 1 << 11, /* We support group quotas */
OCFS2_MOUNT_HB_NONE = 1 << 12, /* No heartbeat */
OCFS2_MOUNT_HB_GLOBAL = 1 << 13, /* Global heartbeat */
}; };
#define OCFS2_OSB_SOFT_RO 0x0001 #define OCFS2_OSB_SOFT_RO 0x0001
......
...@@ -376,6 +376,7 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = { ...@@ -376,6 +376,7 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = {
/* Parameter passed from mount.ocfs2 to module */ /* Parameter passed from mount.ocfs2 to module */
#define OCFS2_HB_NONE "heartbeat=none" #define OCFS2_HB_NONE "heartbeat=none"
#define OCFS2_HB_LOCAL "heartbeat=local" #define OCFS2_HB_LOCAL "heartbeat=local"
#define OCFS2_HB_GLOBAL "heartbeat=global"
/* /*
* OCFS2 directory file types. Only the low 3 bits are used. The * OCFS2 directory file types. Only the low 3 bits are used. The
......
...@@ -162,6 +162,7 @@ enum { ...@@ -162,6 +162,7 @@ enum {
Opt_nointr, Opt_nointr,
Opt_hb_none, Opt_hb_none,
Opt_hb_local, Opt_hb_local,
Opt_hb_global,
Opt_data_ordered, Opt_data_ordered,
Opt_data_writeback, Opt_data_writeback,
Opt_atime_quantum, Opt_atime_quantum,
...@@ -190,6 +191,7 @@ static const match_table_t tokens = { ...@@ -190,6 +191,7 @@ static const match_table_t tokens = {
{Opt_nointr, "nointr"}, {Opt_nointr, "nointr"},
{Opt_hb_none, OCFS2_HB_NONE}, {Opt_hb_none, OCFS2_HB_NONE},
{Opt_hb_local, OCFS2_HB_LOCAL}, {Opt_hb_local, OCFS2_HB_LOCAL},
{Opt_hb_global, OCFS2_HB_GLOBAL},
{Opt_data_ordered, "data=ordered"}, {Opt_data_ordered, "data=ordered"},
{Opt_data_writeback, "data=writeback"}, {Opt_data_writeback, "data=writeback"},
{Opt_atime_quantum, "atime_quantum=%u"}, {Opt_atime_quantum, "atime_quantum=%u"},
...@@ -608,6 +610,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) ...@@ -608,6 +610,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
int ret = 0; int ret = 0;
struct mount_options parsed_options; struct mount_options parsed_options;
struct ocfs2_super *osb = OCFS2_SB(sb); struct ocfs2_super *osb = OCFS2_SB(sb);
u32 tmp;
lock_kernel(); lock_kernel();
...@@ -617,8 +620,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) ...@@ -617,8 +620,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
goto out; goto out;
} }
if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) != tmp = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL |
(parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL)) { OCFS2_MOUNT_HB_NONE;
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;
...@@ -809,23 +813,29 @@ static int ocfs2_sb_probe(struct super_block *sb, ...@@ -809,23 +813,29 @@ static int ocfs2_sb_probe(struct super_block *sb,
static int ocfs2_verify_heartbeat(struct ocfs2_super *osb) static int ocfs2_verify_heartbeat(struct ocfs2_super *osb)
{ {
if (ocfs2_mount_local(osb)) { u32 hb_enabled = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL;
if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
if (osb->s_mount_opt & hb_enabled) {
if (ocfs2_mount_local(osb)) {
mlog(ML_ERROR, "Cannot heartbeat on a locally " mlog(ML_ERROR, "Cannot heartbeat on a locally "
"mounted device.\n"); "mounted device.\n");
return -EINVAL; return -EINVAL;
} }
} if (ocfs2_userspace_stack(osb)) {
if (ocfs2_userspace_stack(osb)) {
if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) {
mlog(ML_ERROR, "Userspace stack expected, but " mlog(ML_ERROR, "Userspace stack expected, but "
"o2cb heartbeat arguments passed to mount\n"); "o2cb heartbeat arguments passed to mount\n");
return -EINVAL; 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) && if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) &&
!ocfs2_userspace_stack(osb)) { !ocfs2_userspace_stack(osb)) {
mlog(ML_ERROR, "Heartbeat has to be started to mount " mlog(ML_ERROR, "Heartbeat has to be started to mount "
...@@ -1291,6 +1301,7 @@ static int ocfs2_parse_options(struct super_block *sb, ...@@ -1291,6 +1301,7 @@ static int ocfs2_parse_options(struct super_block *sb,
{ {
int status; int status;
char *p; char *p;
u32 tmp;
mlog_entry("remount: %d, options: \"%s\"\n", is_remount, mlog_entry("remount: %d, options: \"%s\"\n", is_remount,
options ? options : "(none)"); options ? options : "(none)");
...@@ -1322,7 +1333,10 @@ static int ocfs2_parse_options(struct super_block *sb, ...@@ -1322,7 +1333,10 @@ static int ocfs2_parse_options(struct super_block *sb,
mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL; mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL;
break; break;
case Opt_hb_none: 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; break;
case Opt_barrier: case Opt_barrier:
if (match_int(&args[0], &option)) { if (match_int(&args[0], &option)) {
...@@ -1477,6 +1491,15 @@ static int ocfs2_parse_options(struct super_block *sb, ...@@ -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; status = 1;
bail: bail:
...@@ -1490,10 +1513,14 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) ...@@ -1490,10 +1513,14 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
unsigned long opts = osb->s_mount_opt; unsigned long opts = osb->s_mount_opt;
unsigned int local_alloc_megs; unsigned int local_alloc_megs;
if (opts & OCFS2_MOUNT_HB_LOCAL) if (opts & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL)) {
seq_printf(s, ",_netdev,heartbeat=local"); seq_printf(s, ",_netdev");
else if (opts & OCFS2_MOUNT_HB_LOCAL)
seq_printf(s, ",heartbeat=none"); 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) if (opts & OCFS2_MOUNT_NOINTR)
seq_printf(s, ",nointr"); seq_printf(s, ",nointr");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment