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 <[email protected]>
Signed-off-by: Hitoshi Mitake <[email protected]>
---
 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

-- 
sheepdog mailing list
[email protected]
https://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to