diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-09-07 02:57:18 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 12:36:59 -0800 |
commit | b0644111eeacfad0939092acded3b0f8540d1f84 (patch) | |
tree | e77d9b2bdd9e7ce52f5ce09469be99e975b6d3b0 | |
parent | 39034b737d17ced060fdd9913a85e0609ff74cd4 (diff) |
bcache: fix lost wakeup in allocation code
-rw-r--r-- | drivers/md/bcache/alloc.c | 34 | ||||
-rw-r--r-- | drivers/md/bcache/alloc.h | 7 | ||||
-rw-r--r-- | drivers/md/bcache/bcache.h | 1 |
3 files changed, 19 insertions, 23 deletions
diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c index af3bd123d943..b9b1e171fc9d 100644 --- a/drivers/md/bcache/alloc.c +++ b/drivers/md/bcache/alloc.c @@ -1066,46 +1066,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; } } @@ -1577,7 +1571,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, @@ -1691,7 +1684,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; /* |