[Ocfs2-tools-devel] [PATCH 20/25] libocfs2: Add a compat feature flag OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2
Sunil Mushran
sunil.mushran at oracle.com
Wed Jun 23 11:44:30 PDT 2010
OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2 denotes an enhanced s_cluster_info in
the super block. This field now allows the storage of cluster stack specific
flag.
This patch also introduces a clusterinfo flag OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT
to denote the enabled global heartbeat mode.
This flag is set and cleared using tunefs.ocfs2 --fs-features=[no]clusterinfo-v2.
The global heartbeat flag is set and cleared using tunefs.ocfs2 --update-cluster-stack.
Signed-off-by: Sunil Mushran <sunil.mushran at oracle.com>
---
debugfs.ocfs2/dump.c | 4 +
debugfs.ocfs2/include/utils.h | 2 +
debugfs.ocfs2/utils.c | 18 +++++
include/ocfs2-kernel/ocfs2_fs.h | 27 +++++++-
include/ocfs2/ocfs2.h | 16 ++++
libocfs2/feature_string.c | 47 +++++++++++--
tunefs.ocfs2/Makefile | 3 +-
tunefs.ocfs2/feature_clusterinfo_v2.c | 125 +++++++++++++++++++++++++++++++++
tunefs.ocfs2/op_features.c | 2 +
9 files changed, 234 insertions(+), 10 deletions(-)
create mode 100644 tunefs.ocfs2/feature_clusterinfo_v2.c
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index dc59071..762f923 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -102,6 +102,10 @@ void dump_super_block(FILE *out, struct ocfs2_super_block *sb)
else
fprintf(out, "\tCluster stack: classic o2cb\n");
+ get_cluster_info_flag(sb, buf, sizeof(buf));
+ fprintf(out, "\tCluster flags: %u %s\n",
+ sb->s_cluster_info.ci_stackflags, buf);
+
return ;
}
diff --git a/debugfs.ocfs2/include/utils.h b/debugfs.ocfs2/include/utils.h
index 96de0cf..8b5c90c 100644
--- a/debugfs.ocfs2/include/utils.h
+++ b/debugfs.ocfs2/include/utils.h
@@ -41,6 +41,8 @@ void get_incompat_flag(struct ocfs2_super_block *sb, char *buf, size_t count);
void get_tunefs_flag(struct ocfs2_super_block *sb, char *buf, size_t count);
void get_compat_flag(struct ocfs2_super_block *sb, char *buf, size_t count);
void get_rocompat_flag(struct ocfs2_super_block *sb, char *buf, size_t count);
+void get_cluster_info_flag(struct ocfs2_super_block *sb, char *buf,
+ size_t count);
void get_journal_block_type (uint32_t jtype, GString *str);
void get_tag_flag (uint32_t flags, GString *str);
FILE *open_pager(int interactive);
diff --git a/debugfs.ocfs2/utils.c b/debugfs.ocfs2/utils.c
index 38b4f6d..d14ba98 100644
--- a/debugfs.ocfs2/utils.c
+++ b/debugfs.ocfs2/utils.c
@@ -78,6 +78,24 @@ void get_rocompat_flag(struct ocfs2_super_block *sb, char *buf, size_t count)
com_err(gbls.cmd, err, "while processing ro compat flags");
}
+void get_cluster_info_flag(struct ocfs2_super_block *sb, char *buf,
+ size_t count)
+{
+ errcode_t err = 0;
+
+ *buf = '\0';
+ if (!ocfs2_clusterinfo_v2(sb))
+ return;
+
+ if (!ocfs2_o2cb_stack(sb))
+ return;
+
+ err = ocfs2_snprint_cluster_o2cb_flags(buf, count,
+ sb->s_cluster_info.ci_stackflags);
+ if (err)
+ com_err(gbls.cmd, err, "while processing clusterinfo flags");
+}
+
/*
* get_journal_block_type()
*
diff --git a/include/ocfs2-kernel/ocfs2_fs.h b/include/ocfs2-kernel/ocfs2_fs.h
index 7b7de72..e6b4da1 100644
--- a/include/ocfs2-kernel/ocfs2_fs.h
+++ b/include/ocfs2-kernel/ocfs2_fs.h
@@ -91,7 +91,8 @@
OCFS2_SB(sb)->s_feature_incompat &= ~(mask)
#define OCFS2_FEATURE_COMPAT_SUPP (OCFS2_FEATURE_COMPAT_BACKUP_SB \
- | OCFS2_FEATURE_COMPAT_JBD2_SB)
+ | OCFS2_FEATURE_COMPAT_JBD2_SB \
+ | OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2)
#define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \
| OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \
| OCFS2_FEATURE_INCOMPAT_INLINE_DATA \
@@ -185,6 +186,11 @@
#define OCFS2_FEATURE_COMPAT_JBD2_SB 0x0002
/*
+ * With this bit set, the ci_flag in ocfs2_cluster_info can be trusted.
+ */
+#define OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2 0x0004
+
+/*
* Unwritten extents support.
*/
#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 0x0001
@@ -307,6 +313,11 @@
*/
#define OCFS2_MIN_XATTR_INLINE_SIZE 256
+/*
+ * Cluster info flags (ocfs2_cluster_info.ci_stackflags)
+ */
+#define OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT (0x01)
+
struct ocfs2_system_inode_info {
char *si_name;
int si_iflags;
@@ -564,9 +575,21 @@ struct ocfs2_slot_map_extended {
*/
};
+/*
+ * ci_stackflags is only valid if the compat bit
+ * OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2 is set.
+ */
struct ocfs2_cluster_info {
/*00*/ __u8 ci_stack[OCFS2_STACK_LABEL_LEN];
- __le32 ci_reserved;
+ union {
+ __le32 ci_reserved;
+ struct {
+ __u8 ci_reserved1;
+ __u8 ci_reserved2;
+ __u8 ci_reserved3;
+ __u8 ci_stackflags;
+ };
+ };
/*08*/ __u8 ci_cluster[OCFS2_CLUSTER_NAME_LEN];
/*18*/
};
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 34e83f4..b4cb4dd 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -961,6 +961,8 @@ errcode_t ocfs2_snprint_feature_flags(char *str, size_t size,
errcode_t ocfs2_snprint_tunefs_flags(char *str, size_t size, uint16_t flags);
errcode_t ocfs2_snprint_extent_flags(char *str, size_t size, uint8_t flags);
errcode_t ocfs2_snprint_refcount_flags(char *str, size_t size, uint8_t flags);
+errcode_t ocfs2_snprint_cluster_o2cb_flags(char *str, size_t size,
+ uint8_t flags);
errcode_t ocfs2_parse_feature(const char *opts,
ocfs2_fs_options *feature_flags,
ocfs2_fs_options *reverse_flags);
@@ -1251,6 +1253,20 @@ static inline int ocfs2_clusterinfo_valid(struct ocfs2_super_block *osb)
return 0;
}
+static inline int ocfs2_clusterinfo_v2(struct ocfs2_super_block *osb)
+{
+ if (osb->s_feature_compat & OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2)
+ return 1;
+ return 0;
+}
+
+static inline int ocfs2_cluster_o2cb_global_heartbeat(struct ocfs2_super_block *osb)
+{
+ return (ocfs2_o2cb_stack(osb) && ocfs2_clusterinfo_v2(osb) &&
+ (osb->s_cluster_info.ci_stackflags &
+ OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT));
+}
+
static inline int ocfs2_writes_unwritten_extents(struct ocfs2_super_block *osb)
{
/*
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
index ad44807..da3d328 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -61,17 +61,20 @@ static struct feature_level_translation ocfs2_feature_levels_table[] = {
};
static ocfs2_fs_options feature_level_defaults[] = {
- {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB |
+ OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
OCFS2_FEATURE_INCOMPAT_XATTR,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_FEATURE_LEVEL_DEFAULT */
- {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB |
+ OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2,
0,
0}, /* OCFS2_FEATURE_LEVEL_MAX_COMPAT */
- {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB |
+ OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
@@ -85,25 +88,29 @@ static ocfs2_fs_options feature_level_defaults[] = {
};
static ocfs2_fs_options mkfstypes_features_defaults[] = {
- {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB |
+ OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
OCFS2_FEATURE_INCOMPAT_XATTR,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_MKFSTYPE_DEFAULT */
- {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB |
+ OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
OCFS2_FEATURE_INCOMPAT_XATTR,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_MKFSTYPE_DATAFILES */
- {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB |
+ OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
OCFS2_FEATURE_INCOMPAT_XATTR,
OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_MKFSTYPE_MAIL */
- {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB,
+ {OCFS2_FEATURE_COMPAT_BACKUP_SB | OCFS2_FEATURE_COMPAT_JBD2_SB |
+ OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2,
OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
OCFS2_FEATURE_INCOMPAT_INLINE_DATA |
OCFS2_FEATURE_INCOMPAT_XATTR |
@@ -175,6 +182,11 @@ static struct fs_feature_flags ocfs2_supported_features[] = {
{0, OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE, 0},
},
{
+ "clusterinfo-v2",
+ {OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2, 0, 0},
+ {OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2, 0, 0},
+ },
+ {
NULL,
{0, 0, 0},
{0, 0, 0}
@@ -266,6 +278,10 @@ static struct feature_name ocfs2_feature_names[] = {
.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_O2CB_STACK, 0},
},
{
+ .fn_name = "clusterinfo-v2",
+ .fn_flag = {OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2, 0, 0},
+ },
+ {
.fn_name = NULL,
},
};
@@ -330,6 +346,16 @@ static struct flag_name ocfs2_refcount_flag_names[] = {
},
};
+static struct flag_name ocfs2_cluster_o2cb_flag_names[] = {
+ {
+ .fl_name = "Globalheartbeat",
+ .fl_flag = OCFS2_CLUSTER_O2CB_GLOBAL_HEARTBEAT,
+ },
+ {
+ .fl_name = NULL,
+ },
+};
+
static inline void merge_features(ocfs2_fs_options *features,
ocfs2_fs_options new_features)
{
@@ -494,6 +520,13 @@ errcode_t ocfs2_snprint_refcount_flags(char *str, size_t size, uint8_t flags)
str, size, (uint32_t)flags);
}
+errcode_t ocfs2_snprint_cluster_o2cb_flags(char *str, size_t size,
+ uint8_t flags)
+{
+ return ocfs2_snprint_flag_names(ocfs2_cluster_o2cb_flag_names,
+ str, size, (uint32_t)flags);
+}
+
/*
* If we are asked to clear a feature, we also need to clear any other
* features that depend on it.
diff --git a/tunefs.ocfs2/Makefile b/tunefs.ocfs2/Makefile
index 6219af6..e9d77b1 100644
--- a/tunefs.ocfs2/Makefile
+++ b/tunefs.ocfs2/Makefile
@@ -27,7 +27,8 @@ OCFS2NE_FEATURES = \
feature_unwritten_extents \
feature_xattr \
feature_indexed_dirs \
- feature_quota
+ feature_quota \
+ feature_clusterinfo_v2
OCFS2NE_OPERATIONS = \
op_cloned_volume \
diff --git a/tunefs.ocfs2/feature_clusterinfo_v2.c b/tunefs.ocfs2/feature_clusterinfo_v2.c
new file mode 100644
index 0000000..1897662
--- /dev/null
+++ b/tunefs.ocfs2/feature_clusterinfo_v2.c
@@ -0,0 +1,125 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * feature_clusterinfo_v2.c
+ *
+ * ocfs2 tune utility to enable and disable the clusterinfo_v2 feature flag.
+ *
+ * Copyright (C) 2010 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include "ocfs2/ocfs2.h"
+
+#include "libocfs2ne.h"
+
+
+static int enable_clusterinfo_v2(ocfs2_filesys *fs, int flags)
+{
+ errcode_t err = 0;
+ struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
+ struct tools_progress *prog;
+
+ if (ocfs2_clusterinfo_v2(super)) {
+ verbosef(VL_APP,
+ "Clusterinfo v2 feature is already enabled; "
+ "nothing to enable\n");
+ goto out;
+ }
+
+ if (!tools_interact("Enable the clusterinfo v2 feature on "
+ "device \"%s\"? ",
+ fs->fs_devname))
+ goto out;
+
+ prog = tools_progress_start("Enable clusterinfo-v2",
+ "clusterinfo-v2", 1);
+ if (!prog) {
+ err = TUNEFS_ET_NO_MEMORY;
+ tcom_err(err, "while initializing the progress display");
+ goto out;
+ }
+
+ OCFS2_SET_COMPAT_FEATURE(super, OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2);
+ super->s_cluster_info.ci_stackflags = 0;
+
+ tunefs_block_signals();
+ err = ocfs2_write_super(fs);
+ if (err)
+ tcom_err(err, "while writing out the superblock");
+ tunefs_unblock_signals();
+
+ tools_progress_step(prog, 1);
+ tools_progress_stop(prog);
+
+out:
+ return err;
+}
+
+static int disable_clusterinfo_v2(ocfs2_filesys *fs, int flags)
+{
+ errcode_t err = 0;
+ struct ocfs2_super_block *super = OCFS2_RAW_SB(fs->fs_super);
+ struct tools_progress *prog;
+
+ if (!ocfs2_clusterinfo_v2(super)) {
+ verbosef(VL_APP,
+ "Clusterinfo v2 feature is not enabled; "
+ "nothing to disable\n");
+ goto out;
+ }
+
+ if (!tools_interact("Disable the clusterinfo v2 feature on "
+ "device \"%s\"? ",
+ fs->fs_devname))
+ goto out;
+
+ prog = tools_progress_start("Disable clusterinfo-v2",
+ "noclusterinfo-v2", 1);
+ if (!prog) {
+ err = TUNEFS_ET_NO_MEMORY;
+ tcom_err(err, "while initializing the progress display");
+ goto out;
+ }
+
+ OCFS2_CLEAR_COMPAT_FEATURE(super, OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2);
+ super->s_cluster_info.ci_stackflags = 0;
+
+ tunefs_block_signals();
+ err = ocfs2_write_super(fs);
+ if (err)
+ tcom_err(err, "while writing out the superblock");
+ tunefs_unblock_signals();
+
+ tools_progress_step(prog, 1);
+ tools_progress_stop(prog);
+
+out:
+ return err;
+}
+
+DEFINE_TUNEFS_FEATURE_COMPAT(clusterinfo_v2,
+ OCFS2_FEATURE_COMPAT_CLUSTERINFO_V2,
+ TUNEFS_FLAG_RW,
+ enable_clusterinfo_v2,
+ disable_clusterinfo_v2);
+
+#ifdef DEBUG_EXE
+int main(int argc, char *argv[])
+{
+ return tunefs_feature_main(argc, argv, &clusterinfo_v2_feature);
+}
+#endif
diff --git a/tunefs.ocfs2/op_features.c b/tunefs.ocfs2/op_features.c
index 613ea7e..bd41b73 100644
--- a/tunefs.ocfs2/op_features.c
+++ b/tunefs.ocfs2/op_features.c
@@ -45,6 +45,7 @@ extern struct tunefs_feature usrquota_feature;
extern struct tunefs_feature grpquota_feature;
extern struct tunefs_feature refcount_feature;
extern struct tunefs_feature indexed_dirs_feature;
+extern struct tunefs_feature clusterinfo_v2_feature;
/* List of features supported by ocfs2ne */
static struct tunefs_feature *features[] = {
@@ -60,6 +61,7 @@ static struct tunefs_feature *features[] = {
&grpquota_feature,
&refcount_feature,
&indexed_dirs_feature,
+ &clusterinfo_v2_feature,
NULL,
};
--
1.7.0.4
More information about the Ocfs2-tools-devel
mailing list