mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 13:43:21 -04:00
bcachefs: btree_node_(rewrite|update_key) cleanup
Factor out get_iter_to_node() and use it for btree_node_rewrite_get_iter(), to be used for fixing btree node write error behaviour. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
@@ -2126,6 +2126,31 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int get_iter_to_node(struct btree_trans *trans, struct btree_iter *iter,
|
||||
struct btree *b)
|
||||
{
|
||||
bch2_trans_node_iter_init(trans, iter, b->c.btree_id, b->key.k.p,
|
||||
BTREE_MAX_DEPTH, b->c.level,
|
||||
BTREE_ITER_intent);
|
||||
int ret = bch2_btree_iter_traverse(iter);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
/* has node been freed? */
|
||||
if (btree_iter_path(trans, iter)->l[b->c.level].b != b) {
|
||||
/* node has been freed: */
|
||||
BUG_ON(!btree_node_dying(b));
|
||||
ret = -BCH_ERR_btree_node_dying;
|
||||
goto err;
|
||||
}
|
||||
|
||||
BUG_ON(!btree_node_hashed(b));
|
||||
return 0;
|
||||
err:
|
||||
bch2_trans_iter_exit(trans, iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_btree_node_rewrite(struct btree_trans *trans,
|
||||
struct btree_iter *iter,
|
||||
struct btree *b,
|
||||
@@ -2191,6 +2216,41 @@ int bch2_btree_node_rewrite(struct btree_trans *trans,
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int bch2_btree_node_rewrite_key(struct btree_trans *trans,
|
||||
enum btree_id btree, unsigned level,
|
||||
struct bkey_i *k, unsigned flags)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
bch2_trans_node_iter_init(trans, &iter,
|
||||
btree, k->k.p,
|
||||
BTREE_MAX_DEPTH, level, 0);
|
||||
struct btree *b = bch2_btree_iter_peek_node(&iter);
|
||||
int ret = PTR_ERR_OR_ZERO(b);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
bool found = b && btree_ptr_hash_val(&b->key) == btree_ptr_hash_val(k);
|
||||
ret = found
|
||||
? bch2_btree_node_rewrite(trans, &iter, b, flags)
|
||||
: -ENOENT;
|
||||
out:
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bch2_btree_node_rewrite_key_get_iter(struct btree_trans *trans,
|
||||
struct btree *b, unsigned flags)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
int ret = get_iter_to_node(trans, &iter, b);
|
||||
if (ret)
|
||||
return ret == -BCH_ERR_btree_node_dying ? 0 : ret;
|
||||
|
||||
ret = bch2_btree_node_rewrite(trans, &iter, b, flags);
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct async_btree_rewrite {
|
||||
struct bch_fs *c;
|
||||
struct work_struct work;
|
||||
@@ -2200,57 +2260,14 @@ struct async_btree_rewrite {
|
||||
struct bkey_buf key;
|
||||
};
|
||||
|
||||
static int async_btree_node_rewrite_trans(struct btree_trans *trans,
|
||||
struct async_btree_rewrite *a)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
bch2_trans_node_iter_init(trans, &iter,
|
||||
a->btree_id, a->key.k->k.p,
|
||||
BTREE_MAX_DEPTH, a->level, 0);
|
||||
struct btree *b = bch2_btree_iter_peek_node(&iter);
|
||||
int ret = PTR_ERR_OR_ZERO(b);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
bool found = b && btree_ptr_hash_val(&b->key) == btree_ptr_hash_val(a->key.k);
|
||||
ret = found
|
||||
? bch2_btree_node_rewrite(trans, &iter, b, 0)
|
||||
: -ENOENT;
|
||||
|
||||
#if 0
|
||||
/* Tracepoint... */
|
||||
if (!ret || ret == -ENOENT) {
|
||||
struct bch_fs *c = trans->c;
|
||||
struct printbuf buf = PRINTBUF;
|
||||
|
||||
if (!ret) {
|
||||
prt_printf(&buf, "rewrite node:\n ");
|
||||
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(a->key.k));
|
||||
} else {
|
||||
prt_printf(&buf, "node to rewrite not found:\n want: ");
|
||||
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(a->key.k));
|
||||
prt_printf(&buf, "\n got: ");
|
||||
if (b)
|
||||
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
|
||||
else
|
||||
prt_str(&buf, "(null)");
|
||||
}
|
||||
bch_info(c, "%s", buf.buf);
|
||||
printbuf_exit(&buf);
|
||||
}
|
||||
#endif
|
||||
out:
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void async_btree_node_rewrite_work(struct work_struct *work)
|
||||
{
|
||||
struct async_btree_rewrite *a =
|
||||
container_of(work, struct async_btree_rewrite, work);
|
||||
struct bch_fs *c = a->c;
|
||||
|
||||
int ret = bch2_trans_do(c, async_btree_node_rewrite_trans(trans, a));
|
||||
int ret = bch2_trans_do(c, bch2_btree_node_rewrite_key(trans,
|
||||
a->btree_id, a->level, a->key.k, 0));
|
||||
if (ret != -ENOENT)
|
||||
bch_err_fn_ratelimited(c, ret);
|
||||
|
||||
@@ -2494,30 +2511,15 @@ int bch2_btree_node_update_key_get_iter(struct btree_trans *trans,
|
||||
unsigned commit_flags, bool skip_triggers)
|
||||
{
|
||||
struct btree_iter iter;
|
||||
int ret;
|
||||
|
||||
bch2_trans_node_iter_init(trans, &iter, b->c.btree_id, b->key.k.p,
|
||||
BTREE_MAX_DEPTH, b->c.level,
|
||||
BTREE_ITER_intent);
|
||||
ret = bch2_btree_iter_traverse(&iter);
|
||||
int ret = get_iter_to_node(trans, &iter, b);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* has node been freed? */
|
||||
if (btree_iter_path(trans, &iter)->l[b->c.level].b != b) {
|
||||
/* node has been freed: */
|
||||
BUG_ON(!btree_node_dying(b));
|
||||
goto out;
|
||||
}
|
||||
|
||||
BUG_ON(!btree_node_hashed(b));
|
||||
return ret == -BCH_ERR_btree_node_dying ? 0 : ret;
|
||||
|
||||
bch2_bkey_drop_ptrs(bkey_i_to_s(new_key), ptr,
|
||||
!bch2_bkey_has_device(bkey_i_to_s(&b->key), ptr->dev));
|
||||
|
||||
ret = bch2_btree_node_update_key(trans, &iter, b, new_key,
|
||||
commit_flags, skip_triggers);
|
||||
out:
|
||||
bch2_trans_iter_exit(trans, &iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -169,6 +169,9 @@ static inline int bch2_foreground_maybe_merge(struct btree_trans *trans,
|
||||
|
||||
int bch2_btree_node_rewrite(struct btree_trans *, struct btree_iter *,
|
||||
struct btree *, unsigned);
|
||||
int bch2_btree_node_rewrite_key_get_iter(struct btree_trans *,
|
||||
struct btree *, unsigned);
|
||||
|
||||
void bch2_btree_node_rewrite_async(struct bch_fs *, struct btree *);
|
||||
int bch2_btree_node_update_key(struct btree_trans *, struct btree_iter *,
|
||||
struct btree *, struct bkey_i *,
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
x(ENOENT, ENOENT_dev_idx_not_found) \
|
||||
x(ENOENT, ENOENT_inode_no_backpointer) \
|
||||
x(ENOENT, ENOENT_no_snapshot_tree_subvol) \
|
||||
x(ENOENT, btree_node_dying) \
|
||||
x(ENOTEMPTY, ENOTEMPTY_dir_not_empty) \
|
||||
x(ENOTEMPTY, ENOTEMPTY_subvol_not_empty) \
|
||||
x(EEXIST, EEXIST_str_hash_set) \
|
||||
|
||||
Reference in New Issue
Block a user