[sheepdog] [PATCH] dog: a new command "dog upgrade" for various upgrading tools

Hitoshi Mitake mitake.hitoshi at lab.ntt.co.jp
Thu Jul 2 16:29:15 CEST 2015


This patch adds a new command "dog upgrade" and its subcommand
convert-inode for converting old inode file to new version.

Example:
$ dog upgrade inode-convert -o v0.7 original_inode_file new_inode_file

Currently, snapshot isn't supported.

Cc: Masahiro Tsuji <tuji at atworks.co.jp>
Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
 dog/Makefile.am          |   3 +-
 dog/dog.c                |   1 +
 dog/dog.h                |   1 +
 dog/upgrade.c            | 172 +++++++++++++++++++++++++++++++++++++++++++++++
 include/sheepdog_proto.h |  48 +++++++++++++
 5 files changed, 224 insertions(+), 1 deletion(-)
 create mode 100644 dog/upgrade.c

diff --git a/dog/Makefile.am b/dog/Makefile.am
index 1bb1b14..9615468 100644
--- a/dog/Makefile.am
+++ b/dog/Makefile.am
@@ -25,7 +25,8 @@ sbin_PROGRAMS		= dog
 
 dog_SOURCES		= farm/object_tree.c farm/sha1_file.c farm/snap.c \
 			  farm/trunk.c farm/farm.c farm/slice.c \
-			  dog.c common.c treeview.c vdi.c node.c cluster.c
+			  dog.c common.c treeview.c vdi.c node.c cluster.c \
+			  upgrade.c
 
 if BUILD_TRACE
 dog_SOURCES		+= trace.c
diff --git a/dog/dog.c b/dog/dog.c
index 77aa27b..916ce5e 100644
--- a/dog/dog.c
+++ b/dog/dog.c
@@ -182,6 +182,7 @@ static void init_commands(const struct command **commands)
 #ifdef HAVE_NFS
 		nfs_command,
 #endif
+		upgrade_command,
 		{NULL,}
 	};
 
diff --git a/dog/dog.h b/dog/dog.h
index d603328..b099a31 100644
--- a/dog/dog.h
+++ b/dog/dog.h
@@ -115,6 +115,7 @@ extern struct command vdi_command;
 extern struct command node_command;
 extern struct command cluster_command;
 extern struct command alter_command;
+extern struct command upgrade_command;
 
 #ifdef HAVE_TRACE
 extern struct command trace_command;
