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