bcachefs: Re-enable hash_redo_key()
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 4 Sep 2022 18:10:12 +0000 (14:10 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:40 +0000 (17:09 -0400)
When subvolumes & snapshots were rolled out, hash_redo_key() was
disabled due to some new complications - namely, bch2_hash_set() works
at the subvolume level, and fsck does not run in a defined subvolume,
instead working at the snapshot ID level.

This patch splits out bch2_hash_set_snapshot() from bch2_hash_set(), and
makes one small tweak for fsck:

 - Normally, bch2_hash_set() (and other dirent code) needs to know what
   subvolume we're in, because dirents that point to other subvolumes
   should only be visible in the subvolume they were created in, not
   other snapshots. We can't check that in fsck, so we just assume that
   all dirents are visible.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fsck.c
fs/bcachefs/str_hash.h

index 9f768d774ba6d6ab26673adcd414a019ce9e3ed3..12f2ef4417cb31255a405d5517ee727922ff5623 100644 (file)
@@ -772,9 +772,6 @@ static int hash_redo_key(struct btree_trans *trans,
                         struct bch_hash_info *hash_info,
                         struct btree_iter *k_iter, struct bkey_s_c k)
 {
-       bch_err(trans->c, "hash_redo_key() not implemented yet");
-       return -EINVAL;
-#if 0
        struct bkey_i *delete;
        struct bkey_i *tmp;
 
@@ -792,8 +789,14 @@ static int hash_redo_key(struct btree_trans *trans,
        delete->k.p = k_iter->pos;
        return  bch2_btree_iter_traverse(k_iter) ?:
                bch2_trans_update(trans, k_iter, delete, 0) ?:
-               bch2_hash_set(trans, desc, hash_info, k_iter->pos.inode, tmp, 0);
-#endif
+               bch2_hash_set_snapshot(trans, desc, hash_info,
+                                      (subvol_inum) { 0, k.k->p.inode },
+                                      k.k->p.snapshot, tmp,
+                                      BCH_HASH_SET_MUST_CREATE,
+                                      BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE) ?:
+               bch2_trans_commit(trans, NULL, NULL,
+                                 BTREE_INSERT_NOFAIL|
+                                 BTREE_INSERT_LAZY_RW);
 }
 
 static int hash_check_key(struct btree_trans *trans,
index 591bbb9f8beb544de1369204ffc666018ef40740..560983df13f09645b7739aed855a65bb7f5a3e96 100644 (file)
@@ -144,7 +144,9 @@ struct bch_hash_desc {
 static inline bool is_visible_key(struct bch_hash_desc desc, subvol_inum inum, struct bkey_s_c k)
 {
        return k.k->type == desc.key_type &&
-               (!desc.is_visible || desc.is_visible(inum, k));
+               (!desc.is_visible ||
+                !inum.inum ||
+                desc.is_visible(inum, k));
 }
 
 static __always_inline int
@@ -239,27 +241,24 @@ int bch2_hash_needs_whiteout(struct btree_trans *trans,
 }
 
 static __always_inline
-int bch2_hash_set(struct btree_trans *trans,
-                 const struct bch_hash_desc desc,
-                 const struct bch_hash_info *info,
-                 subvol_inum inum,
-                 struct bkey_i *insert, int flags)
+int bch2_hash_set_snapshot(struct btree_trans *trans,
+                          const struct bch_hash_desc desc,
+                          const struct bch_hash_info *info,
+                          subvol_inum inum, u32 snapshot,
+                          struct bkey_i *insert,
+                          int flags,
+                          int update_flags)
 {
        struct btree_iter iter, slot = { NULL };
        struct bkey_s_c k;
        bool found = false;
-       u32 snapshot;
        int ret;
 
-       ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
-       if (ret)
-               return ret;
-
        for_each_btree_key_upto_norestart(trans, iter, desc.btree_id,
-                          SPOS(inum.inum,
+                          SPOS(insert->k.p.inode,
                                desc.hash_bkey(info, bkey_i_to_s_c(insert)),
                                snapshot),
-                          POS(inum.inum, U64_MAX),
+                          POS(insert->k.p.inode, U64_MAX),
                           BTREE_ITER_SLOTS|BTREE_ITER_INTENT, k, ret) {
                if (is_visible_key(desc, inum, k)) {
                        if (!desc.cmp_bkey(k, bkey_i_to_s_c(insert)))
@@ -303,6 +302,26 @@ not_found:
        goto out;
 }
 
+static __always_inline
+int bch2_hash_set(struct btree_trans *trans,
+                 const struct bch_hash_desc desc,
+                 const struct bch_hash_info *info,
+                 subvol_inum inum,
+                 struct bkey_i *insert, int flags)
+{
+       u32 snapshot;
+       int ret;
+
+       ret = bch2_subvolume_get_snapshot(trans, inum.subvol, &snapshot);
+       if (ret)
+               return ret;
+
+       insert->k.p.inode = inum.inum;
+
+       return bch2_hash_set_snapshot(trans, desc, info, inum,
+                                     snapshot, insert, flags, 0);
+}
+
 static __always_inline
 int bch2_hash_delete_at(struct btree_trans *trans,
                        const struct bch_hash_desc desc,