diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-10-19 08:08:05 +0300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-23 00:09:14 +0300 |
commit | 488f97764a9adb68d2ebec0a6e5b96f0f0a7bf38 (patch) | |
tree | 3140e80f31b92ad6567424abb262b895c6528507 /fs/bcachefs/fsck.c | |
parent | ca130b9c5e120994483a34c72526dcd4bf308d84 (diff) | |
download | linux-488f97764a9adb68d2ebec0a6e5b96f0f0a7bf38.tar.xz |
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/bcachefs/fsck.c')
-rw-r--r-- | fs/bcachefs/fsck.c | 24 |
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) |