diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index eb6f2e6927ad..25f017248a81 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -645,12 +645,7 @@ struct cache_set { */ mempool_t *fill_iter; - /* - * btree_sort() is a merge sort and requires temporary space - single - * element mempool - */ - struct mutex sort_lock; - struct bset *sort; + mempool_t *sort_pool; unsigned sort_crit_factor; /* List of buckets we're currently writing data to */ diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c index 98f0ced236b6..e6882659afb9 100644 --- a/drivers/md/bcache/bset.c +++ b/drivers/md/bcache/bset.c @@ -1047,11 +1047,12 @@ static void __btree_sort(struct btree *b, struct btree_iter *iter, { uint64_t start_time; bool remove_stale = !b->written; + bool used_mempool = false; struct bset *out = (void *) __get_free_pages(__GFP_NOWARN|GFP_NOIO, order); if (!out) { - mutex_lock(&b->c->sort_lock); - out = b->c->sort; + out = page_address(mempool_alloc(b->c->sort_pool, GFP_NOIO)); + used_mempool = true; order = ilog2(bucket_pages(b->c)); } @@ -1071,17 +1072,14 @@ static void __btree_sort(struct btree *b, struct btree_iter *iter, out->seq = b->sets[0].data->seq; out->version = b->sets[0].data->version; swap(out, b->sets[0].data); - - if (b->c->sort == b->sets[0].data) - b->c->sort = out; } else { b->sets[start].data->keys = out->keys; memcpy(b->sets[start].data->start, out->start, (void *) end(out) - (void *) out->start); } - if (out == b->c->sort) - mutex_unlock(&b->c->sort_lock); + if (used_mempool) + mempool_free(virt_to_page(out), b->c->sort_pool); else free_pages((unsigned long) out, order); diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 677a604e7f3f..d05e75627714 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1352,7 +1352,6 @@ static void cache_set_free(struct closure *cl) kobject_put(&ca->kobj); free_pages((unsigned long) c->uuids, ilog2(bucket_pages(c))); - free_pages((unsigned long) c->sort, ilog2(bucket_pages(c))); if (c->bio_split) bioset_free(c->bio_split); @@ -1489,7 +1488,6 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb) init_waitqueue_head(&c->try_wait); init_waitqueue_head(&c->bucket_wait); sema_init(&c->uuid_write_mutex, 1); - mutex_init(&c->sort_lock); spin_lock_init(&c->sort_time.lock); spin_lock_init(&c->btree_gc_time.lock); @@ -1519,7 +1517,8 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb) bucket_pages(c))) || !(c->fill_iter = mempool_create_kmalloc_pool(1, iter_size)) || !(c->bio_split = bioset_create(4, offsetof(struct bbio, bio))) || - !(c->sort = alloc_bucket_pages(GFP_KERNEL, c)) || + !(c->sort_pool = mempool_create_page_pool(1, + ilog2(bucket_pages(c)))) || !(c->uuids = alloc_bucket_pages(GFP_KERNEL, c)) || bch_journal_alloc(c) || bch_btree_cache_alloc(c) ||