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

Signed-off-by: levin li <xingke....@taobao.com>
---
 sheep/ops.c        |   13 ++++++++
 sheep/sheep_priv.h |    1 +
 sheep/vdi.c        |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 97 insertions(+), 0 deletions(-)

diff --git a/sheep/ops.c b/sheep/ops.c
index ccb1c5e..e35e96f 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -353,6 +353,13 @@ static int cluster_get_vdi_attr(struct request *req)
        return ret;
 }
 
+static int cluster_rollback_vdi(struct request *req)
+{
+       uint32_t vid = *(uint32_t *)req->data;
+
+       return rollback_vdi(vid, req->rq.vdi.base_vdi_id);
+}
+
 static int local_get_store_list(struct request *req)
 {
        struct strbuf buf = STRBUF_INIT;
@@ -956,6 +963,12 @@ static struct sd_op_template sd_ops[] = {
                .type = SD_OP_TYPE_CLUSTER,
        },
 
+       [SD_OP_ROLLBACK_VDI] = {
+               .name = "ROLLBACK_VDI",
+               .type = SD_OP_TYPE_CLUSTER,
+               .process_work = cluster_rollback_vdi,
+       },
+
        [SD_OP_FORCE_RECOVER] = {
                .name = "FORCE_RECOVER",
                .type = SD_OP_TYPE_CLUSTER,
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index 90006f6..38b66ad 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -230,6 +230,7 @@ int lookup_vdi(char *name, char *tag, uint32_t *vid, 
uint32_t snapid,
               unsigned int *nr_copies, uint64_t *ctime);
 
 int read_vdis(char *data, int len, unsigned int *rsp_len);
+int rollback_vdi(uint32_t vid, uint32_t snap_vid);
 
 int get_vdi_attr(struct sheepdog_vdi_attr *vattr, int data_len, uint32_t vid,
                uint32_t *attrid, uint64_t ctime, int write,
diff --git a/sheep/vdi.c b/sheep/vdi.c
index f7e762f..36bfa4e 100644
--- a/sheep/vdi.c
+++ b/sheep/vdi.c
@@ -513,6 +513,89 @@ out:
        return ret;
 }
 
+int rollback_vdi(uint32_t vid, uint32_t snap_vid)
+{
+       int ret, i;
+       struct sheepdog_inode *inode, *snap_inode;
+
+       dprintf("%" PRIx32 ", %" PRIx32 "\n", vid, snap_vid);
+
+       inode = xzalloc(sizeof(*inode));
+       snap_inode = xzalloc(sizeof(*snap_inode));
+
+       ret = read_object(vid_to_vdi_oid(vid), (char *)inode,
+                         sizeof(*inode), 0, 0);
+       if (ret != SD_RES_SUCCESS) {
+               eprintf("failed to read VDI %" PRIx32 "\n", vid);
+               ret = SD_RES_NO_VDI;
+               goto out;
+       }
+
+       ret = read_object(vid_to_vdi_oid(snap_vid), (char *)snap_inode,
+                         sizeof(*snap_inode), 0, 0);
+       if (ret != SD_RES_SUCCESS) {
+               eprintf("failed to read VDI %" PRIx32 "\n", snap_vid);
+               ret = SD_RES_NO_BASE_VDI;
+               goto out;
+       }
+
+       if (inode->parent_vdi_id == snap_vid)
+               goto reset_child;
+
+       for (i = 0; i < ARRAY_SIZE(snap_inode->child_vdi_id); i++) {
+               if (!snap_inode->child_vdi_id[i]) {
+                       snap_inode->child_vdi_id[i] = vid;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(snap_inode->child_vdi_id)) {
+               eprintf("failed to set child vdi id(%" PRIx32 ") for %"
+                       PRIx32 "\n", vid, snap_vid);
+               ret = SD_RES_NO_BASE_VDI;
+               goto out;
+       }
+
+       ret = write_object(vid_to_vdi_oid(snap_vid), (char *)snap_inode,
+                          sizeof(*snap_inode), 0, 0, 0, snap_inode->nr_copies);
+       if (ret != SD_RES_SUCCESS) {
+               eprintf("failed to write snapshot VDI %" PRIx32 "\n",
+                       snap_vid);
+               goto out;
+       }
+
+       inode->parent_vdi_id = snap_inode->vdi_id;
+
+reset_child:
+       for (i = 0; i < MAX_DATA_OBJS; i++) {
+               uint64_t oid;
+
+               if (!inode->data_vdi_id[i])
+                       continue;
+
+               if (inode->data_vdi_id[i] != vid)
+                       continue;
+
+               oid = vid_to_data_oid(inode->data_vdi_id[i], i);
+               ret = remove_object(oid, inode->nr_copies);
+               if (ret != SD_RES_SUCCESS)
+                       eprintf("failed to remove object %" PRIx64 "\n", oid);
+       }
+
+       memcpy(inode->data_vdi_id, snap_inode->data_vdi_id,
+              sizeof(inode->data_vdi_id));
+       inode->vdi_size = snap_inode->vdi_size;
+
+       ret = write_object(vid_to_vdi_oid(vid), (char *)inode, sizeof(*inode),
+                          0, 0, 0, inode->nr_copies);
+       if (ret != SD_RES_SUCCESS)
+               eprintf("failed to write VDI %" PRIx32 "\n", vid);
+
+out:
+       free(inode);
+       free(snap_inode);
+       return ret;
+}
+
 int read_vdis(char *data, int len, unsigned int *rsp_len)
 {
        if (len != sizeof(sys->vdi_inuse))
-- 
1.7.1

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

Reply via email to