From: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp> This removes old vdi deletion code, which reclaims objects only when all relevant snapshots are deleted, and uses a generational reference counting algorithm. Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp> --- sheep/vdi.c | 213 +++-------------------------------------------------------- 1 file changed, 9 insertions(+), 204 deletions(-) diff --git a/sheep/vdi.c b/sheep/vdi.c index c374314..8681519 100644 --- a/sheep/vdi.c +++ b/sheep/vdi.c @@ -568,47 +568,11 @@ int read_vdis(char *data, int len, unsigned int *rsp_len) } struct deletion_work { - uint32_t done; - struct work work; - struct list_head list; struct request *req; - uint32_t vid; - - int count; - uint32_t *buf; }; -static LIST_HEAD(deletion_work_list); - -static int delete_inode(struct deletion_work *dw) -{ - struct sd_inode *inode = NULL; - int ret = SD_RES_SUCCESS; - - inode = xzalloc(sizeof(*inode)); - ret = read_object(vid_to_vdi_oid(dw->vid), (char *)inode, - SD_INODE_HEADER_SIZE, 0); - if (ret != SD_RES_SUCCESS) { - ret = SD_RES_EIO; - goto out; - } - - memset(inode->name, 0, sizeof(inode->name)); - - ret = write_object(vid_to_vdi_oid(dw->vid), (char *)inode, - SD_INODE_HEADER_SIZE, 0, false); - if (ret != 0) { - ret = SD_RES_EIO; - goto out; - } - -out: - free(inode); - return ret; -} - static int notify_vdi_deletion(uint32_t vdi_id) { struct sd_req hdr; @@ -629,11 +593,11 @@ static int notify_vdi_deletion(uint32_t vdi_id) static void delete_one(struct work *work) { struct deletion_work *dw = container_of(work, struct deletion_work, work); - uint32_t vdi_id = *(dw->buf + dw->count - dw->done - 1); + uint32_t vdi_id = dw->vid; int ret, i, nr_deleted; struct sd_inode *inode = NULL; - sd_dprintf("%d %d, %16x", dw->done, dw->count, vdi_id); + sd_eprintf("%16" PRIx32, vdi_id); inode = malloc(sizeof(*inode)); if (!inode) { @@ -649,9 +613,6 @@ static void delete_one(struct work *work) goto out; } - if (inode->vdi_size == 0 && vdi_is_deleted(inode)) - goto out; - for (nr_deleted = 0, i = 0; i < MAX_DATA_OBJS; i++) { uint64_t oid; @@ -660,15 +621,10 @@ static void delete_one(struct work *work) oid = vid_to_data_oid(inode->data_vdi_id[i], i); - if (inode->data_vdi_id[i] != inode->vdi_id) { - sd_dprintf("object %" PRIx64 " is base's data, would" - " not be deleted.", oid); - continue; - } - - ret = remove_object(oid); + ret = dec_object_refcnt(oid, inode->data_ref[i].generation, + inode->data_ref[i].count); if (ret != SD_RES_SUCCESS) - sd_eprintf("remove object %" PRIx64 " fail, %d", oid, + sd_eprintf("discard ref %" PRIx64 " fail, %d", oid, ret); nr_deleted++; @@ -677,11 +633,10 @@ static void delete_one(struct work *work) if (nr_deleted) notify_vdi_deletion(vdi_id); - if (vdi_is_deleted(inode)) - goto out; - inode->vdi_size = 0; memset(inode->name, 0, sizeof(inode->name)); + memset((char *)inode + SD_INODE_HEADER_SIZE, 0, + SD_INODE_SIZE - SD_INODE_HEADER_SIZE); write_object(vid_to_vdi_oid(vdi_id), (void *)inode, sizeof(*inode), 0, false); @@ -694,175 +649,25 @@ static void delete_one_done(struct work *work) struct deletion_work *dw = container_of(work, struct deletion_work, work); struct request *req = dw->req; - dw->done++; - if (dw->done < dw->count) { - queue_work(sys->deletion_wqueue, &dw->work); - return; - } - - list_del(&dw->list); - put_request(req); - - free(dw->buf); - free(dw); - - if (!list_empty(&deletion_work_list)) { - dw = list_first_entry(&deletion_work_list, - struct deletion_work, list); - - queue_work(sys->deletion_wqueue, &dw->work); - } -} - -static int fill_vdi_list(struct deletion_work *dw, uint32_t root_vid) -{ - int ret, i; - struct sd_inode *inode = NULL; - int done = dw->count; - uint32_t vid; - - inode = malloc(SD_INODE_HEADER_SIZE); - if (!inode) { - sd_eprintf("failed to allocate memory"); - goto err; - } - - dw->buf[dw->count++] = root_vid; -again: - vid = dw->buf[done++]; - ret = read_backend_object(vid_to_vdi_oid(vid), (char *)inode, - SD_INODE_HEADER_SIZE, 0); - - if (ret != SD_RES_SUCCESS) { - sd_eprintf("cannot find VDI object"); - goto err; - } - - if (!vdi_is_deleted(inode) && vid != dw->vid) - goto out; - - for (i = 0; i < ARRAY_SIZE(inode->child_vdi_id); i++) { - if (!inode->child_vdi_id[i]) - continue; - - dw->buf[dw->count++] = inode->child_vdi_id[i]; - } - - if (dw->buf[done]) - goto again; -err: - free(inode); - return 0; -out: - free(inode); - return 1; -} - -static uint64_t get_vdi_root(uint32_t vid, bool *cloned) -{ - int ret; - struct sd_inode *inode = NULL; - - *cloned = false; - - inode = malloc(SD_INODE_HEADER_SIZE); - if (!inode) { - sd_eprintf("failed to allocate memory"); - vid = 0; - goto out; - } -next: - ret = read_backend_object(vid_to_vdi_oid(vid), (char *)inode, - SD_INODE_HEADER_SIZE, 0); - - if (vid == inode->vdi_id && inode->snap_id == 1 - && inode->parent_vdi_id != 0 - && !inode->snap_ctime) { - sd_dprintf("vdi %" PRIx32 " is a cloned vdi.", vid); - /* current vdi is a cloned vdi */ - *cloned = true; - } - - if (ret != SD_RES_SUCCESS) { - sd_eprintf("cannot find VDI object"); - vid = 0; - goto out; - } - - if (!inode->parent_vdi_id) - goto out; - - vid = inode->parent_vdi_id; - - goto next; -out: - free(inode); - - return vid; } static int start_deletion(struct request *req, uint32_t vid) { struct deletion_work *dw = NULL; - int ret = SD_RES_NO_MEM; - bool cloned; - uint32_t root_vid; dw = xzalloc(sizeof(struct deletion_work)); - /* buf is to store vdi id of every object */ - dw->buf = xzalloc(SD_INODE_SIZE - SD_INODE_HEADER_SIZE); - dw->count = 0; + dw->vid = vid; dw->req = req; dw->work.fn = delete_one; dw->work.done = delete_one_done; - root_vid = get_vdi_root(dw->vid, &cloned); - if (!root_vid) { - ret = SD_RES_EIO; - goto err; - } - - ret = fill_vdi_list(dw, root_vid); - if (ret) { - /* - * if the VDI is a cloned VDI, delete its objects - * no matter whether the VDI tree is clear. - */ - if (cloned) { - dw->buf[0] = vid; - dw->count = 1; - } else { - sd_dprintf("snapshot chain has valid vdi, " - "just mark vdi %" PRIx32 " as deleted.", - dw->vid); - delete_inode(dw); - return SD_RES_SUCCESS; - } - } - - sd_dprintf("%d", dw->count); - - if (dw->count == 0) - goto out; - uatomic_inc(&req->refcnt); + queue_work(sys->deletion_wqueue, &dw->work); - if (list_empty(&deletion_work_list)) { - list_add_tail(&dw->list, &deletion_work_list); - queue_work(sys->deletion_wqueue, &dw->work); - } else - list_add_tail(&dw->list, &deletion_work_list); -out: return SD_RES_SUCCESS; -err: - if (dw) - free(dw->buf); - free(dw); - - return ret; } int get_vdi_attr(struct sheepdog_vdi_attr *vattr, int data_len, -- 1.7.9.5 |