From: levin li <xingke....@taobao.com>

With this command, we can reset a cloned VDI to its initial state as
it's just cloned from a snapshot, the usage is simple:

$ collie vdi reset cloned_vdi_name

Signed-off-by: levin li <xingke....@taobao.com>
---
 collie/collie.h |    1 +
 collie/common.c |   35 ++++++++++++++++++++++++++++++
 collie/vdi.c    |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+), 0 deletions(-)

diff --git a/collie/collie.h b/collie/collie.h
index 7f93ded..5ef2534 100644
--- a/collie/collie.h
+++ b/collie/collie.h
@@ -74,6 +74,7 @@ int sd_read_object(uint64_t oid, void *data, unsigned int 
datalen,
                   uint64_t offset);
 int sd_write_object(uint64_t oid, uint64_t cow_oid, void *data, unsigned int 
datalen,
                    uint64_t offset, uint32_t flags, int copies, int create);
+int sd_remove_object(uint64_t oid, int copies);
 int send_light_req(struct sd_req *hdr, const char *host, int port);
 int send_light_req_get_response(struct sd_req *hdr, const char *host, int 
port);
 
diff --git a/collie/common.c b/collie/common.c
index ce8dcf7..c66c3ff 100644
--- a/collie/common.c
+++ b/collie/common.c
@@ -124,6 +124,41 @@ int sd_write_object(uint64_t oid, uint64_t cow_oid, void 
*data, unsigned int dat
        return SD_RES_SUCCESS;
 }
 
+int sd_remove_object(uint64_t oid, int copies)
+{
+       struct sd_req hdr;
+       struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
+       int fd, ret;
+       unsigned wlen = 0, rlen = 0;
+
+       fd = connect_to(sdhost, sdport);
+       if (fd < 0) {
+               fprintf(stderr, "Failed to connect\n");
+               return SD_RES_EIO;
+       }
+
+       sd_init_req(&hdr, SD_OP_REMOVE_OBJ);
+       hdr.epoch = sd_epoch;
+       hdr.data_length = wlen;
+       hdr.obj.copies = copies;
+       hdr.obj.oid = oid;
+
+       ret = exec_req(fd, &hdr, NULL, &wlen, &rlen);
+       close(fd);
+
+       if (ret) {
+               fprintf(stderr, "Failed to remove object %" PRIx64 "\n", oid);
+               return SD_RES_EIO;
+       }
+       if (rsp->result != SD_RES_SUCCESS) {
+               fprintf(stderr, "Failed to remove object %" PRIx64 ": %s\n", 
oid,
+                               sd_strerror(rsp->result));
+               return rsp->result;
+       }
+
+       return SD_RES_SUCCESS;
+}
+
 int parse_vdi(vdi_parser_func_t func, size_t size, void *data)
 {
        int ret, fd, count;
diff --git a/collie/vdi.c b/collie/vdi.c
index 7e2f5b0..4ac69db 100644
--- a/collie/vdi.c
+++ b/collie/vdi.c
@@ -753,6 +753,66 @@ static int vdi_delete(int argc, char **argv)
        return EXIT_SUCCESS;
 }
 
+static int vdi_reset(int argc, char **argv)
+{
+       char *vdiname = argv[optind++];
+       int ret, i;
+       struct sheepdog_inode inode, pinode;
+       uint32_t vid, pvid;
+
+       ret = find_vdi_name(vdiname, 0, "", &vid, 0);
+       if (ret < 0) {
+               fprintf(stderr, "Failed to open VDI %s\n", vdiname);
+               return EXIT_FAILURE;
+       }
+
+       ret = sd_read_object(vid_to_vdi_oid(vid), &inode, sizeof(inode), 0);
+       if (ret != SD_RES_SUCCESS) {
+               fprintf(stderr, "Failed to read VDI %" PRIx32 "\n", vid);
+               return EXIT_FAILURE;
+       }
+
+       /* check whether it's a cloned VDI */
+       if (inode.snap_id != 1 || inode.parent_vdi_id == 0) {
+               fprintf(stderr, "Can not reset a non-cloned VDI\n");
+               return EXIT_FAILURE;
+       }
+
+       pvid = inode.parent_vdi_id;
+       ret = sd_read_object(vid_to_vdi_oid(pvid), &pinode, sizeof(pinode), 0);
+       if (ret != SD_RES_SUCCESS) {
+               fprintf(stderr, "Can not read parent VDI %" PRIx32 "\n", pvid);
+               return EXIT_FAILURE;
+       }
+
+       for (i = 0; i < MAX_DATA_OBJS; i++) {
+               uint64_t oid;
+
+               if (!inode.data_vdi_id[i])
+                       continue;
+
+               if (!is_data_obj_writeable(&inode, i))
+                       continue;
+
+               oid = vid_to_data_oid(inode.data_vdi_id[i], i);
+               ret = sd_remove_object(oid, inode.nr_copies);
+               if (ret != SD_RES_SUCCESS)
+                       fprintf(stderr, "Failed to remove object %" PRIx64
+                               "\n", oid);
+       }
+
+       memcpy(inode.data_vdi_id, pinode.data_vdi_id,
+              sizeof(inode.data_vdi_id));
+
+       ret = sd_write_object(vid_to_vdi_oid(vid), 0, &inode, sizeof(inode),
+                             0, 0, inode.nr_copies, 0);
+       if (ret != SD_RES_SUCCESS)
+               fprintf(stderr, "Failed to write object %" PRIx64 "\n",
+                       vid_to_vdi_oid(vid));
+
+       return SD_RES_SUCCESS;
+}
+
 static int vdi_object(int argc, char **argv)
 {
        char *vdiname = argv[optind];
@@ -1538,6 +1598,9 @@ static struct subcommand vdi_cmd[] = {
        {"delete", "<vdiname>", "saph", "delete an image",
         NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG,
         vdi_delete, vdi_options},
+       {"reset", "<vdiname>", "aph", "reset an cloned image",
+        NULL, SUBCMD_FLAG_NEED_NODELIST|SUBCMD_FLAG_NEED_THIRD_ARG,
+        vdi_reset, vdi_options},
        {"list", "[vdiname]", "aprh", "list images",
         NULL, SUBCMD_FLAG_NEED_NODELIST, vdi_list, vdi_options},
        {"tree", NULL, "aph", "show images in tree view format",
-- 
1.7.1

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

Reply via email to