[sheepdog] [PATCH 1/5] dog: a new command "dog upgrade" for various upgrading tools
Hitoshi Mitake
mitake.hitoshi at lab.ntt.co.jp
Sun Jul 12 07:54:28 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..54a4248
--- /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 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", "upgrade inode object file",
+ 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..0c279eb 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[SD_INODE_DATA_INDEX];
+};
+
+/*
+ * 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