Current sheep cannot handle a case of VID overflow correctly. The main cause of this problem is invalid usage of fill_vdi_info_range() by fill_vdi_info() in a case of overflow. This patch fixes this problem.
In addition, this patch lets 0x000000 be an invalid VID. It is for VID recycling. In some places of sheepdog, parent_vid is used as a value which indicates that the VDI has a parent (clone or snapshot) or not (working VDI). So this patch lets the first VID 0x000001 and prevent this sort of confusion. Signed-off-by: Hitoshi Mitake <[email protected]> --- sheep/vdi.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/sheep/vdi.c b/sheep/vdi.c index 63e578d..0505d7d 100644 --- a/sheep/vdi.c +++ b/sheep/vdi.c @@ -1345,7 +1345,7 @@ out: /* * Return SUCCESS (range of bits set): * Iff we get a bitmap range [left, right) that VDI might be set between. if - * right < start, this means a wrap around case where we should examine the + * right < left, this means a wrap around case where we should examine the * two split ranges, [left, SD_NR_VDIS - 1] and [0, right). 'Right' is the free * bit that might be used by newly created VDI. * @@ -1356,13 +1356,17 @@ static int get_vdi_bitmap_range(const char *name, unsigned long *left, unsigned long *right) { *left = sd_hash_vdi(name); + + if (unlikely(!*left)) + *left = 1; /* 0x000000 should be skipeed */ + *right = find_next_zero_bit(sys->vdi_inuse, SD_NR_VDIS, *left); if (*left == *right) return SD_RES_NO_VDI; if (*right == SD_NR_VDIS) { /* Wrap around */ - *right = find_next_zero_bit(sys->vdi_inuse, SD_NR_VDIS, 0); + *right = find_next_zero_bit(sys->vdi_inuse, SD_NR_VDIS, 1); if (*right == SD_NR_VDIS) return SD_RES_FULL_VDI; } @@ -1404,7 +1408,7 @@ static int fill_vdi_info_range(uint32_t left, uint32_t right, ret = SD_RES_NO_MEM; goto out; } - for (i = right - 1; i >= left; i--) { + for (i = right - 1; i >= left && i; i--) { ret = sd_read_object(vid_to_vdi_oid(i), (char *)inode, SD_INODE_HEADER_SIZE, 0); if (ret != SD_RES_SUCCESS) @@ -1448,14 +1452,24 @@ static int fill_vdi_info(unsigned long left, unsigned long right, { int ret; + assert(left != right); + /* + * If left == right, fill_vdi_info() shouldn't called by vdi_lookup(). + * vdi_lookup() must return SD_RES_NO_VDI to its caller. + */ + if (left < right) return fill_vdi_info_range(left, right, iocb, info); - ret = fill_vdi_info_range(0, right, iocb, info); + if (likely(1 < right)) + ret = fill_vdi_info_range(1, right, iocb, info); + else + ret = SD_RES_NO_VDI; + 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 [email protected] https://lists.wpkg.org/mailman/listinfo/sheepdog
