Commit 2b3e79fe authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Don't use bch2_btree_node_lock_write_nofail() in btree split path

It turns out - btree splits happen with the rest of the transaction
still locked, to avoid unnecessary restarts, which means using nofail
doesn't work here - we can deadlock.

Fortunately, we now have the ability to return errors here.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 1189bdda
...@@ -1280,23 +1280,29 @@ static void bch2_btree_set_root_inmem(struct bch_fs *c, struct btree *b) ...@@ -1280,23 +1280,29 @@ static void bch2_btree_set_root_inmem(struct bch_fs *c, struct btree *b)
bch2_recalc_btree_reserve(c); bch2_recalc_btree_reserve(c);
} }
static void bch2_btree_set_root(struct btree_update *as, static int bch2_btree_set_root(struct btree_update *as,
struct btree_trans *trans, struct btree_trans *trans,
struct btree_path *path, struct btree_path *path,
struct btree *b) struct btree *b,
bool nofail)
{ {
struct bch_fs *c = as->c; struct bch_fs *c = as->c;
struct btree *old;
trace_and_count(c, btree_node_set_root, trans, b); trace_and_count(c, btree_node_set_root, trans, b);
old = btree_node_root(c, b); struct btree *old = btree_node_root(c, b);
/* /*
* Ensure no one is using the old root while we switch to the * Ensure no one is using the old root while we switch to the
* new root: * new root:
*/ */
if (nofail) {
bch2_btree_node_lock_write_nofail(trans, path, &old->c); bch2_btree_node_lock_write_nofail(trans, path, &old->c);
} else {
int ret = bch2_btree_node_lock_write(trans, path, &old->c);
if (ret)
return ret;
}
bch2_btree_set_root_inmem(c, b); bch2_btree_set_root_inmem(c, b);
...@@ -1310,6 +1316,7 @@ static void bch2_btree_set_root(struct btree_update *as, ...@@ -1310,6 +1316,7 @@ static void bch2_btree_set_root(struct btree_update *as,
* depend on the new root would have to update the new root. * depend on the new root would have to update the new root.
*/ */
bch2_btree_node_unlock_write(trans, path, old); bch2_btree_node_unlock_write(trans, path, old);
return 0;
} }
/* Interior node updates: */ /* Interior node updates: */
...@@ -1652,15 +1659,16 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans, ...@@ -1652,15 +1659,16 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
if (parent) { if (parent) {
/* Split a non root node */ /* Split a non root node */
ret = bch2_btree_insert_node(as, trans, path, parent, &as->parent_keys); ret = bch2_btree_insert_node(as, trans, path, parent, &as->parent_keys);
if (ret)
goto err;
} else if (n3) { } else if (n3) {
bch2_btree_set_root(as, trans, trans->paths + path, n3); ret = bch2_btree_set_root(as, trans, trans->paths + path, n3, false);
} else { } else {
/* Root filled up but didn't need to be split */ /* Root filled up but didn't need to be split */
bch2_btree_set_root(as, trans, trans->paths + path, n1); ret = bch2_btree_set_root(as, trans, trans->paths + path, n1, false);
} }
if (ret)
goto err;
if (n3) { if (n3) {
bch2_btree_update_get_open_buckets(as, n3); bch2_btree_update_get_open_buckets(as, n3);
bch2_btree_node_write(c, n3, SIX_LOCK_intent, 0); bch2_btree_node_write(c, n3, SIX_LOCK_intent, 0);
...@@ -1863,7 +1871,9 @@ static void __btree_increase_depth(struct btree_update *as, struct btree_trans * ...@@ -1863,7 +1871,9 @@ static void __btree_increase_depth(struct btree_update *as, struct btree_trans *
bch2_keylist_add(&as->parent_keys, &b->key); bch2_keylist_add(&as->parent_keys, &b->key);
btree_split_insert_keys(as, trans, path_idx, n, &as->parent_keys); btree_split_insert_keys(as, trans, path_idx, n, &as->parent_keys);
bch2_btree_set_root(as, trans, path, n); int ret = bch2_btree_set_root(as, trans, path, n, true);
BUG_ON(ret);
bch2_btree_update_get_open_buckets(as, n); bch2_btree_update_get_open_buckets(as, n);
bch2_btree_node_write(c, n, SIX_LOCK_intent, 0); bch2_btree_node_write(c, n, SIX_LOCK_intent, 0);
bch2_trans_node_add(trans, path, n); bch2_trans_node_add(trans, path, n);
...@@ -2106,12 +2116,13 @@ int bch2_btree_node_rewrite(struct btree_trans *trans, ...@@ -2106,12 +2116,13 @@ int bch2_btree_node_rewrite(struct btree_trans *trans,
if (parent) { if (parent) {
bch2_keylist_add(&as->parent_keys, &n->key); bch2_keylist_add(&as->parent_keys, &n->key);
ret = bch2_btree_insert_node(as, trans, iter->path, parent, &as->parent_keys); ret = bch2_btree_insert_node(as, trans, iter->path, parent, &as->parent_keys);
if (ret)
goto err;
} else { } else {
bch2_btree_set_root(as, trans, btree_iter_path(trans, iter), n); ret = bch2_btree_set_root(as, trans, btree_iter_path(trans, iter), n, false);
} }
if (ret)
goto err;
bch2_btree_update_get_open_buckets(as, n); bch2_btree_update_get_open_buckets(as, n);
bch2_btree_node_write(c, n, SIX_LOCK_intent, 0); bch2_btree_node_write(c, n, SIX_LOCK_intent, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment