diff options
| -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"); |
