Any feedback for the patch?

On 2014年06月18日 17:08, Ruoyu wrote:
It is useful for users who want to backup or restore only part of
all VDIs from cluster-wide snapshot.

To show which VDIs are snapshot, dog cluster snapshot show command
is added.

Usage and example:

1. save all vdi:
    dog cluster snapshot save snapname /tmp/ss

2. save some specified vdi:
    dog cluster snapshot save snapname /tmp/ss test0 test1 test2

3. load all vdi:
    dog cluster snapshot load snapname /tmp/ss

4. load some specified vdi:
    dog cluster snapshot load snapname /tmp/ss test6 test0 test3

5. show snapshot:
    dog cluster snapshot show snapname /tmp/ss

Signed-off-by: Ruoyu <lian...@ucweb.com>
---
  dog/cluster.c   |  86 ++++++++++++++++++++++++++++++++---
  dog/farm/farm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
  dog/farm/farm.h |  10 +++-
  3 files changed, 224 insertions(+), 11 deletions(-)

diff --git a/dog/cluster.c b/dog/cluster.c
index 69ec07c..13aef8b 100644
--- a/dog/cluster.c
+++ b/dog/cluster.c
@@ -326,11 +326,25 @@ static void fill_object_tree(uint32_t vid, const char 
*name, const char *tag,
        uint64_t vdi_oid = vid_to_vdi_oid(vid), vmstate_oid;
        uint32_t vdi_id;
        uint32_t nr_objs, nr_vmstate_object;
+       struct vdi_option *opt = (struct vdi_option *)data;
+       bool matched;
/* ignore active vdi */
        if (!vdi_is_snapshot(i))
                return;
+ /* iff vdi specified in command line */
+       if (opt->count > 0) {
+               matched = false;
+               for (int n = 0; n < opt->count; n++)
+                       if (strcmp(name, opt->name[n]) == 0) {
+                               matched = true;
+                               break;
+                       }
+               if (!matched)
+                       return;
+       }
+
        /* fill vdi object id */
        object_tree_insert(vdi_oid, i->nr_copies, i->copy_policy);
@@ -360,6 +374,7 @@ static int save_snapshot(int argc, char **argv)
        const char *tag = argv[optind++];
        char *path, *p;
        int ret = EXIT_SYSFAIL, uninitialized_var(unused);
+       struct vdi_option opt;
unused = strtol(tag, &p, 10);
        if (tag != p) {
@@ -367,11 +382,11 @@ static int save_snapshot(int argc, char **argv)
                return EXIT_USAGE;
        }
- if (!argv[optind]) {
+       path = argv[optind++];
+       if (!path) {
                sd_err("Please specify the path to save snapshot.");
                return EXIT_USAGE;
        }
-       path = argv[optind];
if (farm_init(path) != SD_RES_SUCCESS)
                goto out;
@@ -382,8 +397,23 @@ static int save_snapshot(int argc, char **argv)
                goto out;
        }
- if (parse_vdi(fill_object_tree, SD_INODE_SIZE, NULL) != SD_RES_SUCCESS)
+       opt.count = argc - optind;
+       opt.name = argv + optind;
+       if (parse_vdi(fill_object_tree, SD_INODE_SIZE, &opt) != SD_RES_SUCCESS)
+               goto out;
+
+       if (object_tree_size() == 0) {
+               sd_err("Object not found. It may be caused by:");
+               if (opt.count > 0) {
+                       sd_err("1. The specified VDIs are not found.");
+                       sd_err("2. The specified VDIs don't have snapshots.");
+               } else {
+                       sd_err("1. The cluster is empty.");
+                       sd_err("2. All VDIs of the cluster "
+                                         "don't have snapshots.");
+               }
                goto out;
+       }
if (farm_save_snapshot(tag) != SD_RES_SUCCESS)
                goto out;
@@ -408,11 +438,11 @@ static int load_snapshot(int argc, char **argv)
        if (tag == p)
                idx = 0;
- if (!argv[optind]) {
+       path = argv[optind++];
+       if (!path) {
                sd_err("Please specify the path to save snapshot.");
                return EXIT_USAGE;
        }
-       path = argv[optind];
if (farm_init(path) != SD_RES_SUCCESS)
                goto out;
@@ -430,16 +460,55 @@ static int load_snapshot(int argc, char **argv)
        if (cluster_format(0, NULL) != SD_RES_SUCCESS)
                goto out;
- if (farm_load_snapshot(idx, tag) != SD_RES_SUCCESS)
+       if (farm_load_snapshot(idx, tag, argc - optind, argv + optind)
+                       != SD_RES_SUCCESS)
                goto out;
ret = EXIT_SUCCESS;
+
  out:
        if (ret)
                sd_err("Fail to load snapshot");
        return ret;
  }
+static int show_snapshot(int argc, char **argv)
+{
+       char *tag = argv[optind++];
+       char *path, *p;
+       uint32_t idx;
+       int ret = EXIT_SYSFAIL;
+
+       idx = strtol(tag, &p, 10);
+       if (tag == p)
+               idx = 0;
+
+       path = argv[optind++];
+       if (!path) {
+               sd_err("Please specify the path to show snapshot.");
+               return EXIT_USAGE;
+       }
+
+       if (farm_init(path) != SD_RES_SUCCESS)
+               goto out;
+
+       if (!farm_contain_snapshot(idx, tag)) {
+               sd_err("Snapshot index or tag does not exist.");
+               goto out;
+       }
+
+       if (farm_show_snapshot(idx, tag, argc - optind, argv + optind)
+                       != SD_RES_SUCCESS)
+               goto out;
+
+       ret = EXIT_SUCCESS;
+
+out:
+       if (ret)
+               sd_err("Fail to show snapshot");
+       return ret;
+}
+
  #define RECOVER_PRINT \
        "Caution! Please try starting all the cluster nodes normally before\n" \
        "running this command.\n\n" \
@@ -530,6 +599,8 @@ static struct subcommand cluster_snapshot_cmd[] = {
         NULL, CMD_NEED_ARG, list_snapshot, NULL},
        {"load", NULL, "h", "load snapshot from localpath",
         NULL, CMD_NEED_ARG | CMD_NEED_NODELIST, load_snapshot, NULL},
+       {"show", NULL, "h", "show vdi list from snapshot",
+        NULL, CMD_NEED_ARG | CMD_NEED_NODELIST, show_snapshot, NULL},
        {NULL},
  };
