mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
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:
parent
3a136177f3
commit
56e230473d
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user