summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-10-25 10:23:55 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-25 10:24:31 -0800
commit87a7bcb915e9ae71d90f550f7cbdc7f4a0386ea9 (patch)
treeda7754646468ca7a69a039c542ecfbe9cc29e60f
parent0963e0830c3c29476e4050f6a7cc0fbc30e94dfd (diff)
bcache: fix handling of ptr_offset in allocation code
only affects replication
-rw-r--r--drivers/md/bcache/alloc.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index ce335693bb44..cc773059ff27 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -969,6 +969,8 @@ static enum bucket_alloc_ret bch_bucket_alloc_group(struct cache_set *c,
unsigned fail_idx = -1, i;
unsigned available = 0;
+ BUG_ON(nr_replicas > ARRAY_SIZE(ob->ptrs));
+
if (ob->nr_ptrs >= nr_replicas)
return ALLOC_SUCCESS;
@@ -1022,12 +1024,16 @@ static enum bucket_alloc_ret bch_bucket_alloc_group(struct cache_set *c,
memmove(&ob->ptrs[1],
&ob->ptrs[0],
ob->nr_ptrs * sizeof(ob->ptrs[0]));
+ memmove(&ob->ptr_offset[1],
+ &ob->ptr_offset[0],
+ ob->nr_ptrs * sizeof(ob->ptr_offset[0]));
ob->nr_ptrs++;
ob->ptrs[0] = (struct bch_extent_ptr) {
.gen = ca->bucket_gens[bucket],
.offset = bucket_to_sector(ca, bucket),
.dev = ca->sb.nr_this_dev,
};
+ ob->ptr_offset[0] = 0;
__set_bit(ca->sb.nr_this_dev, caches_used);
available--;
@@ -1167,7 +1173,6 @@ static struct open_bucket *bch_open_bucket_get(struct cache_set *c,
BUG_ON(ret->nr_ptrs);
atomic_set(&ret->pin, 1); /* XXX */
- memset(ret->ptr_offset, 0, sizeof(ret->ptr_offset));
ret->has_full_ptrs = false;
c->open_buckets_nr_free--;
@@ -1231,7 +1236,9 @@ static void open_bucket_copy_unused_ptrs(struct cache_set *c,
struct bch_extent_ptr tmp = old->ptrs[i];
tmp.offset += old->ptr_offset[i];
- new->ptrs[new->nr_ptrs++] = tmp;
+ new->ptrs[new->nr_ptrs] = tmp;
+ new->ptr_offset[new->nr_ptrs] = 0;
+ new->nr_ptrs++;
}
cache_member_info_put();
}
@@ -1276,7 +1283,7 @@ static int open_bucket_add_buckets(struct cache_set *c,
{
const struct bch_extent_ptr *ptr;
long caches_used[BITS_TO_LONGS(MAX_CACHES_PER_SET)];
- unsigned i, end;
+ int i, dst;
/*
* We might be allocating pointers to add to an existing extent
@@ -1295,29 +1302,21 @@ static int open_bucket_add_buckets(struct cache_set *c,
__set_bit(ptr->dev, caches_used);
/*
- * Any duplicate pointers get moved to the end - later,
+ * Shuffle pointers to devices we already have to the end:
+ * bch_bucket_alloc_set() will add new pointers to the statr of @b, and
* bch_alloc_sectors_done() will add the first nr_replicas ptrs to @e:
*/
- end = ob->nr_ptrs;
- i = 0;
- while (i < end) {
+ for (i = dst = ob->nr_ptrs - 1; i >= 0; --i)
if (__test_and_set_bit(ob->ptrs[i].dev, caches_used)) {
- struct bch_extent_ptr tmp = ob->ptrs[i];
-
+ if (i != dst) {
+ swap(ob->ptrs[i], ob->ptrs[dst]);
+ swap(ob->ptr_offset[i], ob->ptr_offset[dst]);
+ }
+ --dst;
nr_replicas++;
-
- memmove(&ob->ptrs[i],
- &ob->ptrs[i + 1],
- (ob->nr_ptrs - i - 1) * sizeof(ob->ptrs[0]));
- ob->ptrs[ob->nr_ptrs - 1] = tmp;
- end--;
- } else {
- i++;
}
- }
- return bch_bucket_alloc_set(c, wp, ob, nr_replicas,
- caches_used, cl);
+ return bch_bucket_alloc_set(c, wp, ob, nr_replicas, caches_used, cl);
}
/*