@@ -578,7 +649,8 @@ static struct subcommand cluster_cmd[] = {
         NULL, CMD_NEED_NODELIST, cluster_format, cluster_options},
        {"shutdown", NULL, "aph", "stop Sheepdog",
         NULL, 0, cluster_shutdown, cluster_options},
-       {"snapshot", "<tag|idx> <path>", "aph", "snapshot/restore the cluster",
+       {"snapshot", "<tag|idx> <path> [vdi1] [vdi2] ...",
+        "aph", "snapshot/restore the cluster",
         cluster_snapshot_cmd, CMD_NEED_ARG,
         cluster_snapshot, cluster_options},
        {"recover", NULL, "afph",
diff --git a/dog/farm/farm.c b/dog/farm/farm.c
index fb2b08d..e5d86b2 100644
--- a/dog/farm/farm.c
+++ b/dog/farm/farm.c
@@ -40,10 +40,18 @@ struct active_vdi_entry {
        uint8_t store_policy;
  };
+struct registered_obj_entry {
+       struct rb_node rb;
+       uint64_t oid;
+};
+
  /* We use active_vdi_tree to create active vdi on top of the snapshot chain */
  static struct rb_root active_vdi_tree = RB_ROOT;
  /* We have to register vdi information first before loading objects */
  static struct rb_root registered_vdi_tree = RB_ROOT;
+/* register object if vdi specified */
+static struct rb_root registered_obj_tree = RB_ROOT;
+static uint64_t obj_to_load;
struct snapshot_work {
        struct trunk_entry entry;
@@ -413,7 +421,8 @@ static void do_load_object(struct work *work)
        if (is_vdi_obj(sw->entry.oid))
                add_active_vdi(buffer);
- farm_show_progress(uatomic_add_return(&loaded, 1), trunk_get_count());
+       farm_show_progress(uatomic_add_return(&loaded, 1),
+                       (obj_to_load > 0) ? obj_to_load : trunk_get_count());
        free(buffer);
        return;
  error:
@@ -430,9 +439,25 @@ static void load_object_done(struct work *work)
        free(sw);
  }
+static int registered_obj_cmp(struct registered_obj_entry *a,
+                             struct registered_obj_entry *b)
+{
+       return intcmp(a->oid, b->oid);
+}
+
  static int queue_load_snapshot_work(struct trunk_entry *entry, void *data)
  {
-       struct snapshot_work *sw = xzalloc(sizeof(struct snapshot_work));
+       struct snapshot_work *sw;
+       struct registered_obj_entry key;
+
+       if (obj_to_load > 0) {
+               key.oid = entry->oid;
+               if (!rb_search(&registered_obj_tree, &key, rb,
+                               registered_obj_cmp))
+                       return 0;
+       }
+
+       sw = xzalloc(sizeof(struct snapshot_work));
memcpy(&sw->entry, entry, sizeof(struct trunk_entry));
        sw->work.fn = do_load_object;
@@ -442,14 +467,89 @@ static int queue_load_snapshot_work(struct trunk_entry 
*entry, void *data)
        return 0;
  }
-int farm_load_snapshot(uint32_t idx, const char *tag)
+static int visit_vdi_obj_entry(struct trunk_entry *entry, void *data)
+{
+       int ret = -1;
+       size_t size;
+       struct sd_inode *inode;
+       struct vdi_option *opt = (struct vdi_option *)data;
+
+       if (!is_vdi_obj(entry->oid))
+               return 0;
+
+       inode = slice_read(entry->sha1, &size);
+       if (!inode) {
+               sd_err("Fail to load vdi object, oid %"PRIx64, entry->oid);
+               goto out;
+       }
+
+       if (opt->count == 0) {
+               if (opt->enable_if_blank)
+                       opt->func(inode);
+       } else {
+               for (int i = 0; i < opt->count; i++)
+                       if (!strcmp(inode->name, opt->name[i])) {
+                               opt->func(inode);
+                               break;
+                       }
+       }
+
+       ret = 0;
+out:
+       free(inode);
+       return ret;
+}
+
+static void do_register_obj(uint64_t oid)
+{
+       struct registered_obj_entry *new;
+
+       new = xmalloc(sizeof(*new));
+       new->oid = oid;
+       if (rb_search(&registered_obj_tree, new, rb, registered_obj_cmp)) {
+               free(new);
+               return;
+       }
+
+       rb_insert(&registered_obj_tree, new, rb, registered_obj_cmp);
+       obj_to_load++;
+}
+
+static void register_obj(struct sd_inode *inode)
+{
+       do_register_obj(vid_to_vdi_oid(inode->vdi_id));
+
+       for (int i = 0; i < SD_INODE_DATA_INDEX; i++) {
+               if (!inode->data_vdi_id[i])
+                       continue;
+
+               do_register_obj(vid_to_data_oid(inode->data_vdi_id[i], i));
+       }
+}
+
+int farm_load_snapshot(uint32_t idx, const char *tag, int count, char **name)
  {
        int ret = -1;
        unsigned char trunk_sha1[SHA1_DIGEST_SIZE];
+       struct vdi_option opt;
if (get_trunk_sha1(idx, tag, trunk_sha1) < 0)
                goto out;
+ opt.count = count;
+       opt.name = name;
+       opt.func = register_obj;
+       opt.enable_if_blank = false;
+
+       if (for_each_entry_in_trunk(trunk_sha1, visit_vdi_obj_entry, &opt) < 0)
+               goto out;
+
+       if (count > 0 && obj_to_load == 0) {
+               sd_err("Objects of specified VDIs are not found "
+                          "in local cluster snapshot storage.");
+               goto out;
+       }
+
        wq = create_work_queue("load snapshot", WQ_DYNAMIC);
        if (for_each_entry_in_trunk(trunk_sha1, queue_load_snapshot_work,
                                    NULL) < 0)
@@ -466,5 +566,38 @@ int farm_load_snapshot(uint32_t idx, const char *tag)
  out:
        rb_destroy(&active_vdi_tree, struct active_vdi_entry, rb);
        rb_destroy(&registered_vdi_tree, struct registered_vdi_entry, rb);
+       rb_destroy(&registered_obj_tree, struct registered_obj_entry, rb);
+       return ret;
+}
+
+static void print_vdi(struct sd_inode *inode)
+{
+       static int seq;
+
+       sd_info("%d. VDI id: %"PRIx32", name: %s, tag: %s",
+                       ++seq, inode->vdi_id, inode->name, inode->tag);
+}
+
+int farm_show_snapshot(uint32_t idx, const char *tag, int count, char **name)
+{
+       int ret = -1;
+       unsigned char trunk_sha1[SHA1_DIGEST_SIZE];
+       struct vdi_option opt;
+
+       if (get_trunk_sha1(idx, tag, trunk_sha1) < 0)
+               goto out;
+
+       opt.count = count;
+       opt.name = name;
+       opt.func = print_vdi;
+       opt.enable_if_blank = true;
+
+       if (for_each_entry_in_trunk(trunk_sha1, visit_vdi_obj_entry, &opt) < 0)
+               goto out;
+
+       ret = 0;
+out:
+       if (ret)
+               sd_err("Fail to show snapshot.");
        return ret;
  }
diff --git a/dog/farm/farm.h b/dog/farm/farm.h
index 95dcfca..b95006a 100644
--- a/dog/farm/farm.h
+++ b/dog/farm/farm.h
@@ -49,11 +49,19 @@ struct snap_log {
        unsigned char trunk_sha1[SHA1_DIGEST_SIZE];
  };
+struct vdi_option {
+       int count;
+       char **name;
+       void (*func)(struct sd_inode *inode);
+       bool enable_if_blank;
+};
+
  /* farm.c */
  int farm_init(const char *path);
  bool farm_contain_snapshot(uint32_t idx, const char *tag);
  int farm_save_snapshot(const char *tag);
-int farm_load_snapshot(uint32_t idx, const char *tag);
+int farm_load_snapshot(uint32_t idx, const char *tag, int count, char **name);
+int farm_show_snapshot(uint32_t idx, const char *tag, int count, char **name);
  char *get_object_directory(void);
/* trunk.c */


--
sheepdog mailing list
sheepdog@lists.wpkg.org
http://lists.wpkg.org/mailman/listinfo/sheepdog

Reply via email to