bcachefs: bch2_readdir() now calls str_hash_check_key()
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 28 May 2025 20:34:42 +0000 (16:34 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 1 Jun 2025 02:03:17 +0000 (22:03 -0400)
More self healing code: readdir will now notice if there are dirents
hashed incorrectly, and it'll repair them if errors=fix_safe.

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

index d198001838f33a149b7c755858f024b9be71e1ef..37d7cf69ae1ddb22253742cbcee3fcf5ae84625f 100644 (file)
@@ -692,7 +692,9 @@ static int bch2_dir_emit(struct dir_context *ctx, struct bkey_s_c_dirent d, subv
        return !ret;
 }
 
-int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
+int bch2_readdir(struct bch_fs *c, subvol_inum inum,
+                struct bch_hash_info *hash_info,
+                struct dir_context *ctx)
 {
        struct bkey_buf sk;
        bch2_bkey_buf_init(&sk);
@@ -710,7 +712,10 @@ int bch2_readdir(struct bch_fs *c, subvol_inum inum, struct dir_context *ctx)
                        struct bkey_s_c_dirent dirent = bkey_i_to_s_c_dirent(sk.k);
 
                        subvol_inum target;
-                       int ret2 = bch2_dirent_read_target(trans, inum, dirent, &target);
+
+                       int ret2 = bch2_str_hash_check_key(trans, NULL, &bch2_dirent_hash_desc,
+                                                          hash_info, &iter, k) ?:
+                               bch2_dirent_read_target(trans, inum, dirent, &target);
                        if (ret2 > 0)
                                continue;
 
index d3e7ae669575a6d3cf7e13657b4b1564f4e78cf6..1f600dedafe1d3bfa06b97ad16605d6e1beb7a8e 100644 (file)
@@ -95,7 +95,7 @@ u64 bch2_dirent_lookup(struct bch_fs *, subvol_inum,
 
 int bch2_empty_dir_snapshot(struct btree_trans *, u64, u32, u32);
 int bch2_empty_dir_trans(struct btree_trans *, subvol_inum);
-int bch2_readdir(struct bch_fs *, subvol_inum, struct dir_context *);
+int bch2_readdir(struct bch_fs *, subvol_inum, struct bch_hash_info *, struct dir_context *);
 
 int bch2_fsck_remove_dirent(struct btree_trans *, struct bpos);
 
index adae43223bce3dd6a3832c0d33ba3c7f4fc0fe2b..f52c7db16dec6187864a74a81fc120bcf0825748 100644 (file)
@@ -1573,11 +1573,12 @@ static int bch2_vfs_readdir(struct file *file, struct dir_context *ctx)
 {
        struct bch_inode_info *inode = file_bch_inode(file);
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
+       struct bch_hash_info hash = bch2_hash_info_init(c, &inode->ei_inode);
 
        if (!dir_emit_dots(file, ctx))
                return 0;
 
-       int ret = bch2_readdir(c, inode_inum(inode), ctx);
+       int ret = bch2_readdir(c, inode_inum(inode), &hash, ctx);
 
        bch_err_fn(c, ret);
        return bch2_err_class(ret);