bcachefs: btree_node_(rewrite|update_key) cleanup
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 25 Feb 2025 20:04:58 +0000 (15:04 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 15 Mar 2025 01:02:10 +0000 (21:02 -0400)
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>
fs/bcachefs/btree_update_interior.c
fs/bcachefs/btree_update_interior.h
fs/bcachefs/errcode.h

index e4e7c804625e0ee115f4a104d2e7cbd0e797c79f..05aa9e32adf4b3bd43b73f90c7965c9768313539 100644 (file)
@@ -2126,6 +2126,31 @@ err_free_update:
        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,66 +2216,58 @@ err:
        goto out;
 }
 
-struct async_btree_rewrite {
-       struct bch_fs           *c;
-       struct work_struct      work;
-       struct list_head        list;
-       enum btree_id           btree_id;
-       unsigned                level;
-       struct bkey_buf         key;
-};
-
-static int async_btree_node_rewrite_trans(struct btree_trans *trans,
-                                         struct async_btree_rewrite *a)
+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,
-                                 a->btree_id, a->key.k->k.p,
-                                 BTREE_MAX_DEPTH, a->level, 0);
+                                 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(a->key.k);
+       bool found = b && btree_ptr_hash_val(&b->key) == btree_ptr_hash_val(k);
        ret = found
-               ? bch2_btree_node_rewrite(trans, &iter, b, 0)
+               ? bch2_btree_node_rewrite(trans, &iter, b, flags)
                : -ENOENT;
+out:
+       bch2_trans_iter_exit(trans, &iter);
+       return ret;
+}
 
-#if 0
-       /* Tracepoint... */
-       if (!ret || ret == -ENOENT) {
-               struct bch_fs *c = trans->c;
-               struct printbuf buf = PRINTBUF;
+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;
 
-               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:
+       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;
+       struct list_head        list;
+       enum btree_id           btree_id;
+       unsigned                level;
+       struct bkey_buf         key;
+};
+
 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;
 }
index 26d646e1275c070e86c5e3fd24eb3bdfa5ae0086..9261a9a341fb3b9e328161e85f8c7024ff781b90 100644 (file)
@@ -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 *,
index 4590cd0c7c90587a9c185acddf79ed3f16fddc34..712877036612be4b16df765705b1a6f8e47d3913 100644 (file)
        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)                    \