[sheepdog] [PATCH v4 1/3] sheep: handle VID overflow correctly
Hitoshi Mitake
mitake.hitoshi at lab.ntt.co.jp
Sun Mar 8 05:08:33 CET 2015
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 <mitake.hitoshi at lab.ntt.co.jp>
---
sheep/vdi.c | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
v4:
- revive 0xffffff
v3:
- handle a case of 0xffffff and 0x000000 VID
diff --git a/sheep/vdi.c b/sheep/vdi.c
index 8114fb5..ea64719 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,15 @@ 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--) {
+ /*
+ * below bitmap checking is an optimization for
+ * vdi_lookup_for_creation()
+ */
+ if (!test_bit(i, sys->vdi_inuse) &&
+ !test_bit(i, sys->vdi_deleted))
+ continue;
+
ret = sd_read_object(vid_to_vdi_oid(i), (char *)inode,
SD_INODE_HEADER_SIZE, 0);
if (ret != SD_RES_SUCCESS)
@@ -1448,14 +1460,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
More information about the sheepdog
mailing list