summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-03-21 21:32:19 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2017-01-18 21:38:43 -0900
commit3205df3b5e8235f05370e859275cabb3c5f2822a (patch)
tree81310814eaec528cf2304c8de42d6a9d77f67fe1
parentd2d68205c41cf9688809717b4ea21c6e7bbd1a11 (diff)
bcache: fix allocator shutdown
the BUG_ON(!atomic_read(&ob->pin)) line was wrong - since there's no lock around putting the ref, have to use the wait_event() method
-rw-r--r--drivers/md/bcache/alloc.c44
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index 469ef659c2d3..c779bd9071d9 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -1602,13 +1602,33 @@ found:
bch_open_bucket_put(c, ob);
}
+static bool bch_dev_has_open_write_point(struct cache *ca)
+{
+ struct cache_set *c = ca->set;
+ struct bch_extent_ptr *ptr;
+ struct open_bucket *ob;
+
+ for (ob = c->open_buckets;
+ ob < c->open_buckets + ARRAY_SIZE(c->open_buckets);
+ ob++)
+ if (atomic_read(&ob->pin)) {
+ mutex_lock(&ob->lock);
+ for (ptr = ob->ptrs; ptr < ob->ptrs + ob->nr_ptrs; ptr++)
+ if (ptr->dev == ca->sb.nr_this_dev) {
+ mutex_unlock(&ob->lock);
+ return true;
+ }
+ mutex_unlock(&ob->lock);
+ }
+
+ return false;
+}
+
/* device goes ro: */
void bch_cache_allocator_stop(struct cache *ca)
{
struct cache_set *c = ca->set;
struct cache_group *tier = &c->cache_tiers[ca->mi.tier];
- struct open_bucket *ob;
- struct bch_extent_ptr *ptr;
struct task_struct *p;
struct closure cl;
unsigned i;
@@ -1675,24 +1695,12 @@ void bch_cache_allocator_stop(struct cache *ca)
/* Now wait for any in flight writes: */
while (1) {
- bool found = false;
+ closure_wait(&c->open_buckets_wait, &cl);
- for (ob = c->open_buckets;
- ob < c->open_buckets + ARRAY_SIZE(c->open_buckets);
- ob++) {
- mutex_lock(&ob->lock);
- for (ptr = ob->ptrs; ptr < ob->ptrs + ob->nr_ptrs; ptr++)
- if (ptr->dev == ca->sb.nr_this_dev) {
- BUG_ON(!atomic_read(&ob->pin));
- closure_wait(&c->open_buckets_wait, &cl);
- found = true;
- break;
- }
- mutex_unlock(&ob->lock);
- }
-
- if (!found)
+ if (!bch_dev_has_open_write_point(ca)) {
+ closure_wake_up(&c->open_buckets_wait);
break;
+ }
closure_sync(&cl);
}