summaryrefslogtreecommitdiff
path: root/libbcachefs/btree_update.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/btree_update.c')
-rw-r--r--libbcachefs/btree_update.c60
1 files changed, 26 insertions, 34 deletions
diff --git a/libbcachefs/btree_update.c b/libbcachefs/btree_update.c
index 51dff1b7..cdbc0de4 100644
--- a/libbcachefs/btree_update.c
+++ b/libbcachefs/btree_update.c
@@ -614,7 +614,7 @@ int bch2_btree_root_alloc(struct bch_fs *c, enum btree_id id,
b = __btree_root_alloc(c, 0, id, reserve);
- bch2_btree_node_write(c, b, writes, SIX_LOCK_intent, -1);
+ bch2_btree_node_write(c, b, writes, SIX_LOCK_intent);
bch2_btree_set_root_initial(c, b, reserve);
bch2_btree_open_bucket_put(c, b);
@@ -750,39 +750,27 @@ overwrite:
}
static void __btree_node_flush(struct journal *j, struct journal_entry_pin *pin,
- unsigned i)
+ unsigned i, u64 seq)
{
struct bch_fs *c = container_of(j, struct bch_fs, journal);
struct btree_write *w = container_of(pin, struct btree_write, journal);
struct btree *b = container_of(w, struct btree, writes[i]);
six_lock_read(&b->lock);
- /*
- * Reusing a btree node can race with the journal reclaim code calling
- * the journal pin flush fn, and there's no good fix for this: we don't
- * really want journal_pin_drop() to block until the flush fn is no
- * longer running, because journal_pin_drop() is called from the btree
- * node write endio function, and we can't wait on the flush fn to
- * finish running in mca_reap() - where we make reused btree nodes ready
- * to use again - because there, we're holding the lock this function
- * needs - deadlock.
- *
- * So, the b->level check is a hack so we don't try to write nodes we
- * shouldn't:
- */
- if (!b->level)
- bch2_btree_node_write(c, b, NULL, SIX_LOCK_read, i);
+ bch2_btree_node_write_dirty(c, b, NULL,
+ (btree_current_write(b) == w &&
+ w->journal.pin_list == journal_seq_pin(j, seq)));
six_unlock_read(&b->lock);
}
-static void btree_node_flush0(struct journal *j, struct journal_entry_pin *pin)
+static void btree_node_flush0(struct journal *j, struct journal_entry_pin *pin, u64 seq)
{
- return __btree_node_flush(j, pin, 0);
+ return __btree_node_flush(j, pin, 0, seq);
}
-static void btree_node_flush1(struct journal *j, struct journal_entry_pin *pin)
+static void btree_node_flush1(struct journal *j, struct journal_entry_pin *pin, u64 seq)
{
- return __btree_node_flush(j, pin, 1);
+ return __btree_node_flush(j, pin, 1, seq);
}
void bch2_btree_journal_key(struct btree_insert *trans,
@@ -799,10 +787,11 @@ void bch2_btree_journal_key(struct btree_insert *trans,
test_bit(JOURNAL_REPLAY_DONE, &j->flags));
if (!journal_pin_active(&w->journal))
- bch2_journal_pin_add(j, &w->journal,
- btree_node_write_idx(b) == 0
- ? btree_node_flush0
- : btree_node_flush1);
+ bch2_journal_pin_add(j, &trans->journal_res,
+ &w->journal,
+ btree_node_write_idx(b) == 0
+ ? btree_node_flush0
+ : btree_node_flush1);
if (trans->journal_res.ref) {
u64 seq = trans->journal_res.seq;
@@ -972,9 +961,9 @@ retry:
closure_wait(&btree_current_write(b)->wait, cl);
list_del(&as->write_blocked_list);
+ mutex_unlock(&c->btree_interior_update_lock);
- if (list_empty(&b->write_blocked))
- bch2_btree_node_write(c, b, NULL, SIX_LOCK_read, -1);
+ bch2_btree_node_write_dirty(c, b, NULL, true);
six_unlock_read(&b->lock);
break;
@@ -991,6 +980,7 @@ retry:
* and then we have to wait on that btree_interior_update to finish:
*/
closure_wait(&as->parent_as->wait, cl);
+ mutex_unlock(&c->btree_interior_update_lock);
break;
case BTREE_INTERIOR_UPDATING_ROOT:
@@ -1017,8 +1007,9 @@ retry:
* can reuse the old nodes it'll have to do a journal commit:
*/
six_unlock_read(&b->lock);
+ mutex_unlock(&c->btree_interior_update_lock);
+ break;
}
- mutex_unlock(&c->btree_interior_update_lock);
continue_at(cl, btree_interior_update_nodes_reachable, system_wq);
}
@@ -1083,7 +1074,8 @@ static void btree_interior_update_updated_root(struct bch_fs *c,
system_freezable_wq);
}
-static void interior_update_flush(struct journal *j, struct journal_entry_pin *pin)
+static void interior_update_flush(struct journal *j,
+ struct journal_entry_pin *pin, u64 seq)
{
struct btree_interior_update *as =
container_of(pin, struct btree_interior_update, journal);
@@ -1441,7 +1433,7 @@ static void btree_split(struct btree *b, struct btree_iter *iter,
six_unlock_write(&n2->lock);
six_unlock_write(&n1->lock);
- bch2_btree_node_write(c, n2, &as->cl, SIX_LOCK_intent, -1);
+ bch2_btree_node_write(c, n2, &as->cl, SIX_LOCK_intent);
/*
* Note that on recursive parent_keys == insert_keys, so we
@@ -1461,7 +1453,7 @@ static void btree_split(struct btree *b, struct btree_iter *iter,
btree_split_insert_keys(iter, n3, &as->parent_keys,
reserve);
- bch2_btree_node_write(c, n3, &as->cl, SIX_LOCK_intent, -1);
+ bch2_btree_node_write(c, n3, &as->cl, SIX_LOCK_intent);
}
} else {
trace_btree_node_compact(c, b, b->nr.live_u64s);
@@ -1472,7 +1464,7 @@ static void btree_split(struct btree *b, struct btree_iter *iter,
bch2_keylist_add(&as->parent_keys, &n1->key);
}
- bch2_btree_node_write(c, n1, &as->cl, SIX_LOCK_intent, -1);
+ bch2_btree_node_write(c, n1, &as->cl, SIX_LOCK_intent);
/* New nodes all written, now make them visible: */
@@ -1773,7 +1765,7 @@ retry:
bch2_keylist_add(&as->parent_keys, &delete);
bch2_keylist_add(&as->parent_keys, &n->key);
- bch2_btree_node_write(c, n, &as->cl, SIX_LOCK_intent, -1);
+ bch2_btree_node_write(c, n, &as->cl, SIX_LOCK_intent);
bch2_btree_insert_node(parent, iter, &as->parent_keys, reserve, as);
@@ -2323,7 +2315,7 @@ int bch2_btree_node_rewrite(struct btree_iter *iter, struct btree *b,
trace_btree_gc_rewrite_node(c, b);
- bch2_btree_node_write(c, n, &as->cl, SIX_LOCK_intent, -1);
+ bch2_btree_node_write(c, n, &as->cl, SIX_LOCK_intent);
if (parent) {
bch2_btree_insert_node(parent, iter,