bcachefs: Correctly reattach subvolumes

Subvolumes need special handling to reattach - we always reattach them
in the root subvolume's lost+found, and they need a slightly different
kind of dirent.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-02-09 16:04:50 -05:00
parent 3a136177f3
commit 56e230473d
3 changed files with 28 additions and 10 deletions

View File

@ -201,17 +201,17 @@ static struct bkey_i_dirent *dirent_create_key(struct btree_trans *trans,
}
int bch2_dirent_create_snapshot(struct btree_trans *trans,
u64 dir, u32 snapshot,
u32 dir_subvol, u64 dir, u32 snapshot,
const struct bch_hash_info *hash_info,
u8 type, const struct qstr *name, u64 dst_inum,
u64 *dir_offset,
bch_str_hash_flags_t str_hash_flags)
{
subvol_inum zero_inum = { 0 };
subvol_inum dir_inum = { .subvol = dir_subvol, .inum = dir };
struct bkey_i_dirent *dirent;
int ret;
dirent = dirent_create_key(trans, zero_inum, type, name, dst_inum);
dirent = dirent_create_key(trans, dir_inum, type, name, dst_inum);
ret = PTR_ERR_OR_ZERO(dirent);
if (ret)
return ret;
@ -220,7 +220,7 @@ int bch2_dirent_create_snapshot(struct btree_trans *trans,
dirent->k.p.snapshot = snapshot;
ret = bch2_hash_set_in_snapshot(trans, bch2_dirent_hash_desc, hash_info,
zero_inum, snapshot,
dir_inum, snapshot,
&dirent->k_i, str_hash_flags,
BTREE_UPDATE_INTERNAL_SNAPSHOT_NODE);
*dir_offset = dirent->k.p.offset;

View File

@ -35,7 +35,7 @@ static inline unsigned dirent_val_u64s(unsigned len)
int bch2_dirent_read_target(struct btree_trans *, subvol_inum,
struct bkey_s_c_dirent, subvol_inum *);
int bch2_dirent_create_snapshot(struct btree_trans *, u64, u32,
int bch2_dirent_create_snapshot(struct btree_trans *, u32, u64, u32,
const struct bch_hash_info *, u8,
const struct qstr *, u64, u64 *,
bch_str_hash_flags_t);

View File

@ -252,7 +252,7 @@ create_lostfound:
goto err;
ret = bch2_dirent_create_snapshot(trans,
root_inode.bi_inum, snapshot, &root_hash_info,
0, root_inode.bi_inum, snapshot, &root_hash_info,
mode_to_type(lostfound->bi_mode),
&lostfound_str,
lostfound->bi_inum,
@ -275,9 +275,24 @@ static int reattach_inode(struct btree_trans *trans,
char name_buf[20];
struct qstr name;
u64 dir_offset = 0;
u32 dirent_snapshot = inode_snapshot;
int ret;
ret = lookup_lostfound(trans, inode_snapshot, &lostfound);
if (inode->bi_subvol) {
inode->bi_parent_subvol = BCACHEFS_ROOT_SUBVOL;
u64 root_inum;
ret = subvol_lookup(trans, inode->bi_parent_subvol,
&dirent_snapshot, &root_inum);
if (ret)
return ret;
snprintf(name_buf, sizeof(name_buf), "subvol-%u", inode->bi_subvol);
} else {
snprintf(name_buf, sizeof(name_buf), "%llu", inode->bi_inum);
}
ret = lookup_lostfound(trans, dirent_snapshot, &lostfound);
if (ret)
return ret;
@ -291,14 +306,16 @@ static int reattach_inode(struct btree_trans *trans,
dir_hash = bch2_hash_info_init(trans->c, &lostfound);
snprintf(name_buf, sizeof(name_buf), "%llu", inode->bi_inum);
name = (struct qstr) QSTR(name_buf);
ret = bch2_dirent_create_snapshot(trans,
lostfound.bi_inum, inode_snapshot,
inode->bi_parent_subvol, lostfound.bi_inum,
dirent_snapshot,
&dir_hash,
inode_d_type(inode),
&name, inode->bi_inum, &dir_offset,
&name,
inode->bi_subvol ?: inode->bi_inum,
&dir_offset,
BCH_HASH_SET_MUST_CREATE);
if (ret)
return ret;
@ -2135,6 +2152,7 @@ static int check_path(struct btree_trans *trans, pathbuf *p, struct bkey_s_c ino
}
if (bch2_err_matches(ret, ENOENT)) {
ret = 0;
if (fsck_err(c, inode_unreachable,
"unreachable inode\n%s",
(printbuf_reset(&buf),