summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-10-19 01:08:05 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:14 -0400
commit488f97764a9adb68d2ebec0a6e5b96f0f0a7bf38 (patch)
tree3140e80f31b92ad6567424abb262b895c6528507 /fs
parentca130b9c5e120994483a34c72526dcd4bf308d84 (diff)
downloadlinux-stable-488f97764a9adb68d2ebec0a6e5b96f0f0a7bf38.tar.gz
linux-stable-488f97764a9adb68d2ebec0a6e5b96f0f0a7bf38.tar.bz2
linux-stable-488f97764a9adb68d2ebec0a6e5b96f0f0a7bf38.zip
bcachefs: Fix check_path() across subvolumes
Checking of directory structure across subvolumes was broken - we need to look up the snapshot ID of the parent subvolume when crossing subvol boundaries. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/fsck.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 208bf6df82b5..826a3577ee93 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -1050,6 +1050,8 @@ static int inode_backpointer_exists(struct btree_trans *trans,
{
struct btree_iter iter;
struct bkey_s_c k;
+ u32 target_subvol, target_snapshot;
+ u64 target_inum;
int ret;
bch2_trans_iter_init(trans, &iter, BTREE_ID_dirents,
@@ -1061,7 +1063,15 @@ static int inode_backpointer_exists(struct btree_trans *trans,
if (k.k->type != KEY_TYPE_dirent)
goto out;
- ret = le64_to_cpu(bkey_s_c_to_dirent(k).v->d_inum) == inode->bi_inum;
+ ret = __bch2_dirent_read_target(trans, bkey_s_c_to_dirent(k),
+ &target_subvol,
+ &target_snapshot,
+ &target_inum,
+ true);
+ if (ret)
+ goto out;
+
+ ret = target_inum == inode->bi_inum;
out:
bch2_trans_iter_exit(trans, &iter);
return ret;
@@ -1754,7 +1764,17 @@ static int check_path(struct btree_trans *trans,
snapshot = snapshot_t(c, snapshot)->equiv;
p->nr = 0;
- while (inode->bi_inum != BCACHEFS_ROOT_INO) {
+ while (!(inode->bi_inum == BCACHEFS_ROOT_INO &&
+ inode->bi_subvol == BCACHEFS_ROOT_SUBVOL)) {
+ if (inode->bi_parent_subvol) {
+ u64 inum;
+
+ ret = subvol_lookup(trans, inode->bi_parent_subvol,
+ &snapshot, &inum);
+ if (ret)
+ break;
+ }
+
ret = lockrestart_do(trans,
inode_backpointer_exists(trans, inode, snapshot));
if (ret < 0)