This will fix a bug that after deletion of clones, we fail to create clones with the snapshot that we previousy cloned. Signed-off-by: Liu Yuan <namei.unix at gmail.com> --- sheep/vdi.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/sheep/vdi.c b/sheep/vdi.c index f4c589a..c627d26 100644 --- a/sheep/vdi.c +++ b/sheep/vdi.c @@ -1028,6 +1028,48 @@ static uint64_t get_vdi_root(uint32_t vid, bool *cloned) return vid; } +static void clear_parent_child_vdi(uint32_t vid) +{ + struct sd_inode * inode = xmalloc(SD_INODE_HEADER_SIZE); + uint32_t pvid, i; + int ret; + + ret = read_backend_object(vid_to_vdi_oid(vid), (char *)inode, + SD_INODE_HEADER_SIZE, 0); + if (ret != SD_RES_SUCCESS) { + sd_err("failed to read inode %"PRIx32, vid); + goto out; + } + + pvid = inode->parent_vdi_id; + ret = read_backend_object(vid_to_vdi_oid(pvid), (char *)inode, + SD_INODE_HEADER_SIZE, 0); + if (ret != SD_RES_SUCCESS) { + sd_err("failed to read parent inode %"PRIx32, pvid); + goto out; + } + + for (i = 0; i < MAX_CHILDREN; i++) + if (inode->child_vdi_id[i] == vid) { + inode->child_vdi_id[i] = 0; + break; + } + + if (i == MAX_CHILDREN) { + sd_info("failed to find child %"PRIx32, vid); + goto out; + } + + ret = sd_write_object(vid_to_vdi_oid(pvid), (char *)inode, + SD_INODE_HEADER_SIZE, 0, false); + if (ret != SD_RES_SUCCESS) { + sd_err("failed to update parent %"PRIx32, pvid); + goto out; + } +out: + free(inode); +} + static int start_deletion(struct request *req, uint32_t vid) { struct deletion_work *dw = NULL; @@ -1066,6 +1108,7 @@ static int start_deletion(struct request *req, uint32_t vid) if (cloned) { dw->delete_vid_array[0] = vid; dw->delete_vid_count = 1; + clear_parent_child_vdi(vid); } else { sd_debug("snapshot chain has valid vdi, just mark vdi %" PRIx32 " as deleted.", dw->target_vid); -- 1.8.1.2 |