diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2015-06-04 21:33:11 -0700 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2016-10-07 12:34:23 -0800 |
commit | 44c8f531eed9e0971a909d7a12f785caaacbfc4a (patch) | |
tree | d41e36aa94b0d4ffde36c91761101ae712a38439 | |
parent | c0b78500dfcce11e01ef95da85f754c38e30405b (diff) |
bcache: Split out bch_btree_set_root_initial()
-rw-r--r-- | drivers/md/bcache/btree.c | 111 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 22 |
2 files changed, 68 insertions, 65 deletions
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 68305c52f88f..16649749dfbb 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -1662,39 +1662,8 @@ void bch_btree_node_free(struct cache_set *c, struct btree *b) false, true); } -/** - * bch_btree_set_root - update the root in memory and on disk - * - * To ensure forward progress, the current task must not be holding any - * btree node write locks. However, you must hold an intent lock on the - * old root. - * - * Frees the old root. - * - * Note: This allocates a journal entry but doesn't add any keys to - * it. All the btree roots are part of every journal write, so there - * is nothing new to be done. This just guarantees that there is a - * journal write. - */ -static void bch_btree_set_root(struct cache_set *c, struct btree *b) +static void __bch_btree_set_root(struct cache_set *c, struct btree *b) { - struct journal_res res; - struct btree *old; - - memset(&res, 0, sizeof(res)); - - trace_bcache_btree_set_root(b); - BUG_ON(!b->written); - - old = btree_node_root(b); - if (old) { - /* - * Ensure no one is using the old root while we switch to the - * new root: - */ - six_lock_write(&old->lock); - } - /* Root nodes cannot be reaped */ mutex_lock(&c->btree_cache_lock); list_del_init(&b->list); @@ -1716,28 +1685,66 @@ static void bch_btree_set_root(struct cache_set *c, struct btree *b) spin_unlock(&c->btree_root_lock); bch_recalc_btree_reserve(c); +} - if (old) { - struct closure cl; +/* + * Only for cache set bringup, when first reading the btree roots or allocating + * btree roots when initializing a new cache set: + */ +static void bch_btree_set_root_initial(struct cache_set *c, struct btree *b) +{ + BUG_ON(btree_node_root(b)); - closure_init_stack(&cl); + __bch_btree_set_root(c, b); +} - /* - * Unlock old root after new root is visible: - * - * The new root isn't persistent, but that's ok: we still have - * an intent lock on the new root, and any updates that would - * depend on the new root would have to update the new root. - */ - six_unlock_write(&old->lock); +/** + * bch_btree_set_root - update the root in memory and on disk + * + * To ensure forward progress, the current task must not be holding any + * btree node write locks. However, you must hold an intent lock on the + * old root. + * + * Note: This allocates a journal entry but doesn't add any keys to + * it. All the btree roots are part of every journal write, so there + * is nothing new to be done. This just guarantees that there is a + * journal write. + */ +static void bch_btree_set_root(struct cache_set *c, struct btree *b) +{ + struct btree *old; + struct closure cl; - /* - * Ensure new btree root is persistent (reachable via the - * journal) before returning and the caller unlocking it: - */ - bch_journal_meta(&c->journal, &cl); - closure_sync(&cl); - } + closure_init_stack(&cl); + + trace_bcache_btree_set_root(b); + BUG_ON(!b->written); + + old = btree_node_root(b); + + /* + * Ensure no one is using the old root while we switch to the + * new root: + */ + six_lock_write(&old->lock); + + __bch_btree_set_root(c, b); + + /* + * Unlock old root after new root is visible: + * + * The new root isn't persistent, but that's ok: we still have + * an intent lock on the new root, and any updates that would + * depend on the new root would have to update the new root. + */ + six_unlock_write(&old->lock); + + /* + * Ensure new btree root is persistent (reachable via the + * journal) before returning and the caller unlocking it: + */ + bch_journal_meta(&c->journal, &cl); + closure_sync(&cl); } static struct btree *__bch_btree_node_alloc(struct cache_set *c, @@ -1991,7 +1998,7 @@ int bch_btree_root_alloc(struct cache_set *c, enum btree_id id, bch_btree_node_write(b, writes, NULL); - bch_btree_set_root(c, b); + bch_btree_set_root_initial(c, b); btree_open_bucket_put(c, b); six_unlock_intent(&b->lock); @@ -2022,7 +2029,7 @@ int bch_btree_root_read(struct cache_set *c, enum btree_id id, return -EIO; } - bch_btree_set_root(c, b); + bch_btree_set_root_initial(c, b); six_unlock_intent(&b->lock); return 0; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index c274503df127..44c15a371f78 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1261,6 +1261,7 @@ static const char *run_cache_set(struct cache_set *c) * set up the journal.pin FIFO and journal.cur pointer: */ bch_journal_start(c); + bch_journal_set_replay_done(&c->journal); for_each_cache(ca, c, i) if (CACHE_STATE(&ca->mi) == CACHE_ACTIVE && @@ -1274,16 +1275,7 @@ static const char *run_cache_set(struct cache_set *c) if (bch_btree_root_alloc(c, id, &cl)) goto err; - /* - * We don't want to write the first journal entry until - * everything is set up - fortunately journal entries won't be - * written until the SET_CACHE_SYNC() here: - */ - SET_CACHE_SYNC(&c->sb, true); - bch_journal_set_replay_done(&c->journal); - - /* XXX: necessary? */ - bch_journal_meta(&c->journal, &cl); + /* Wait for new btree roots to be written: */ closure_sync(&cl); bkey_inode_init(&inode.k_i); @@ -1294,15 +1286,19 @@ static const char *run_cache_set(struct cache_set *c) err = "error creating root directory"; if (bch_btree_insert(c, BTREE_ID_INODES, &keylist_single(&inode.k_i), - NULL, &cl, NULL, 0)) + NULL, NULL, NULL, 0)) goto err; + + bch_journal_meta(&c->journal, &cl); + closure_sync(&cl); + + /* Mark cache set as initialized: */ + SET_CACHE_SYNC(&c->sb, true); } bch_prio_timer_start(c, READ); bch_prio_timer_start(c, WRITE); - closure_sync(&cl); - if (c->opts.read_only) { bch_cache_set_read_only(c); } else { |