diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-08-27 02:37:58 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-08-27 02:37:58 -0800 |
commit | 0a9ad028970ba45acb365a559bfbd81c86918ec8 (patch) | |
tree | 468ba38777ddda0f2b296584197075a80dda701d | |
parent | 17b8d5efc11585f3eb87238237df78f61fefc4fe (diff) |
bcache: rename async_split -> btree_interior_update
& refactoring
-rw-r--r-- | drivers/md/bcache/bcache.h | 9 | ||||
-rw-r--r-- | drivers/md/bcache/btree_gc.c | 13 | ||||
-rw-r--r-- | drivers/md/bcache/btree_types.h | 14 | ||||
-rw-r--r-- | drivers/md/bcache/btree_update.c | 198 | ||||
-rw-r--r-- | drivers/md/bcache/btree_update.h | 65 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 13 |
6 files changed, 165 insertions, 147 deletions
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index fca21a796c17..137c0d7a2e50 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -613,12 +613,9 @@ struct cache_set { unsigned btree_reserve_cache_nr; struct mutex btree_reserve_cache_lock; - mempool_t btree_async_split_pool; - - struct list_head btree_node_pending_free; - struct mutex btree_node_pending_free_lock; - - struct mutex async_split_lock; + mempool_t btree_interior_update_pool; + struct list_head btree_interior_update_list; + struct mutex btree_interior_update_lock; struct workqueue_struct *wq; diff --git a/drivers/md/bcache/btree_gc.c b/drivers/md/bcache/btree_gc.c index 5dfa8e766717..486c47372458 100644 --- a/drivers/md/bcache/btree_gc.c +++ b/drivers/md/bcache/btree_gc.c @@ -280,12 +280,13 @@ static void bch_mark_metadata(struct cache_set *c) static void bch_mark_pending_btree_node_frees(struct cache_set *c) { struct bucket_stats_cache_set stats = { 0 }; + struct btree_interior_update *as; struct pending_btree_node_free *d; - mutex_lock(&c->btree_node_pending_free_lock); + mutex_lock(&c->btree_interior_update_lock); gc_pos_set(c, gc_phase(GC_PHASE_PENDING_DELETE)); - list_for_each_entry(d, &c->btree_node_pending_free, list) + for_each_pending_btree_node_free(c, as, d) if (d->index_update_done) __bch_gc_mark_key(c, bkey_i_to_s_c(&d->key), c->sb.btree_node_size, true, @@ -295,7 +296,7 @@ static void bch_mark_pending_btree_node_frees(struct cache_set *c) * cache_set_stats: */ - mutex_unlock(&c->btree_node_pending_free_lock); + mutex_unlock(&c->btree_interior_update_lock); } static void bch_mark_scan_keylists(struct cache_set *c) @@ -450,7 +451,7 @@ static void bch_coalesce_nodes(struct btree *old_nodes[GC_MERGE_NODES], unsigned i, nr_old_nodes, nr_new_nodes, u64s = 0; unsigned blocks = btree_blocks(c) * 2 / 3; struct btree *new_nodes[GC_MERGE_NODES]; - struct async_split *as; + struct btree_interior_update *as; struct btree_reserve *res; struct keylist keylist; struct bkey_format_state format_state; @@ -499,10 +500,10 @@ static void bch_coalesce_nodes(struct btree *old_nodes[GC_MERGE_NODES], goto out; } - as = __bch_async_split_alloc(old_nodes, nr_old_nodes, iter); + as = __bch_btree_interior_update_alloc(old_nodes, nr_old_nodes, iter); for (i = 0; i < nr_old_nodes; i++) - bch_async_split_will_free_node(as, old_nodes[i]); + bch_btree_interior_update_will_free_node(as, old_nodes[i]); /* Repack everything with @new_format and sort down to one bset */ for (i = 0; i < nr_old_nodes; i++) diff --git a/drivers/md/bcache/btree_types.h b/drivers/md/bcache/btree_types.h index 4734c0da89c8..5bce26ba3f95 100644 --- a/drivers/md/bcache/btree_types.h +++ b/drivers/md/bcache/btree_types.h @@ -14,7 +14,7 @@ struct cache_set; struct open_bucket; -struct async_split; +struct btree_interior_update; struct btree_write { unsigned index; @@ -25,7 +25,7 @@ struct btree_write { struct btree_root { struct btree *b; - struct async_split *as; + struct btree_interior_update *as; /* On disk root - see async splits: */ __BKEY_PADDED(key, BKEY_BTREE_PTR_VAL_U64s_MAX); @@ -56,7 +56,8 @@ struct btree { * node to point to them: we update the parent in memory immediately, * but then we must wait until the children have been written out before * the update to the parent can be written - this is a list of the - * async_splits that are blocking this node from being written: + * btree_interior_updates that are blocking this node from being + * written: */ struct list_head write_blocked; @@ -67,13 +68,6 @@ struct btree { struct open_bucket *ob; - /* - * When a node is going to be freed while write_blocked nonzero, we have - * to preserve the write ordering - this then points to the async_split - * that's waiting on writes before making the new node visible: - */ - struct async_split *as; - /* lru list */ struct list_head list; diff --git a/drivers/md/bcache/btree_update.c b/drivers/md/bcache/btree_update.c index 251d2f6e7d65..3fc2fcb6bd65 100644 --- a/drivers/md/bcache/btree_update.c +++ b/drivers/md/bcache/btree_update.c @@ -18,7 +18,7 @@ #include <linux/sort.h> #include <trace/events/bcache.h> -static void async_split_updated_root(struct async_split *, +static void btree_interior_update_updated_root(struct btree_interior_update *, struct btree *); /* Calculate ideal packed bkey format for new btree nodes: */ @@ -74,38 +74,42 @@ bool bch_btree_node_format_fits(struct btree *b, struct bkey_format *new_f) * @b is going to be freed, allocate a pending_btree_node_free in @as: */ void bch_btree_node_free_start(struct cache_set *c, - struct async_split *as, + struct btree_interior_update *as, struct btree *b) { struct pending_btree_node_free *d; BUG_ON(as->nr_pending >= ARRAY_SIZE(as->pending)); - d = &as->pending[as->nr_pending++]; - d->index_update_done = false; + mutex_lock(&c->btree_interior_update_lock); + + d = &as->pending[as->nr_pending++]; + d->index_update_done = false; + d->seq = b->data->keys.seq; + d->btree_id = b->btree_id; + d->level = b->level; bkey_copy(&d->key, &b->key); - mutex_lock(&c->btree_node_pending_free_lock); - list_add(&d->list, &c->btree_node_pending_free); - mutex_unlock(&c->btree_node_pending_free_lock); + mutex_unlock(&c->btree_interior_update_lock); } /* * We're doing the index update that makes @b unreachable, update stuff to * reflect that: * - * Must be called _before_ async_split_updated_root() or - * async_split_updated_btree: + * Must be called _before_ btree_interior_update_updated_root() or + * btree_interior_update_updated_btree: */ static void bch_btree_node_free_index(struct cache_set *c, struct btree *b, enum btree_id id, struct bkey_s_c k, struct bucket_stats_cache_set *stats) { + struct btree_interior_update *as; struct pending_btree_node_free *d; - mutex_lock(&c->btree_node_pending_free_lock); + mutex_lock(&c->btree_interior_update_lock); - list_for_each_entry(d, &c->btree_node_pending_free, list) + for_each_pending_btree_node_free(c, as, d) if (!bkey_cmp(k.k->p, d->key.k.p) && bkey_val_bytes(k.k) == bkey_val_bytes(&d->key.k) && !memcmp(k.v, &d->key.v, bkey_val_bytes(k.k))) @@ -157,7 +161,7 @@ found: */ } - mutex_unlock(&c->btree_node_pending_free_lock); + mutex_unlock(&c->btree_interior_update_lock); } static void __btree_node_free(struct cache_set *c, struct btree *b, @@ -223,9 +227,6 @@ static void bch_btree_node_free_ondisk(struct cache_set *c, BUG_ON(!pending->index_update_done); - mutex_lock(&c->btree_node_pending_free_lock); - list_del(&pending->list); - bch_mark_key(c, bkey_i_to_s_c(&pending->key), -c->sb.btree_node_size, true, gc_phase(GC_PHASE_PENDING_DELETE), @@ -234,8 +235,6 @@ static void bch_btree_node_free_ondisk(struct cache_set *c, * Don't apply stats - pending deletes aren't tracked in * cache_set_stats: */ - - mutex_unlock(&c->btree_node_pending_free_lock); } void btree_open_bucket_put(struct cache_set *c, struct btree *b) @@ -369,6 +368,7 @@ static void bch_btree_set_root_inmem(struct cache_set *c, struct btree *b, mutex_lock(&c->btree_root_lock); btree_node_root(b) = b; + mutex_unlock(&c->btree_root_lock); if (btree_reserve) { /* @@ -390,7 +390,6 @@ static void bch_btree_set_root_inmem(struct cache_set *c, struct btree *b, bch_cache_set_stats_apply(c, &stats, &btree_reserve->disk_res, gc_pos_btree_root(b->btree_id)); } - mutex_unlock(&c->btree_root_lock); bch_recalc_btree_reserve(c); } @@ -435,7 +434,7 @@ void bch_btree_set_root_initial(struct cache_set *c, struct btree *b, * journal write. */ static void bch_btree_set_root(struct btree_iter *iter, struct btree *b, - struct async_split *as, + struct btree_interior_update *as, struct btree_reserve *btree_reserve) { struct cache_set *c = iter->c; @@ -454,7 +453,7 @@ static void bch_btree_set_root(struct btree_iter *iter, struct btree *b, bch_btree_set_root_inmem(c, b, btree_reserve); - async_split_updated_root(as, b); + btree_interior_update_updated_root(as, b); /* * Unlock old root after new root is visible: @@ -782,20 +781,20 @@ relock: /* Asynchronous interior node update machinery */ -struct async_split *__bch_async_split_alloc(struct btree *nodes[], - unsigned nr_nodes, - struct btree_iter *iter) +struct btree_interior_update * +__bch_btree_interior_update_alloc(struct btree *nodes[], unsigned nr_nodes, + struct btree_iter *iter) { struct cache_set *c = iter->c; - struct async_split *as; + struct btree_interior_update *as; struct journal_entry_pin_list *pin_list = NULL; unsigned i, pin_idx = UINT_MAX; - as = mempool_alloc(&c->btree_async_split_pool, GFP_NOIO); + as = mempool_alloc(&c->btree_interior_update_pool, GFP_NOIO); memset(as, 0, sizeof(*as)); closure_init(&as->cl, &c->cl); as->c = c; - as->mode = ASYNC_SPLIT_NO_UPDATE; + as->mode = BTREE_INTERIOR_NO_UPDATE; bch_keylist_init(&as->parent_keys, as->inline_keys, ARRAY_SIZE(as->inline_keys)); @@ -848,24 +847,30 @@ struct async_split *__bch_async_split_alloc(struct btree *nodes[], six_unlock_write(&nodes[i]->lock); } + mutex_lock(&c->btree_interior_update_lock); + list_add(&as->list, &c->btree_interior_update_list); + mutex_unlock(&c->btree_interior_update_lock); + return as; } -struct async_split *bch_async_split_alloc(struct btree *b, struct btree_iter *iter) +struct btree_interior_update * +bch_btree_interior_update_alloc(struct btree *b, struct btree_iter *iter) { - return __bch_async_split_alloc(&b, 1, iter); + return __bch_btree_interior_update_alloc(&b, 1, iter); } -static void async_split_free(struct closure *cl) +static void btree_interior_update_free(struct closure *cl) { - struct async_split *as = container_of(cl, struct async_split, cl); + struct btree_interior_update *as = container_of(cl, struct btree_interior_update, cl); - mempool_free(as, &as->c->btree_async_split_pool); + mempool_free(as, &as->c->btree_interior_update_pool); } -static void async_split_pointers_written(struct closure *cl) +static void btree_interior_update_pointers_written(struct closure *cl) { - struct async_split *as = container_of(cl, struct async_split, cl); + struct btree_interior_update *as = + container_of(cl, struct btree_interior_update, cl); struct cache_set *c = as->c; unsigned i; @@ -873,15 +878,25 @@ static void async_split_pointers_written(struct closure *cl) journal_pin_drop(&c->journal, &as->journal); + mutex_lock(&c->btree_interior_update_lock); + for (i = 0; i < as->nr_pending; i++) bch_btree_node_free_ondisk(c, &as->pending[i]); + as->nr_pending = 0; + + mutex_unlock(&c->btree_interior_update_lock); + + mutex_lock(&c->btree_interior_update_lock); + list_del(&as->list); + mutex_unlock(&c->btree_interior_update_lock); - closure_return_with_destructor(cl, async_split_free); + closure_return_with_destructor(cl, btree_interior_update_free); } -static void async_split_nodes_written(struct closure *cl) +static void btree_interior_update_nodes_written(struct closure *cl) { - struct async_split *as = container_of(cl, struct async_split, cl); + struct btree_interior_update *as = + container_of(cl, struct btree_interior_update, cl); struct cache_set *c = as->c; struct btree *b; @@ -892,16 +907,16 @@ static void async_split_nodes_written(struct closure *cl) */ retry: - mutex_lock(&c->async_split_lock); + mutex_lock(&c->btree_interior_update_lock); switch (as->mode) { - case ASYNC_SPLIT_NO_UPDATE: + case BTREE_INTERIOR_NO_UPDATE: BUG(); - case ASYNC_SPLIT_UPDATING_BTREE: + case BTREE_INTERIOR_UPDATING_NODE: /* The usual case: */ b = READ_ONCE(as->b); if (!six_trylock_read(&b->lock)) { - mutex_unlock(&c->async_split_lock); + mutex_unlock(&c->btree_interior_update_lock); six_lock_read(&b->lock); six_unlock_read(&b->lock); goto retry; @@ -910,34 +925,34 @@ retry: BUG_ON(!btree_node_dirty(b)); closure_wait(&btree_current_write(b)->wait, cl); - list_del(&as->list); + list_del(&as->write_blocked_list); if (list_empty(&b->write_blocked)) __bch_btree_node_write(b, NULL, -1); six_unlock_read(&b->lock); break; - case ASYNC_SPLIT_UPDATING_AS: + case BTREE_INTERIOR_UPDATING_AS: /* * The btree node we originally updated has been freed and is * being rewritten - so we need to write anything here, we just - * need to signal to that async_split that it's ok to make the + * need to signal to that btree_interior_update that it's ok to make the * new replacement node visible: */ closure_put(&as->parent_as->cl); /* - * and then we have to wait on that async_split to finish: + * and then we have to wait on that btree_interior_update to finish: */ closure_wait(&as->parent_as->wait, cl); break; - case ASYNC_SPLIT_UPDATING_ROOT: + case BTREE_INTERIOR_UPDATING_ROOT: /* b is the new btree root: */ b = READ_ONCE(as->b); if (!six_trylock_read(&b->lock)) { - mutex_unlock(&c->async_split_lock); + mutex_unlock(&c->btree_interior_update_lock); six_lock_read(&b->lock); six_unlock_read(&b->lock); goto retry; @@ -950,94 +965,95 @@ retry: /* * We don't have to wait anything anything here (before - * async_split_pointers_written frees the old nodes ondisk) - - * we've ensured that the very next journal write will have the - * pointer to the new root, and before the allocator can reuse - * the old nodes it'll have to do a journal commit: + * btree_interior_update_pointers_written frees the old nodes + * ondisk) - we've ensured that the very next journal write will + * have the pointer to the new root, and before the allocator + * can reuse the old nodes it'll have to do a journal commit: */ six_unlock_read(&b->lock); } - mutex_unlock(&c->async_split_lock); + mutex_unlock(&c->btree_interior_update_lock); - continue_at(cl, async_split_pointers_written, system_wq); + continue_at(cl, btree_interior_update_pointers_written, system_wq); } /* * We're updating @b with pointers to nodes that haven't finished writing yet: * block @b from being written until @as completes */ -static void async_split_updated_btree(struct async_split *as, - struct btree *b) +static void btree_interior_update_updated_btree(struct btree_interior_update *as, + struct btree *b) { - mutex_lock(&as->c->async_split_lock); + mutex_lock(&as->c->btree_interior_update_lock); - BUG_ON(as->mode != ASYNC_SPLIT_NO_UPDATE); + BUG_ON(as->mode != BTREE_INTERIOR_NO_UPDATE); BUG_ON(!btree_node_dirty(b)); - as->mode = ASYNC_SPLIT_UPDATING_BTREE; + as->mode = BTREE_INTERIOR_UPDATING_NODE; as->b = b; - list_add(&as->list, &b->write_blocked); + list_add(&as->write_blocked_list, &b->write_blocked); - mutex_unlock(&as->c->async_split_lock); + mutex_unlock(&as->c->btree_interior_update_lock); - continue_at(&as->cl, async_split_nodes_written, system_freezable_wq); + continue_at(&as->cl, btree_interior_update_nodes_written, system_freezable_wq); } -static void async_split_updated_root(struct async_split *as, - struct btree *b) +static void btree_interior_update_updated_root(struct btree_interior_update *as, + struct btree *b) { struct btree_root *r = &as->c->btree_roots[b->btree_id]; /* - * XXX: if there's an outstanding async_split updating the root, we - * have to do the dance with the old one + * XXX: if there's an outstanding btree_interior_update updating the + * root, we have to do the dance with the old one */ - mutex_lock(&as->c->async_split_lock); + mutex_lock(&as->c->btree_interior_update_lock); if (r->as) { - BUG_ON(r->as->mode != ASYNC_SPLIT_UPDATING_ROOT); + BUG_ON(r->as->mode != BTREE_INTERIOR_UPDATING_ROOT); r->as->b = NULL; - r->as->mode = ASYNC_SPLIT_UPDATING_AS; + r->as->mode = BTREE_INTERIOR_UPDATING_AS; r->as->parent_as = as; closure_get(&as->cl); } - BUG_ON(as->mode != ASYNC_SPLIT_NO_UPDATE); - as->mode = ASYNC_SPLIT_UPDATING_ROOT; + BUG_ON(as->mode != BTREE_INTERIOR_NO_UPDATE); + as->mode = BTREE_INTERIOR_UPDATING_ROOT; as->b = b; r->as = as; - mutex_unlock(&as->c->async_split_lock); + mutex_unlock(&as->c->btree_interior_update_lock); - continue_at(&as->cl, async_split_nodes_written, system_freezable_wq); + continue_at(&as->cl, btree_interior_update_nodes_written, system_freezable_wq); } /* * @b is being split/rewritten: it may have pointers to not-yet-written btree - * nodes and thus outstanding async_splits - redirect @b's async_splits to point - * to this async_split: + * nodes and thus outstanding btree_interior_updates - redirect @b's + * btree_interior_updates to point to this btree_interior_update: */ -void bch_async_split_will_free_node(struct async_split *as, struct btree *b) +void bch_btree_interior_update_will_free_node(struct btree_interior_update *as, struct btree *b) { - mutex_lock(&as->c->async_split_lock); + mutex_lock(&as->c->btree_interior_update_lock); while (!list_empty(&b->write_blocked)) { - struct async_split *p = + struct btree_interior_update *p = list_first_entry(&b->write_blocked, - struct async_split, list); + struct btree_interior_update, + write_blocked_list); - BUG_ON(p->mode != ASYNC_SPLIT_UPDATING_BTREE); + BUG_ON(p->mode != BTREE_INTERIOR_UPDATING_NODE); - p->mode = ASYNC_SPLIT_UPDATING_AS; - list_del(&p->list); + p->mode = BTREE_INTERIOR_UPDATING_AS; + list_del(&p->write_blocked_list); p->b = NULL; p->parent_as = as; closure_get(&as->cl); } - mutex_unlock(&as->c->async_split_lock); + mutex_unlock(&as->c->btree_interior_update_lock); } static void btree_node_interior_verify(struct btree *b) @@ -1085,7 +1101,7 @@ static enum btree_insert_ret bch_btree_insert_keys_interior(struct btree *b, struct btree_iter *iter, struct keylist *insert_keys, - struct async_split *as, + struct btree_interior_update *as, struct btree_reserve *res) { struct btree_node_iter node_iter; @@ -1126,7 +1142,7 @@ bch_btree_insert_keys_interior(struct btree *b, bch_keylist_dequeue(insert_keys); } - async_split_updated_btree(as, b); + btree_interior_update_updated_btree(as, b); btree_node_unlock_write(b, iter); @@ -1253,7 +1269,7 @@ static void btree_split_insert_keys(struct btree_iter *iter, struct btree *b, static void btree_split(struct btree *b, struct btree_iter *iter, struct keylist *insert_keys, struct btree_reserve *reserve, - struct async_split *as) + struct btree_interior_update *as) { struct cache_set *c = iter->c; struct btree *parent = iter->nodes[b->level + 1]; @@ -1265,7 +1281,7 @@ static void btree_split(struct btree *b, struct btree_iter *iter, BUG_ON(!parent && (b != btree_node_root(b))); BUG_ON(!btree_node_intent_locked(iter, btree_node_root(b)->level)); - bch_async_split_will_free_node(as, b); + bch_btree_interior_update_will_free_node(as, b); n1 = btree_node_alloc_replacement(c, b, reserve); @@ -1412,7 +1428,7 @@ void bch_btree_insert_node(struct btree *b, struct btree_iter *iter, struct keylist *insert_keys, struct btree_reserve *reserve, - struct async_split *as) + struct btree_interior_update *as) { BUG_ON(!b->level); BUG_ON(!reserve || !as); @@ -1436,7 +1452,7 @@ static int bch_btree_split_leaf(struct btree_iter *iter, unsigned flags, struct cache_set *c = iter->c; struct btree *b = iter->nodes[0]; struct btree_reserve *reserve; - struct async_split *as; + struct btree_interior_update *as; int ret = 0; /* Hack, because gc and splitting nodes doesn't mix yet: */ @@ -1463,7 +1479,7 @@ static int bch_btree_split_leaf(struct btree_iter *iter, unsigned flags, goto out_get_locks; } - as = bch_async_split_alloc(b, iter); + as = bch_btree_interior_update_alloc(b, iter); btree_split(b, iter, NULL, reserve, as); bch_btree_reserve_put(c, reserve); @@ -1928,7 +1944,7 @@ int bch_btree_node_rewrite(struct btree_iter *iter, struct btree *b, struct cache_set *c = iter->c; struct btree *n, *parent = iter->nodes[b->level + 1]; struct btree_reserve *reserve; - struct async_split *as; + struct btree_interior_update *as; iter->locks_want = U8_MAX; if (!bch_btree_iter_upgrade(iter)) @@ -1940,9 +1956,9 @@ int bch_btree_node_rewrite(struct btree_iter *iter, struct btree *b, return PTR_ERR(reserve); } - as = bch_async_split_alloc(b, iter); + as = bch_btree_interior_update_alloc(b, iter); - bch_async_split_will_free_node(as, b); + bch_btree_interior_update_will_free_node(as, b); n = btree_node_alloc_replacement(c, b, reserve); six_unlock_write(&n->lock); diff --git a/drivers/md/bcache/btree_update.h b/drivers/md/bcache/btree_update.h index f5250dee951d..55b74b61c04b 100644 --- a/drivers/md/bcache/btree_update.h +++ b/drivers/md/bcache/btree_update.h @@ -14,13 +14,9 @@ struct btree; struct btree_reserve { struct disk_reservation disk_res; unsigned nr; - struct btree *b[]; + struct btree *b[BTREE_RESERVE_MAX]; }; -#define BTREE_RESERVE_SIZE \ - (sizeof(struct btree_reserve) + \ - sizeof(struct btree *) * BTREE_RESERVE_MAX) - void __bch_btree_calc_format(struct bkey_format_state *, struct btree *); bool bch_btree_node_format_fits(struct btree *, struct bkey_format *); @@ -32,9 +28,11 @@ bool bch_btree_node_format_fits(struct btree *, struct bkey_format *); * node(s) visible and frees the old hasn't completed yet) */ struct pending_btree_node_free { - struct list_head list; bool index_update_done; + __le64 seq; + enum btree_id btree_id; + unsigned level; __BKEY_PADDED(key, BKEY_BTREE_PTR_VAL_U64s_MAX); }; @@ -56,40 +54,49 @@ struct pending_btree_node_free { * until then, the old nodes are still reachable on disk. * */ -struct async_split { +struct btree_interior_update { struct closure cl; - struct cache_set *c; + struct list_head list; + + /* What kind of update are we doing? */ enum { - ASYNC_SPLIT_NO_UPDATE, - ASYNC_SPLIT_UPDATING_BTREE, - ASYNC_SPLIT_UPDATING_ROOT, - ASYNC_SPLIT_UPDATING_AS, + BTREE_INTERIOR_NO_UPDATE, + BTREE_INTERIOR_UPDATING_NODE, + BTREE_INTERIOR_UPDATING_ROOT, + BTREE_INTERIOR_UPDATING_AS, } mode; /* - * ASYNC_SPLIT_UPDATING_BTREE: - * @b - node we're blocking from being written - * @list - corresponds to @b->write_blocked + * BTREE_INTERIOR_UPDATING_NODE: + * The update that made the new nodes visible was a regular update to an + * existing interior node - @b. We can't write out the update to @b + * until the new nodes we created are finished writing, so we block @b + * from writing by putting this btree_interior update on the + * @b->write_blocked list with @write_blocked_list: */ struct btree *b; - struct list_head list; + struct list_head write_blocked_list; /* - * ASYNC_SPLIT_UPDATING_AS: btree node we updated was freed, so now - * we're now blocking another async_split - * @parent_as - async_split that's waiting on our nodes to finish + * BTREE_INTERIOR_UPDATING_AS: btree node we updated was freed, so now + * we're now blocking another btree_interior_update + * @parent_as - btree_interior_update that's waiting on our nodes to finish * writing, before it can make new nodes visible on disk - * @wait - list of child async_splits that are waiting on this - * async_split to make all the new nodes visible before they can free + * @wait - list of child btree_interior_updates that are waiting on this + * btree_interior_update to make all the new nodes visible before they can free * their old btree nodes */ - struct async_split *parent_as; + struct btree_interior_update *parent_as; struct closure_waitlist wait; struct journal_entry_pin journal; + /* + * Nodes being freed: + * Protected by c->btree_node_pending_free_lock + */ struct pending_btree_node_free pending[BTREE_MAX_DEPTH + GC_MERGE_NODES]; unsigned nr_pending; @@ -103,7 +110,11 @@ struct async_split { u64 inline_keys[BKEY_BTREE_PTR_U64s_MAX * 3]; }; -void bch_btree_node_free_start(struct cache_set *, struct async_split *, +#define for_each_pending_btree_node_free(c, as, p) \ + list_for_each_entry(as, &c->btree_interior_update_list, list) \ + for (p = as->pending; p < as->pending + as->nr_pending; p++) + +void bch_btree_node_free_start(struct cache_set *, struct btree_interior_update *, struct btree *); void bch_btree_node_free_inmem(struct btree_iter *, struct btree *); @@ -118,11 +129,11 @@ struct btree *__btree_node_alloc_replacement(struct cache_set *, struct btree *btree_node_alloc_replacement(struct cache_set *, struct btree *, struct btree_reserve *); -struct async_split *__bch_async_split_alloc(struct btree *[], unsigned, +struct btree_interior_update *__bch_btree_interior_update_alloc(struct btree *[], unsigned, struct btree_iter *); -struct async_split *bch_async_split_alloc(struct btree *, struct btree_iter *); +struct btree_interior_update *bch_btree_interior_update_alloc(struct btree *, struct btree_iter *); -void bch_async_split_will_free_node(struct async_split *, struct btree *); +void bch_btree_interior_update_will_free_node(struct btree_interior_update *, struct btree *); void bch_btree_set_root_initial(struct cache_set *, struct btree *, struct btree_reserve *); @@ -185,7 +196,7 @@ static inline bool bch_btree_node_insert_fits(struct cache_set *c, void bch_btree_insert_node(struct btree *, struct btree_iter *, struct keylist *, struct btree_reserve *, - struct async_split *as); + struct btree_interior_update *as); /* Normal update interface: */ diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 09451a155b35..27d984c1d37a 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -892,7 +892,7 @@ static void cache_set_free(struct cache_set *c) bioset_exit(&c->bio_read_split); bioset_exit(&c->bio_read); bioset_exit(&c->btree_read_bio); - mempool_exit(&c->btree_async_split_pool); + mempool_exit(&c->btree_interior_update_pool); mempool_exit(&c->btree_reserve_pool); mempool_exit(&c->fill_iter); mempool_exit(&c->search); @@ -1079,10 +1079,9 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, INIT_LIST_HEAD(&c->btree_cache_freeable); INIT_LIST_HEAD(&c->btree_cache_freed); - INIT_LIST_HEAD(&c->btree_node_pending_free); - mutex_init(&c->btree_node_pending_free_lock); + INIT_LIST_HEAD(&c->btree_interior_update_list); mutex_init(&c->btree_reserve_cache_lock); - mutex_init(&c->async_split_lock); + mutex_init(&c->btree_interior_update_lock); mutex_init(&c->bio_bounce_pages_lock); INIT_WORK(&c->bio_submit_work, bch_bio_submit_work); @@ -1138,9 +1137,9 @@ static struct cache_set *bch_cache_set_alloc(struct cache_sb *sb, percpu_ref_init(&c->writes, bch_writes_disabled, 0, GFP_KERNEL) || mempool_init_slab_pool(&c->search, 1, bch_search_cache) || mempool_init_kmalloc_pool(&c->btree_reserve_pool, 1, - BTREE_RESERVE_SIZE) || - mempool_init_kmalloc_pool(&c->btree_async_split_pool, 1, - sizeof(struct async_split)) || + sizeof(struct btree_reserve)) || + mempool_init_kmalloc_pool(&c->btree_interior_update_pool, 1, + sizeof(struct btree_interior_update)) || mempool_init_kmalloc_pool(&c->fill_iter, 1, iter_size) || bioset_init(&c->btree_read_bio, 1, offsetof(struct bbio, bio)) || bioset_init(&c->bio_read, 1, offsetof(struct bch_read_bio, bio)) || |