mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
bcachefs: Check subvol <-> inode pointers in check_subvol()
Subvolumes and subvolume root inodes point to each other: this verifies the subvolume -> inode -> subvolme path. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
52946d828a
commit
4c20278eb1
@ -324,7 +324,7 @@ int bch2_inode_unpack(struct bkey_s_c k,
|
||||
return bch2_inode_unpack_slowpath(k, unpacked);
|
||||
}
|
||||
|
||||
static int bch2_inode_peek_nowarn(struct btree_trans *trans,
|
||||
int bch2_inode_peek_nowarn(struct btree_trans *trans,
|
||||
struct btree_iter *iter,
|
||||
struct bch_inode_unpacked *inode,
|
||||
subvol_inum inum, unsigned flags)
|
||||
|
@ -95,6 +95,8 @@ struct bkey_i *bch2_inode_to_v3(struct btree_trans *, struct bkey_i *);
|
||||
|
||||
void bch2_inode_unpacked_to_text(struct printbuf *, struct bch_inode_unpacked *);
|
||||
|
||||
int bch2_inode_peek_nowarn(struct btree_trans *, struct btree_iter *,
|
||||
struct bch_inode_unpacked *, subvol_inum, unsigned);
|
||||
int bch2_inode_peek(struct btree_trans *, struct btree_iter *,
|
||||
struct bch_inode_unpacked *, subvol_inum, unsigned);
|
||||
|
||||
|
@ -42,6 +42,36 @@ static int check_subvol(struct btree_trans *trans,
|
||||
return ret ?: -BCH_ERR_transaction_restart_nested;
|
||||
}
|
||||
|
||||
struct bch_inode_unpacked inode;
|
||||
struct btree_iter inode_iter = {};
|
||||
ret = bch2_inode_peek_nowarn(trans, &inode_iter, &inode,
|
||||
(subvol_inum) { k.k->p.offset, le64_to_cpu(subvol.v->inode) },
|
||||
0);
|
||||
bch2_trans_iter_exit(trans, &inode_iter);
|
||||
|
||||
if (ret && !bch2_err_matches(ret, ENOENT))
|
||||
return ret;
|
||||
|
||||
if (fsck_err_on(ret, c, subvol_to_missing_root,
|
||||
"subvolume %llu points to missing subvolume root %llu:%u",
|
||||
k.k->p.offset, le64_to_cpu(subvol.v->inode),
|
||||
le32_to_cpu(subvol.v->snapshot))) {
|
||||
ret = bch2_subvolume_delete(trans, iter->pos.offset);
|
||||
bch_err_msg(c, ret, "deleting subvolume %llu", iter->pos.offset);
|
||||
return ret ?: -BCH_ERR_transaction_restart_nested;
|
||||
}
|
||||
|
||||
if (fsck_err_on(inode.bi_subvol != subvol.k->p.offset,
|
||||
c, subvol_root_wrong_bi_subvol,
|
||||
"subvol root %llu:%u has wrong bi_subvol field: got %u, should be %llu",
|
||||
inode.bi_inum, inode_iter.k.p.snapshot,
|
||||
inode.bi_subvol, subvol.k->p.offset)) {
|
||||
inode.bi_subvol = subvol.k->p.offset;
|
||||
ret = __bch2_fsck_write_inode(trans, &inode, le32_to_cpu(subvol.v->snapshot));
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BCH_SUBVOLUME_SNAP(subvol.v)) {
|
||||
u32 snapshot_root = bch2_snapshot_root(c, le32_to_cpu(subvol.v->snapshot));
|
||||
u32 snapshot_tree;
|
||||
@ -73,6 +103,7 @@ static int check_subvol(struct btree_trans *trans,
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
fsck_err:
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user