From 8d59e6d0719f3265d4306e83480f6cd23f6ad977 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Sat, 17 Jun 2017 23:34:47 -0700 Subject: [PATCH] scoutfs: fix alloc eio for free region It's possible for the next segno to fall at the end of an allocation region that doesn't have any bits set. The code shouldn't return -EIO in that case, it should carry on to the next region. Signed-off-by: Zach Brown --- kmod/src/alloc.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/kmod/src/alloc.c b/kmod/src/alloc.c index 75aa408e..6fef77c5 100644 --- a/kmod/src/alloc.c +++ b/kmod/src/alloc.c @@ -131,31 +131,35 @@ int scoutfs_alloc_segno(struct super_block *sb, u64 *segno) ind = sal->next_segno >> SCOUTFS_ALLOC_REGION_SHIFT; nr = sal->next_segno & SCOUTFS_ALLOC_REGION_MASK; - do { + for (;;) { reg = scoutfs_ring_lookup_next(&sal->ring, &ind); - } while (reg == NULL && ind && (ind = 0, nr = 0, 1)); + if (reg == NULL && ind != 0) { + ind = 0; + nr = 0; + continue; + } + if (IS_ERR_OR_NULL(reg)) { + if (IS_ERR(reg)) + ret = PTR_ERR(reg); + else + ret = -ENOSPC; + goto out; + } - if (IS_ERR_OR_NULL(reg)) { - if (IS_ERR(reg)) - ret = PTR_ERR(reg); - else - ret = -ENOSPC; - goto out; + nr = find_next_bit_le(reg->bits, SCOUTFS_ALLOC_REGION_BITS, nr); + if (nr < SCOUTFS_ALLOC_REGION_BITS) + break; + + /* possible for nr to be after all free bits, keep going */ + ind++; + nr = 0; } scoutfs_ring_dirty(&sal->ring, reg); - nr = find_next_bit_le(reg->bits, SCOUTFS_ALLOC_REGION_BITS, nr); - if (nr >= SCOUTFS_ALLOC_REGION_BITS) { - /* XXX corruption? shouldn't find empty regions */ - ret = -EIO; - goto out; - } - ind = le64_to_cpu(reg->index); clear_bit_le(nr, reg->bits); - if (empty_region(reg)) scoutfs_ring_delete(&sal->ring, reg);