mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-18 11:17:07 +00:00
bcachefs: Per subvolume lost+found
On existing filesystems, we have a single global lost+found. Introducing subvolumes means we need to introduce per subvolume lost+found directories, because inodes are added to lost+found by their inode number, and inode numbers are now only unique within a subvolume. This patch adds support to fsck for per subvolume lost+found. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
This commit is contained in:
parent
b9e1adf579
commit
81ed9ce367
@ -39,6 +39,71 @@ static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum)
|
|||||||
return ret ?: sectors;
|
return ret ?: sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __snapshot_lookup_subvol(struct btree_trans *trans, u32 snapshot,
|
||||||
|
u32 *subvol)
|
||||||
|
{
|
||||||
|
struct btree_iter iter;
|
||||||
|
struct bkey_s_c k;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
bch2_trans_iter_init(trans, &iter, BTREE_ID_snapshots,
|
||||||
|
POS(0, snapshot), 0);
|
||||||
|
k = bch2_btree_iter_peek_slot(&iter);
|
||||||
|
ret = bkey_err(k);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (k.k->type != KEY_TYPE_snapshot) {
|
||||||
|
bch_err(trans->c, "snapshot %u not fonud", snapshot);
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*subvol = le32_to_cpu(bkey_s_c_to_snapshot(k).v->subvol);
|
||||||
|
err:
|
||||||
|
bch2_trans_iter_exit(trans, &iter);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snapshot_lookup_subvol(struct btree_trans *trans, u32 snapshot,
|
||||||
|
u32 *subvol)
|
||||||
|
{
|
||||||
|
return lockrestart_do(trans, __snapshot_lookup_subvol(trans, snapshot, subvol));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __subvol_lookup_root(struct btree_trans *trans, u32 subvol,
|
||||||
|
u64 *inum)
|
||||||
|
{
|
||||||
|
struct btree_iter iter;
|
||||||
|
struct bkey_s_c k;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
bch2_trans_iter_init(trans, &iter, BTREE_ID_subvolumes,
|
||||||
|
POS(0, subvol), 0);
|
||||||
|
k = bch2_btree_iter_peek_slot(&iter);
|
||||||
|
ret = bkey_err(k);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (k.k->type != KEY_TYPE_subvolume) {
|
||||||
|
bch_err(trans->c, "subvolume %u not fonud", subvol);
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*inum = le64_to_cpu(bkey_s_c_to_subvolume(k).v->inode);
|
||||||
|
err:
|
||||||
|
bch2_trans_iter_exit(trans, &iter);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int subvol_lookup_root(struct btree_trans *trans, u32 subvol, u64 *inum)
|
||||||
|
{
|
||||||
|
return lockrestart_do(trans, __subvol_lookup_root(trans, subvol, inum));
|
||||||
|
}
|
||||||
|
|
||||||
static int __lookup_inode(struct btree_trans *trans, u64 inode_nr,
|
static int __lookup_inode(struct btree_trans *trans, u64 inode_nr,
|
||||||
struct bch_inode_unpacked *inode,
|
struct bch_inode_unpacked *inode,
|
||||||
u32 *snapshot)
|
u32 *snapshot)
|
||||||
@ -136,6 +201,7 @@ static int remove_dirent(struct btree_trans *trans, struct bpos pos)
|
|||||||
|
|
||||||
/* Get lost+found, create if it doesn't exist: */
|
/* Get lost+found, create if it doesn't exist: */
|
||||||
static int lookup_lostfound(struct btree_trans *trans,
|
static int lookup_lostfound(struct btree_trans *trans,
|
||||||
|
u32 subvol,
|
||||||
struct bch_inode_unpacked *lostfound)
|
struct bch_inode_unpacked *lostfound)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
@ -146,12 +212,14 @@ static int lookup_lostfound(struct btree_trans *trans,
|
|||||||
u32 snapshot;
|
u32 snapshot;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = lookup_inode(trans, BCACHEFS_ROOT_INO, &root, &snapshot);
|
ret = subvol_lookup_root(trans, subvol, &inum);
|
||||||
|
|
||||||
|
ret = lookup_inode(trans, inum, &root, &snapshot);
|
||||||
if (ret && ret != -ENOENT)
|
if (ret && ret != -ENOENT)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
root_hash_info = bch2_hash_info_init(c, &root);
|
root_hash_info = bch2_hash_info_init(c, &root);
|
||||||
inum = bch2_dirent_lookup(c, BCACHEFS_ROOT_INO, &root_hash_info,
|
inum = bch2_dirent_lookup(c, root.bi_inum, &root_hash_info,
|
||||||
&lostfound_str);
|
&lostfound_str);
|
||||||
if (!inum) {
|
if (!inum) {
|
||||||
bch_notice(c, "creating lost+found");
|
bch_notice(c, "creating lost+found");
|
||||||
@ -188,16 +256,22 @@ create_lostfound:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int reattach_inode(struct btree_trans *trans,
|
static int reattach_inode(struct btree_trans *trans,
|
||||||
struct bch_inode_unpacked *inode)
|
struct bch_inode_unpacked *inode,
|
||||||
|
u32 snapshot)
|
||||||
{
|
{
|
||||||
struct bch_hash_info dir_hash;
|
struct bch_hash_info dir_hash;
|
||||||
struct bch_inode_unpacked lostfound;
|
struct bch_inode_unpacked lostfound;
|
||||||
char name_buf[20];
|
char name_buf[20];
|
||||||
struct qstr name;
|
struct qstr name;
|
||||||
u64 dir_offset = 0;
|
u64 dir_offset = 0;
|
||||||
|
u32 subvol;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = lookup_lostfound(trans, &lostfound);
|
ret = snapshot_lookup_subvol(trans, snapshot, &subvol);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = lookup_lostfound(trans, subvol, &lostfound);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1063,10 +1137,10 @@ static int path_down(struct pathbuf *p, u64 inum)
|
|||||||
|
|
||||||
static int check_path(struct btree_trans *trans,
|
static int check_path(struct btree_trans *trans,
|
||||||
struct pathbuf *p,
|
struct pathbuf *p,
|
||||||
struct bch_inode_unpacked *inode)
|
struct bch_inode_unpacked *inode,
|
||||||
|
u32 snapshot)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
u32 snapshot;
|
|
||||||
size_t i;
|
size_t i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -1085,7 +1159,7 @@ static int check_path(struct btree_trans *trans,
|
|||||||
inode->bi_nlink,
|
inode->bi_nlink,
|
||||||
inode->bi_dir,
|
inode->bi_dir,
|
||||||
inode->bi_dir_offset))
|
inode->bi_dir_offset))
|
||||||
ret = reattach_inode(trans, inode);
|
ret = reattach_inode(trans, inode, snapshot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -1108,13 +1182,13 @@ static int check_path(struct btree_trans *trans,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = lockrestart_do(trans,
|
ret = lockrestart_do(trans,
|
||||||
remove_backpointer(trans, inode));
|
remove_backpointer(trans, inode));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
bch_err(c, "error removing dirent: %i", ret);
|
bch_err(c, "error removing dirent: %i", ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = reattach_inode(trans, inode);
|
ret = reattach_inode(trans, inode, snapshot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1160,7 +1234,7 @@ static int check_directory_structure(struct bch_fs *c)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = check_path(&trans, &path, &u);
|
ret = check_path(&trans, &path, &u, iter.pos.snapshot);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user