diff options
author | Sunil Mushran <sunil.mushran@oracle.com> | 2010-10-07 18:23:50 -0400 |
---|---|---|
committer | Sunil Mushran <sunil.mushran@oracle.com> | 2010-10-07 18:23:50 -0400 |
commit | 2c442719e90a44a6982c033d69df4aae4b167cfa (patch) | |
tree | 33719bdeeab9dc0fcb5898ca673aaa248b639dbb | |
parent | 98f486f23bc5b6a6fa90e1a0707b7e9fe0e7f3e4 (diff) |
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: Sunil Mushran <sunil.mushran@oracle.com>
-rw-r--r-- | fs/ocfs2/ocfs2.h | 4 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2_fs.h | 1 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 55 |
3 files changed, 45 insertions, 15 deletions
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index d5496a792bdb..481387b90b21 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -243,7 +243,7 @@ enum ocfs2_local_alloc_state | |||
243 | 243 | ||
244 | enum ocfs2_mount_options | 244 | enum ocfs2_mount_options |
245 | { | 245 | { |
246 | OCFS2_MOUNT_HB_LOCAL = 1 << 0, /* Heartbeat started in local mode */ | 246 | OCFS2_MOUNT_HB_LOCAL = 1 << 0, /* Local heartbeat */ |
247 | OCFS2_MOUNT_BARRIER = 1 << 1, /* Use block barriers */ | 247 | OCFS2_MOUNT_BARRIER = 1 << 1, /* Use block barriers */ |
248 | OCFS2_MOUNT_NOINTR = 1 << 2, /* Don't catch signals */ | 248 | OCFS2_MOUNT_NOINTR = 1 << 2, /* Don't catch signals */ |
249 | OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */ | 249 | OCFS2_MOUNT_ERRORS_PANIC = 1 << 3, /* Panic on errors */ |
@@ -256,6 +256,8 @@ enum ocfs2_mount_options | |||
256 | control lists */ | 256 | control lists */ |
257 | OCFS2_MOUNT_USRQUOTA = 1 << 10, /* We support user quotas */ | 257 | OCFS2_MOUNT_USRQUOTA = 1 << 10, /* We support user quotas */ |
258 | OCFS2_MOUNT_GRPQUOTA = 1 << 11, /* We support group quotas */ | 258 | OCFS2_MOUNT_GRPQUOTA = 1 << 11, /* We support group quotas */ |
259 | OCFS2_MOUNT_HB_NONE = 1 << 12, /* No heartbeat */ | ||
260 | OCFS2_MOUNT_HB_GLOBAL = 1 << 13, /* Global heartbeat */ | ||
259 | }; | 261 | }; |
260 | 262 | ||
261 | #define OCFS2_OSB_SOFT_RO 0x0001 | 263 | #define OCFS2_OSB_SOFT_RO 0x0001 |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index d5b1d99abc3c..28ff536b4f8d 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -376,6 +376,7 @@ static struct ocfs2_system_inode_info ocfs2_system_inodes[NUM_SYSTEM_INODES] = { | |||
376 | /* Parameter passed from mount.ocfs2 to module */ | 376 | /* Parameter passed from mount.ocfs2 to module */ |
377 | #define OCFS2_HB_NONE "heartbeat=none" | 377 | #define OCFS2_HB_NONE "heartbeat=none" |
378 | #define OCFS2_HB_LOCAL "heartbeat=local" | 378 | #define OCFS2_HB_LOCAL "heartbeat=local" |
379 | #define OCFS2_HB_GLOBAL "heartbeat=global" | ||
379 | 380 | ||
380 | /* | 381 | /* |
381 | * OCFS2 directory file types. Only the low 3 bits are used. The | 382 | * OCFS2 directory file types. Only the low 3 bits are used. The |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 755431739396..4e009ad303a1 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -162,6 +162,7 @@ enum { | |||
162 | Opt_nointr, | 162 | Opt_nointr, |
163 | Opt_hb_none, | 163 | Opt_hb_none, |
164 | Opt_hb_local, | 164 | Opt_hb_local, |
165 | Opt_hb_global, | ||
165 | Opt_data_ordered, | 166 | Opt_data_ordered, |
166 | Opt_data_writeback, | 167 | Opt_data_writeback, |
167 | Opt_atime_quantum, | 168 | Opt_atime_quantum, |
@@ -190,6 +191,7 @@ static const match_table_t tokens = { | |||
190 | {Opt_nointr, "nointr"}, | 191 | {Opt_nointr, "nointr"}, |
191 | {Opt_hb_none, OCFS2_HB_NONE}, | 192 | {Opt_hb_none, OCFS2_HB_NONE}, |
192 | {Opt_hb_local, OCFS2_HB_LOCAL}, | 193 | {Opt_hb_local, OCFS2_HB_LOCAL}, |
194 | {Opt_hb_global, OCFS2_HB_GLOBAL}, | ||
193 | {Opt_data_ordered, "data=ordered"}, | 195 | {Opt_data_ordered, "data=ordered"}, |
194 | {Opt_data_writeback, "data=writeback"}, | 196 | {Opt_data_writeback, "data=writeback"}, |
195 | {Opt_atime_quantum, "atime_quantum=%u"}, | 197 | {Opt_atime_quantum, "atime_quantum=%u"}, |
@@ -608,6 +610,7 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) | |||
608 | int ret = 0; | 610 | int ret = 0; |
609 | struct mount_options parsed_options; | 611 | struct mount_options parsed_options; |
610 | struct ocfs2_super *osb = OCFS2_SB(sb); | 612 | struct ocfs2_super *osb = OCFS2_SB(sb); |
613 | u32 tmp; | ||
611 | 614 | ||
612 | lock_kernel(); | 615 | lock_kernel(); |
613 | 616 | ||
@@ -617,8 +620,9 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data) | |||
617 | goto out; | 620 | goto out; |
618 | } | 621 | } |
619 | 622 | ||
620 | if ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) != | 623 | tmp = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL | |
621 | (parsed_options.mount_opt & OCFS2_MOUNT_HB_LOCAL)) { | 624 | OCFS2_MOUNT_HB_NONE; |
625 | if ((osb->s_mount_opt & tmp) != (parsed_options.mount_opt & tmp)) { | ||
622 | ret = -EINVAL; | 626 | ret = -EINVAL; |
623 | mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n"); | 627 | mlog(ML_ERROR, "Cannot change heartbeat mode on remount\n"); |
624 | goto out; | 628 | goto out; |
@@ -809,23 +813,29 @@ bail: | |||
809 | 813 | ||
810 | static int ocfs2_verify_heartbeat(struct ocfs2_super *osb) | 814 | static int ocfs2_verify_heartbeat(struct ocfs2_super *osb) |
811 | { | 815 | { |
812 | if (ocfs2_mount_local(osb)) { | 816 | u32 hb_enabled = OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL; |
813 | if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { | 817 | |
818 | if (osb->s_mount_opt & hb_enabled) { | ||
819 | if (ocfs2_mount_local(osb)) { | ||
814 | mlog(ML_ERROR, "Cannot heartbeat on a locally " | 820 | mlog(ML_ERROR, "Cannot heartbeat on a locally " |
815 | "mounted device.\n"); | 821 | "mounted device.\n"); |
816 | return -EINVAL; | 822 | return -EINVAL; |
817 | } | 823 | } |
818 | } | 824 | if (ocfs2_userspace_stack(osb)) { |
819 | |||
820 | if (ocfs2_userspace_stack(osb)) { | ||
821 | if (osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) { | ||
822 | mlog(ML_ERROR, "Userspace stack expected, but " | 825 | mlog(ML_ERROR, "Userspace stack expected, but " |
823 | "o2cb heartbeat arguments passed to mount\n"); | 826 | "o2cb heartbeat arguments passed to mount\n"); |
824 | return -EINVAL; | 827 | return -EINVAL; |
825 | } | 828 | } |
829 | if (((osb->s_mount_opt & OCFS2_MOUNT_HB_GLOBAL) && | ||
830 | !ocfs2_cluster_o2cb_global_heartbeat(osb)) || | ||
831 | ((osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL) && | ||
832 | ocfs2_cluster_o2cb_global_heartbeat(osb))) { | ||
833 | mlog(ML_ERROR, "Mismatching o2cb heartbeat modes\n"); | ||
834 | return -EINVAL; | ||
835 | } | ||
826 | } | 836 | } |
827 | 837 | ||
828 | if (!(osb->s_mount_opt & OCFS2_MOUNT_HB_LOCAL)) { | 838 | if (!(osb->s_mount_opt & hb_enabled)) { |
829 | if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) && | 839 | if (!ocfs2_mount_local(osb) && !ocfs2_is_hard_readonly(osb) && |
830 | !ocfs2_userspace_stack(osb)) { | 840 | !ocfs2_userspace_stack(osb)) { |
831 | mlog(ML_ERROR, "Heartbeat has to be started to mount " | 841 | mlog(ML_ERROR, "Heartbeat has to be started to mount " |
@@ -1291,6 +1301,7 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1291 | { | 1301 | { |
1292 | int status; | 1302 | int status; |
1293 | char *p; | 1303 | char *p; |
1304 | u32 tmp; | ||
1294 | 1305 | ||
1295 | mlog_entry("remount: %d, options: \"%s\"\n", is_remount, | 1306 | mlog_entry("remount: %d, options: \"%s\"\n", is_remount, |
1296 | options ? options : "(none)"); | 1307 | options ? options : "(none)"); |
@@ -1322,7 +1333,10 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1322 | mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL; | 1333 | mopt->mount_opt |= OCFS2_MOUNT_HB_LOCAL; |
1323 | break; | 1334 | break; |
1324 | case Opt_hb_none: | 1335 | case Opt_hb_none: |
1325 | mopt->mount_opt &= ~OCFS2_MOUNT_HB_LOCAL; | 1336 | mopt->mount_opt |= OCFS2_MOUNT_HB_NONE; |
1337 | break; | ||
1338 | case Opt_hb_global: | ||
1339 | mopt->mount_opt |= OCFS2_MOUNT_HB_GLOBAL; | ||
1326 | break; | 1340 | break; |
1327 | case Opt_barrier: | 1341 | case Opt_barrier: |
1328 | if (match_int(&args[0], &option)) { | 1342 | if (match_int(&args[0], &option)) { |
@@ -1477,6 +1491,15 @@ static int ocfs2_parse_options(struct super_block *sb, | |||
1477 | } | 1491 | } |
1478 | } | 1492 | } |
1479 | 1493 | ||
1494 | /* Ensure only one heartbeat mode */ | ||
1495 | tmp = mopt->mount_opt & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL | | ||
1496 | OCFS2_MOUNT_HB_NONE); | ||
1497 | if (hweight32(tmp) != 1) { | ||
1498 | mlog(ML_ERROR, "Invalid heartbeat mount options\n"); | ||
1499 | status = 0; | ||
1500 | goto bail; | ||
1501 | } | ||
1502 | |||
1480 | status = 1; | 1503 | status = 1; |
1481 | 1504 | ||
1482 | bail: | 1505 | bail: |
@@ -1490,10 +1513,14 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt) | |||
1490 | unsigned long opts = osb->s_mount_opt; | 1513 | unsigned long opts = osb->s_mount_opt; |
1491 | unsigned int local_alloc_megs; | 1514 | unsigned int local_alloc_megs; |
1492 | 1515 | ||
1493 | if (opts & OCFS2_MOUNT_HB_LOCAL) | 1516 | if (opts & (OCFS2_MOUNT_HB_LOCAL | OCFS2_MOUNT_HB_GLOBAL)) { |
1494 | seq_printf(s, ",_netdev,heartbeat=local"); | 1517 | seq_printf(s, ",_netdev"); |
1495 | else | 1518 | if (opts & OCFS2_MOUNT_HB_LOCAL) |
1496 | seq_printf(s, ",heartbeat=none"); | 1519 | seq_printf(s, ",%s", OCFS2_HB_LOCAL); |
1520 | else | ||
1521 | seq_printf(s, ",%s", OCFS2_HB_GLOBAL); | ||
1522 | } else | ||
1523 | seq_printf(s, ",%s", OCFS2_HB_NONE); | ||
1497 | 1524 | ||
1498 | if (opts & OCFS2_MOUNT_NOINTR) | 1525 | if (opts & OCFS2_MOUNT_NOINTR) |
1499 | seq_printf(s, ",nointr"); | 1526 | seq_printf(s, ",nointr"); |