Current sheep cannot handle a case like this: 1. iterate snapshot creation and let latest working VDI have VID 0xffffff 2. create one more snapshot
(The situation can be reproduced with the below sequence: $ dog vdi create 00471718 1G $ dog vdi snapshot 00471718 (repeat 7 times) ) In this case, new VID becomes 0x000000. Current fill_vdi_info() and fill_vdi_info_range() cannot handle this case. It comes from the below two reasons: 1. Recent change 00ecfb24ee46f2 introduced a bug which breaks fill_vdi_info_range() in a case of underflow of its variable i. 2. fill_vdi_info_range() assumes that its parameters, left and right, are obtained from get_vdi_bitmap_range(). get_vdi_bitmap_range() obtains left and right which mean the range of existing VIDs is [left, right), in other words, [left, right - 1]. So fill_vdi_info_range() starts checking from right - 1 to left. But it means fill_vdi_info_range() cannot check VID 0xffffff even VID overflow happens. So this patch lets fill_vdi_info_range() check from right to left, and also change callers' manner (it passes left and right - 1 in ordinal cases). Signed-off-by: Hitoshi Mitake <mitake.hito...@lab.ntt.co.jp> --- sheep/vdi.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/sheep/vdi.c b/sheep/vdi.c index 2889df6..3d14ccf 100644 --- a/sheep/vdi.c +++ b/sheep/vdi.c @@ -1404,9 +1404,11 @@ static int fill_vdi_info_range(uint32_t left, uint32_t right, ret = SD_RES_NO_MEM; goto out; } - for (i = right - 1; i && i >= left; i--) { + + i = right; + while (i >= left) { if (!test_bit(i, sys->vdi_inuse)) - continue; + goto next; ret = sd_read_object(vid_to_vdi_oid(i), (char *)inode, SD_INODE_HEADER_SIZE, 0); @@ -1420,10 +1422,10 @@ static int fill_vdi_info_range(uint32_t left, uint32_t right, /* Read, delete, clone on snapshots */ if (!vdi_is_snapshot(inode)) { vdi_found = true; - continue; + goto next; } if (!vdi_tag_match(iocb, inode)) - continue; + goto next; } else { /* * Rollback & snap create, read, delete on @@ -1438,6 +1440,10 @@ static int fill_vdi_info_range(uint32_t left, uint32_t right, info->vid = inode->vdi_id; goto out; } +next: + if (!i) + break; + i--; } ret = vdi_found ? SD_RES_NO_TAG : SD_RES_NO_VDI; out: @@ -1452,13 +1458,23 @@ static int fill_vdi_info(unsigned long left, unsigned long right, int ret; if (left < right) - return fill_vdi_info_range(left, right, iocb, info); + return fill_vdi_info_range(left, right - 1, iocb, info); + + if (!right) + /* + * a special case right == 0 + * because the variables left and right have values obtained by + * get_vdi_bitmap_range(), they mean used bitmap range is + * [left, right). If right == 0, it means used bitmap range is + * [left, SD_NR_VDIS]. + */ + return fill_vdi_info_range(left, SD_NR_VDIS, iocb, info); - ret = fill_vdi_info_range(0, right, iocb, info); + ret = fill_vdi_info_range(0, right - 1, iocb, info); switch (ret) { case SD_RES_NO_VDI: case SD_RES_NO_TAG: - ret = fill_vdi_info_range(left, SD_NR_VDIS - 1, iocb, info); + ret = fill_vdi_info_range(left, SD_NR_VDIS, iocb, info); break; default: break; -- 1.9.1 -- sheepdog mailing list sheepdog@lists.wpkg.org https://lists.wpkg.org/mailman/listinfo/sheepdog