summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-09-07 02:57:18 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-09-07 02:57:18 -0800
commit79fbd19ecc389089bd285a54667d816e46870790 (patch)
treeb5f3635d56dd3dc9f50955bf63e01d2ca598d1d9
parent698dc55448a28f733683e14b63e3a90128129ef8 (diff)
bcache: fix lost wakeup in allocation code
-rw-r--r--drivers/md/bcache/alloc.c34
-rw-r--r--drivers/md/bcache/alloc.h7
-rw-r--r--drivers/md/bcache/bcache.h1
3 files changed, 19 insertions, 23 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c
index 4143221e28aa..3a58d51ff645 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -1065,46 +1065,40 @@ static int bch_bucket_alloc_set(struct cache_set *c, struct open_bucket *ob,
struct cache_group *devs, long *caches_used,
struct closure *cl)
{
- struct closure_waitlist *waitlist = NULL;
bool waiting = false;
while (1) {
switch (__bch_bucket_alloc_set(c, ob, reserve, nr_replicas,
devs, caches_used)) {
case ALLOC_SUCCESS:
- if (waitlist)
- closure_wake_up(waitlist);
+ if (waiting)
+ closure_wake_up(&c->freelist_wait);
return 0;
case CACHE_SET_FULL:
trace_bcache_cache_set_full(c, reserve, cl);
- if (waitlist)
- closure_wake_up(waitlist);
+ if (waiting)
+ closure_wake_up(&c->freelist_wait);
return -ENOSPC;
case BUCKETS_NOT_AVAILABLE:
trace_bcache_buckets_unavailable_fail(c, reserve, cl);
- waitlist = &c->buckets_available_wait;
- break;
-
case FREELIST_EMPTY:
- waitlist = &c->freelist_wait;
+ if (!cl)
+ return -ENOSPC;
+
+ if (waiting)
+ return -EAGAIN;
+
+ /* Retry allocation after adding ourself to waitlist: */
+ closure_wait(&c->freelist_wait, cl);
+ waiting = true;
break;
default:
BUG();
}
-
- if (!cl)
- return -ENOSPC;
-
- if (waiting)
- return -EAGAIN;
-
- /* Must retry allocation after adding ourself to waitlist */
- closure_wait(waitlist, cl);
- waiting = true;
}
}
@@ -1576,7 +1570,6 @@ static void bch_recalc_capacity(struct cache_set *c)
/* Wake up case someone was waiting for buckets */
closure_wake_up(&c->freelist_wait);
- closure_wake_up(&c->buckets_available_wait);
}
static void bch_stop_write_point(struct cache *ca,
@@ -1690,7 +1683,6 @@ void bch_cache_allocator_stop(struct cache *ca)
/* Avoid deadlocks.. */
- closure_wake_up(&c->buckets_available_wait);
closure_wake_up(&c->freelist_wait);
wake_up(&c->journal.wait);
diff --git a/drivers/md/bcache/alloc.h b/drivers/md/bcache/alloc.h
index 7dbbb23ff67a..3da349c581b3 100644
--- a/drivers/md/bcache/alloc.h
+++ b/drivers/md/bcache/alloc.h
@@ -36,7 +36,12 @@ static inline void bch_wake_allocator(struct cache *ca)
wake_up_process(p);
rcu_read_unlock();
- closure_wake_up(&ca->set->buckets_available_wait);
+ /*
+ * XXX: this is only needed because of ca->reserve_buckets_count, but is
+ * reserve_buckets_count needed anymore? It predates modern
+ * reservations.
+ */
+ closure_wake_up(&ca->set->freelist_wait);
}
#define __open_bucket_next_online_device(_c, _ob, _ptr, _ca) \
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 137c0d7a2e50..bad67a4a2147 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -654,7 +654,6 @@ struct cache_set {
struct mutex bucket_lock;
struct closure_waitlist freelist_wait;
- struct closure_waitlist buckets_available_wait;
/*