diff --git a/dog/upgrade.c b/dog/upgrade.c
new file mode 100644
index 0000000..88d87fe
--- /dev/null
+++ b/dog/upgrade.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dog.h"
+
+static struct sd_option upgrade_options[] = {
+	{'o', "orig-version", true, "version of converting inode file"},
+	{ 0, NULL, false, NULL },
+};
+
+enum orig_version {
+	ORIG_VERSION_0_7 = 1,
+	ORIG_VERSION_0_8,
+};
+
+static struct upgrade_cmd_data {
+	enum orig_version orig;
+} upgrade_cmd_data = { ~0, };
+
+static int upgrade_inode_convert(int argc, char **argv)
+{
+	const char *orig_file = argv[optind++], *dst_file = NULL;
+	int orig_fd, dst_fd, ret;
+	struct sd_inode_0_7 *orig_0_7;
+	struct sd_inode_0_8 *orig_0_8;
+	struct stat orig_stat;
+	struct sd_inode *dst;
+
+	if (optind < argc)
+		dst_file = argv[optind++];
+	else {
+		sd_info("please specify destination file path");
+		return EXIT_USAGE;
+	}
+
+	orig_fd = open(orig_file, O_RDONLY);
+	if (orig_fd < 0) {
+		sd_err("failed to open original inode file: %m");
+		return EXIT_SYSFAIL;
+	}
+
+	memset(&orig_stat, 0, sizeof(orig_stat));
+	ret = fstat(orig_fd, &orig_stat);
+	if (ret < 0) {
+		sd_err("failed to stat original inode file: %m");
+		return EXIT_SYSFAIL;
+	}
+
+	dst = xzalloc(sizeof(*dst));
+
+	if (upgrade_cmd_data.orig == ORIG_VERSION_0_7) {
+		orig_0_7 = xzalloc(sizeof(*orig_0_7));
+		ret = xread(orig_fd, orig_0_7, orig_stat.st_size);
+		if (ret != orig_stat.st_size) {
+			sd_err("failed to read original inode file: %m");
+			return EXIT_SYSFAIL;
+		}
+
+		if (orig_0_7->snap_ctime) {
+			sd_err("snapshot cannot be converted");
+			return EXIT_USAGE;
+		}
+
+		memcpy(dst->name, orig_0_7->name, SD_MAX_VDI_LEN);
+		memcpy(dst->tag, orig_0_7->tag, SD_MAX_VDI_TAG_LEN);
+		dst->create_time = orig_0_7->create_time;
+		dst->vm_clock_nsec = orig_0_7->vm_clock_nsec;
+		dst->vdi_size = orig_0_7->vdi_size;
+		dst->vm_state_size = orig_0_7->vm_state_size;
+		dst->copy_policy = orig_0_7->copy_policy;
+		dst->nr_copies = orig_0_7->nr_copies;
+		dst->block_size_shift = orig_0_7->block_size_shift;
+		dst->vdi_id = orig_0_7->vdi_id;
+
+		memcpy(dst->data_vdi_id, orig_0_7->data_vdi_id,
+		       sizeof(uint32_t) * SD_INODE_DATA_INDEX);
+	} else if (upgrade_cmd_data.orig == ORIG_VERSION_0_8) {
+		orig_0_8 = xzalloc(sizeof(*orig_0_8));
+		ret = xread(orig_fd, orig_0_8, orig_stat.st_size);
+
+		if (ret != orig_stat.st_size) {
+			sd_err("failed to read original inode file: %m");
+			return EXIT_SYSFAIL;
+		}
+
+		if (orig_0_8->snap_ctime) {
+			sd_err("snapshot cannot be converted");
+			return EXIT_USAGE;
+		}
+
+		memcpy(dst->name, orig_0_8->name, SD_MAX_VDI_LEN);
+		memcpy(dst->tag, orig_0_8->tag, SD_MAX_VDI_TAG_LEN);
+		dst->create_time = orig_0_8->create_time;
+		dst->vm_clock_nsec = orig_0_8->vm_clock_nsec;
+		dst->vdi_size = orig_0_8->vdi_size;
+		dst->vm_state_size = orig_0_8->vm_state_size;
+		dst->copy_policy = orig_0_8->copy_policy;
+		dst->nr_copies = orig_0_8->nr_copies;
+		dst->block_size_shift = orig_0_8->block_size_shift;
+		dst->vdi_id = orig_0_8->vdi_id;
+
+		memcpy(dst->data_vdi_id, orig_0_8->data_vdi_id,
+		       sizeof(uint32_t) * SD_INODE_DATA_INDEX);
+	} else {
+		sd_info("please specify original version of inode file");
+		return EXIT_FAILURE;
+	}
+
+	dst_fd = open(dst_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+	if (dst_fd < 0) {
+		sd_err("failed to create converted inode file: %m");
+		return EXIT_SYSFAIL;
+	}
+
+	ret = xwrite(dst_fd, dst, sizeof(*dst));
+	if (ret != sizeof(*dst)) {
+		sd_err("failed to write converted inode file: %m");
+		return EXIT_SYSFAIL;
+	}
+
+	return EXIT_SUCCESS;
+}
+
+static struct subcommand upgrade_cmd[] = {
+	{"inode-convert", "<path of original inode file>"
+	 " <path of new inode file>",
+	 "hTo", "check and repair image's consistency",
+	 NULL, CMD_NEED_ARG, upgrade_inode_convert, upgrade_options},
+	{NULL,},
+};
+
+static int upgrade_parser(int ch, const char *opt)
+{
+	switch (ch) {
+	case 'o':
+		if (!strcmp(opt, "v0.7"))
+			upgrade_cmd_data.orig = ORIG_VERSION_0_7;
+		else if (!strcmp(opt, "v0.8"))
+			upgrade_cmd_data.orig = ORIG_VERSION_0_8;
+		else {
+			sd_info("unknown original version: %s", opt);
+			sd_info("valid versions are v0.7 or v0.8");
+			exit(EXIT_FAILURE);
+		}
+
+		break;
+	}
+
+	return 0;
+}
+
+struct command upgrade_command = {
+	"upgrade",
+	upgrade_cmd,
+	upgrade_parser
+};
+
diff --git a/include/sheepdog_proto.h b/include/sheepdog_proto.h
index af9b24f..60e61c0 100644
--- a/include/sheepdog_proto.h
+++ b/include/sheepdog_proto.h
@@ -262,6 +262,54 @@ struct sd_rsp {
 	};
 };
 
+#define MAX_CHILDREN 1024U
+
+/*
+ * struct sd_inode_0_7: old inode format used in v0.7.x
+ * Just used by upgrade tools.
+ */
+struct sd_inode_0_7 {
+	char name[SD_MAX_VDI_LEN];
+	char tag[SD_MAX_VDI_TAG_LEN];
+	uint64_t create_time;
+	uint64_t snap_ctime;
+	uint64_t vm_clock_nsec;
+	uint64_t vdi_size;
+	uint64_t vm_state_size;
+	uint16_t copy_policy;
+	uint8_t  nr_copies;
+	uint8_t  block_size_shift;
+	uint32_t snap_id;
+	uint32_t vdi_id;
+	uint32_t parent_vdi_id;
+	uint32_t child_vdi_id[MAX_CHILDREN];
+	uint32_t data_vdi_id[MAX_DATA_OBJS];
+};
+
+/*
+ * struct sd_inode_0_8: old inode format used in v0.8.x
+ * Just used by upgrade tools.
+ */
+struct sd_inode_0_8 {
+	char name[SD_MAX_VDI_LEN];
+	char tag[SD_MAX_VDI_TAG_LEN];
+	uint64_t create_time;
+	uint64_t snap_ctime;
+	uint64_t vm_clock_nsec;
+	uint64_t vdi_size;
+	uint64_t vm_state_size;
+	uint8_t  copy_policy;
+	uint8_t  store_policy;
+	uint8_t  nr_copies;
+	uint8_t  block_size_shift;
+	uint32_t snap_id;
+	uint32_t vdi_id;
+	uint32_t parent_vdi_id;
+	uint32_t child_vdi_id[MAX_CHILDREN];
+	uint32_t data_vdi_id[SD_INODE_DATA_INDEX];
+	uint32_t btree_counter;
+};
+
 /*
  * Historical notes: previous version of sheepdog (< v0.9.0) has a limit of
  * maximum number of children which can be created from single VDI. So the inode
-- 
1.9.1



More information about the sheepdog mailing list