[sheepdog] [PATCH v3] dog/cluster: cluster-wide snapshot save or load specified vdi

Hitoshi Mitake mitake.hitoshi at gmail.com
Sun Jul 27 10:43:10 CEST 2014


On Tue, Jul 1, 2014 at 11:23 AM, Ruoyu <liangry at ucweb.com> wrote:
> Any feedback for the patch?

Looks good to me. Could you rebase it on the latest master?

Thanks,
Hitoshi

>
>
> 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 <liangry at 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 at lists.wpkg.org
> http://lists.wpkg.org/mailman/listinfo/sheepdog



More information about the sheepdog mailing list