[sheepdog] [PATCH 2/5] dog: upgrade command for epoch log file
Hitoshi Mitake
mitake.hitoshi at lab.ntt.co.jp
Sun Jul 12 07:54:29 CEST 2015
This patch adds a new upgrade command for epoch log file. It can be
used as below:
$ dog upgrade epoch-convert <original epoch file path> <new file path>
Example of output:
number of vnodes of each nodes:
IPv4 ip:127.0.0.1 port:7000 == 64
IPv4 ip:127.0.0.1 port:7001 == 64
IPv4 ip:127.0.0.1 port:7002 == 64
please supply the above numbers to sheeps with -V option
As the output says, these numbers must be supplied to new sheep
processes with -V option for enabling fixedvnodes storategy. In other
words, the upgraded cluster cannot use autovnode strategy.
Cc: Masahiro Tsuji <tuji at atworks.co.jp>
Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
dog/upgrade.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++
include/internal_proto.h | 25 ++++++++++
2 files changed, 149 insertions(+)
diff --git a/dog/upgrade.c b/dog/upgrade.c
index 54a4248..d1b55a4 100644
--- a/dog/upgrade.c
+++ b/dog/upgrade.c
@@ -32,6 +32,126 @@ static struct upgrade_cmd_data {
enum orig_version orig;
} upgrade_cmd_data = { ~0, };
+static int upgrade_epoch_convert(int argc, char **argv)
+{
+ const char *orig_file = argv[optind++], *dst_file = NULL;
+ struct stat epoch_stat;
+ time_t timestamp;
+ int fd, new_fd, buf_len, ret, nr_nodes;
+ struct sd_node_0_7 *nodes_0_7 = NULL;
+ struct sd_node_0_8 *nodes_0_8 = NULL;
+ int node_size = -1;
+ struct sd_node *new_nodes;
+
+ if (optind < argc)
+ dst_file = argv[optind++];
+ else {
+ sd_info("please specify destination file path");
+ return EXIT_USAGE;
+ }
+
+ if (upgrade_cmd_data.orig == ORIG_VERSION_0_7)
+ node_size = sizeof(struct sd_node_0_7);
+ else if (upgrade_cmd_data.orig == ORIG_VERSION_0_8)
+ node_size = sizeof(struct sd_node_0_8);
+ else {
+ sd_info("please specify original version of epoch file");
+ return EXIT_USAGE;
+ }
+
+ fd = open(orig_file, O_RDONLY);
+ if (fd < 0) {
+ sd_err("failed to open epoch log file: %m");
+ return EXIT_SYSFAIL;
+ }
+
+ memset(&epoch_stat, 0, sizeof(epoch_stat));
+ ret = fstat(fd, &epoch_stat);
+ if (ret < 0) {
+ sd_err("failed to stat epoch log file: %m");
+ return EXIT_SYSFAIL;
+ }
+
+ buf_len = epoch_stat.st_size - sizeof(timestamp);
+ if (buf_len < 0) {
+ sd_err("invalid epoch log file: %m");
+ return EXIT_SYSFAIL;
+ }
+
+ if (upgrade_cmd_data.orig == ORIG_VERSION_0_7) {
+ nodes_0_7 = xzalloc(buf_len);
+ ret = xread(fd, nodes_0_7, buf_len);
+ } else {
+ sd_assert(upgrade_cmd_data.orig == ORIG_VERSION_0_8);
+ nodes_0_8 = xzalloc(buf_len);
+ ret = xread(fd, nodes_0_8, buf_len);
+ }
+
+ if (ret < 0) {
+ sd_err("failed to read epoch log file: %m");
+ return EXIT_SYSFAIL;
+ }
+
+ if (ret % node_size != 0) {
+ sd_err("invalid epoch log file size");
+ return EXIT_SYSFAIL;
+ }
+
+ nr_nodes = ret / node_size;
+ new_nodes = xcalloc(nr_nodes, sizeof(struct sd_node));
+
+ ret = xread(fd, ×tamp, sizeof(timestamp));
+ if (ret != sizeof(timestamp)) {
+ sd_err("invalid epoch log file, failed to read timestamp: %m");
+ return EXIT_SYSFAIL;
+ }
+
+ for (int i = 0; i < nr_nodes; i++) {
+ if (upgrade_cmd_data.orig == ORIG_VERSION_0_7) {
+ memcpy(&new_nodes[i].nid, &nodes_0_7[i].nid,
+ sizeof(struct node_id));
+ new_nodes[i].nr_vnodes = nodes_0_7[i].nr_vnodes;
+ new_nodes[i].zone = nodes_0_7[i].zone;
+ new_nodes[i].space = nodes_0_7[i].space;
+ } else {
+ sd_assert(upgrade_cmd_data.orig == ORIG_VERSION_0_8);
+
+ memcpy(&new_nodes[i].nid, &nodes_0_8[i].nid,
+ sizeof(struct node_id));
+ new_nodes[i].nr_vnodes = nodes_0_8[i].nr_vnodes;
+ new_nodes[i].zone = nodes_0_8[i].zone;
+ new_nodes[i].space = nodes_0_8[i].space;
+ }
+ }
+
+ new_fd = open(dst_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+ if (new_fd < 0) {
+ sd_err("failed to create a new epoch log file: %m");
+ return EXIT_SYSFAIL;
+ }
+
+ ret = xwrite(new_fd, new_nodes, sizeof(struct sd_node) * nr_nodes);
+ if (ret != sizeof(struct sd_node) * nr_nodes) {
+ sd_err("failed to write node list to a new epoch log file: %m");
+ return EXIT_SYSFAIL;
+ }
+
+ ret = xwrite(new_fd, ×tamp, sizeof(timestamp));
+ if (ret != sizeof(timestamp)) {
+ sd_err("failed to write timestamp to a new epoch log file: %m");
+ return EXIT_SYSFAIL;
+ }
+
+ sd_info("number of vnodes of each nodes:");
+ for (int i = 0; i < nr_nodes; i++)
+ sd_info("\t%s == %"PRIu16, node_to_str(&new_nodes[i]),
+ new_nodes[i].nr_vnodes);
+
+ sd_info("please supply the above numbers to sheeps with -V option");
+
+ return EXIT_SUCCESS;
+}
+
static int upgrade_inode_convert(int argc, char **argv)
{
const char *orig_file = argv[optind++], *dst_file = NULL;
@@ -141,6 +261,10 @@ static struct subcommand upgrade_cmd[] = {
" <path of new inode file>",
"hTo", "upgrade inode object file",
NULL, CMD_NEED_ARG, upgrade_inode_convert, upgrade_options},
+ {"epoch-convert", "<path of original epoch log file>"
+ " <path of new epoch log file>",
+ "hTo", "upgrade epoch log file",
+ NULL, CMD_NEED_ARG, upgrade_epoch_convert, upgrade_options},
{NULL,},
};
diff --git a/include/internal_proto.h b/include/internal_proto.h
index 90421f4..fe159a6 100644
--- a/include/internal_proto.h
+++ b/include/internal_proto.h
@@ -188,6 +188,31 @@ struct disk_info {
#define DISK_MAX 32
#define WEIGHT_MIN (1ULL << 32) /* 4G */
+
+/*
+ * struct sd_node_0_7: an old sd_node struct used in 0.7.x
+ * This struct is defined just for upgrading.
+ */
+struct sd_node_0_7 {
+ struct node_id nid;
+ uint16_t nr_vnodes;
+ uint32_t zone;
+ uint64_t space;
+};
+
+/*
+ * struct sd_node_0_8: an old sd_node struct used in 0.8.x
+ * This struct is defined just for upgrading.
+ * The difference is just things related to diskvnodes.
+ */
+struct sd_node_0_8 {
+ struct rb_node rb;
+ struct node_id nid;
+ uint16_t nr_vnodes;
+ uint32_t zone;
+ uint64_t space;
+};
+
struct sd_node {
struct rb_node rb;
struct node_id nid;
--
1.9.1
More information about the sheepdog
mailing list