bcachefs: check inode->bi_parent_subvol against dirent
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 7 Feb 2024 05:23:25 +0000 (00:23 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 14 Mar 2024 01:22:24 +0000 (21:22 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fsck.c
fs/bcachefs/sb-errors_types.h

index 9069701028a9645001b75ba8b20673bbebd4bfe9..fafce6bffff234967ebd0b1f34934e885f05601c 100644 (file)
@@ -1012,7 +1012,7 @@ static int check_inode(struct btree_trans *trans,
        if (fsck_err_on(u.bi_parent_subvol &&
                        (u.bi_subvol == 0 ||
                         u.bi_subvol == BCACHEFS_ROOT_SUBVOL),
-                       c, inode_bi_parent_subvol_nonzero,
+                       c, inode_bi_parent_nonzero,
                        "inode %llu:%u has subvol %u but nonzero parent subvol %u",
                        u.bi_inum, k.k->p.snapshot, u.bi_subvol, u.bi_parent_subvol)) {
                u.bi_parent_subvol = 0;
@@ -1685,27 +1685,6 @@ static int check_dirent_target(struct btree_trans *trans,
 
                d = dirent_i_to_s_c(n);
        }
-
-       if (fsck_err_on(d.v->d_type == DT_SUBVOL &&
-                       target->bi_parent_subvol != le32_to_cpu(d.v->d_parent_subvol),
-                       c, dirent_d_parent_subvol_wrong,
-                       "dirent has wrong d_parent_subvol field: got %u, should be %u",
-                       le32_to_cpu(d.v->d_parent_subvol),
-                       target->bi_parent_subvol)) {
-               n = bch2_trans_kmalloc(trans, bkey_bytes(d.k));
-               ret = PTR_ERR_OR_ZERO(n);
-               if (ret)
-                       goto err;
-
-               bkey_reassemble(&n->k_i, d.s_c);
-               n->v.d_parent_subvol = cpu_to_le32(target->bi_parent_subvol);
-
-               ret = bch2_trans_update(trans, iter, &n->k_i, 0);
-               if (ret)
-                       goto err;
-
-               d = dirent_i_to_s_c(n);
-       }
 err:
 fsck_err:
        printbuf_exit(&buf);
@@ -1718,6 +1697,7 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
 {
        struct bch_fs *c = trans->c;
        struct bch_inode_unpacked subvol_root;
+       u32 parent_subvol = le32_to_cpu(d.v->d_parent_subvol);
        u32 target_subvol = le32_to_cpu(d.v->d_child_subvol);
        u32 target_snapshot;
        u64 target_inum;
@@ -1738,6 +1718,17 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
        if (ret && !bch2_err_matches(ret, ENOENT))
                return ret;
 
+       if (fsck_err_on(parent_subvol != subvol_root.bi_parent_subvol,
+                       c, inode_bi_parent_wrong,
+                       "subvol root %llu has wrong bi_parent_subvol: got %u, should be %u",
+                       target_inum,
+                       subvol_root.bi_parent_subvol, parent_subvol)) {
+               subvol_root.bi_parent_subvol = parent_subvol;
+               ret = __bch2_fsck_write_inode(trans, &subvol_root, target_snapshot);
+               if (ret)
+                       return ret;
+       }
+
        ret = check_dirent_target(trans, iter, d, &subvol_root,
                                  target_snapshot);
        if (ret)
index 2c998e721d90011d4e84a2306d29246f138de1cc..5178bf579f7c538b6f1132fc687aa281177c7db9 100644 (file)
        x(dirent_name_dot_or_dotdot,                            223)    \
        x(dirent_name_has_slash,                                224)    \
        x(dirent_d_type_wrong,                                  225)    \
-       x(dirent_d_parent_subvol_wrong,                         226)    \
+       x(inode_bi_parent_wrong,                                226)    \
        x(dirent_in_missing_dir_inode,                          227)    \
        x(dirent_in_non_dir_inode,                              228)    \
        x(dirent_to_missing_inode,                              229)    \