Take a view of the following snapshot tree: base vdi --> snapshot vdi --> cloned vdi when cloned vdi has its own data objects created by copy-on-write, we firstly delete the cloned VDI, then delete the base VDI, at last we delete snapshot VDI, the the snapshot VDI would delete fail in this case because in the old code, I try to delete all the VDIs from the VDI tree, but the base VDI and the cloned VDI have beed deleted, and it causes an error which finally cause snapshot VDI delete fail. This patch is another version of my previous one which is here: http://lists.wpkg.org/pipermail/sheepdog/2012-May/003332.html I simplely reset the delete_error flag, as Kazutaka mentions, it's not good to do this, but we should never try to delete the VDIs already deleted again, so I mark an VDI as deeply deleted by clearing its name and size, which means the VDI and it data objects have already been deleted, then in the next deletion work, we can just ignore these VDIs. If the data objects haven't been deleted, then we just clear its name to mark it as deleted, next time, we can try to delete its data objects. Signed-off-by: levin li <xingke.lwp at taobao.com> --- sheep/vdi.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sheep/vdi.c b/sheep/vdi.c index cd6b557..445aeda 100644 --- a/sheep/vdi.c +++ b/sheep/vdi.c @@ -391,7 +391,7 @@ struct deletion_work { static LIST_HEAD(deletion_work_list); -static int delete_inode(struct deletion_work *dw) +static int delete_inode(struct deletion_work *dw, int objs_deleted) { struct sheepdog_inode *inode = NULL; int ret = SD_RES_SUCCESS; @@ -414,8 +414,11 @@ static int delete_inode(struct deletion_work *dw) if (dw->delete_error) inode->vdi_size = 0; - else + else { memset(inode->name, 0, sizeof(inode->name)); + if (objs_deleted) + inode->vdi_size = 0; + } ret = write_object(dw->vnodes, dw->epoch, vid_to_vdi_oid(dw->vid), (char *)inode, SD_INODE_HEADER_SIZE, 0, 0, @@ -458,6 +461,9 @@ static void delete_one(struct work *work) goto out; } + if (inode->vdi_size == 0 && inode->name[0] == '\0') + goto out; + for (i = 0; i < MAX_DATA_OBJS; i++) { if (!inode->data_vdi_id[i]) continue; @@ -497,7 +503,7 @@ static void delete_one_done(struct work *work) return; } - delete_inode(dw); + delete_inode(dw, 1); list_del(&dw->dw_siblings); @@ -647,7 +653,7 @@ int start_deletion(uint32_t vid, uint32_t epoch) dprintf("snapshot chain has valid vdi, " "just mark vdi %" PRIx32 " as deleted.\n", dw->vid); - delete_inode(dw); + delete_inode(dw, 0); return SD_RES_SUCCESS; } } -- 1.7.10 |