summaryrefslogtreecommitdiff
path: root/fs/bcachefs/fsck.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-03-16 00:46:26 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:12 -0400
commitb9e1adf57988fb4632b86c43fde1551a24299b86 (patch)
tree3f6d8942ede2c864a84cb66501bf80d7682c60a7 /fs/bcachefs/fsck.c
parent14b393ee768e8339b9c64f82df24e8c081bdbff9 (diff)
downloadlinux-b9e1adf57988fb4632b86c43fde1551a24299b86.tar.gz
linux-b9e1adf57988fb4632b86c43fde1551a24299b86.tar.bz2
linux-b9e1adf57988fb4632b86c43fde1551a24299b86.zip
bcachefs: Add support for dirents that point to subvolumes
Dirents currently always point to inodes. Subvolumes add a new type of dirent, with d_type DT_SUBVOL, that instead points to an entry in the subvolumes btree, and the subvolume has a pointer to the root inode. This patch adds bch2_dirent_read_target() to get the inode (and potentially subvolume) a dirent points to, and changes existing code to use that instead of reading from d_inum directly. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/fsck.c')
-rw-r--r--fs/bcachefs/fsck.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 62158c0803db..dca4abda2c41 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -723,6 +723,7 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c_dirent d;
struct bch_inode_unpacked target;
u32 target_snapshot;
+ u32 target_subvol;
bool have_target;
bool backpointer_exists = true;
u64 d_inum;
@@ -783,6 +784,10 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
d = bkey_s_c_to_dirent(k);
d_inum = le64_to_cpu(d.v->d_inum);
+ ret = bch2_dirent_read_target(trans, d, &d_inum);
+ if (ret && ret != -ENOENT)
+ return ret;
+
ret = __lookup_inode(trans, d_inum, &target, &target_snapshot);
if (ret && ret != -ENOENT)
return ret;
@@ -855,7 +860,23 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
}
}
- if (fsck_err_on(d.v->d_type != mode_to_type(target.bi_mode), c,
+ target_subvol = d.v->d_type == DT_SUBVOL
+ ? le64_to_cpu(d.v->d_inum) : 0;
+
+ if (fsck_err_on(target.bi_subvol != target_subvol, c,
+ "subvol root %llu has wrong subvol field:\n"
+ "got %u\n"
+ "should be %u",
+ target.bi_inum,
+ target.bi_subvol,
+ target_subvol)) {
+ target.bi_subvol = target_subvol;
+
+ ret = write_inode(trans, &target, target_snapshot);
+ return ret ?: -EINTR;
+ }
+
+ if (fsck_err_on(vfs_d_type(d.v->d_type) != mode_to_type(target.bi_mode), c,
"incorrect d_type: should be %u:\n%s",
mode_to_type(target.bi_mode),
(bch2_bkey_val_to_text(&PBUF(buf), c,