summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2015-06-04 21:33:11 -0700
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:34:23 -0800
commit44c8f531eed9e0971a909d7a12f785caaacbfc4a (patch)
treed41e36aa94b0d4ffde36c91761101ae712a38439
parentc0b78500dfcce11e01ef95da85f754c38e30405b (diff)
bcache: Split out bch_btree_set_root_initial()
-rw-r--r--drivers/md/bcache/btree.c111
-rw-r--r--drivers/md/bcache/super.c22
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 {