Commit 81ed9ce3 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet
Browse files

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: default avatarKent Overstreet <kent.overstreet@gmail.com>
parent b9e1adf5
Loading
Loading
Loading
Loading
+84 −10
Original line number Diff line number Diff line
@@ -39,6 +39,71 @@ static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum)
	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,
			  struct bch_inode_unpacked *inode,
			  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: */
static int lookup_lostfound(struct btree_trans *trans,
			    u32 subvol,
			    struct bch_inode_unpacked *lostfound)
{
	struct bch_fs *c = trans->c;
@@ -146,12 +212,14 @@ static int lookup_lostfound(struct btree_trans *trans,
	u32 snapshot;
	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)
		return ret;

	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);
	if (!inum) {
		bch_notice(c, "creating lost+found");
@@ -188,16 +256,22 @@ static int lookup_lostfound(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_inode_unpacked lostfound;
	char name_buf[20];
	struct qstr name;
	u64 dir_offset = 0;
	u32 subvol;
	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)
		return ret;

@@ -1063,10 +1137,10 @@ static int path_down(struct pathbuf *p, u64 inum)

static int check_path(struct btree_trans *trans,
		      struct pathbuf *p,
		      struct bch_inode_unpacked *inode)
		      struct bch_inode_unpacked *inode,
		      u32 snapshot)
{
	struct bch_fs *c = trans->c;
	u32 snapshot;
	size_t i;
	int ret = 0;

@@ -1085,7 +1159,7 @@ static int check_path(struct btree_trans *trans,
				     inode->bi_nlink,
				     inode->bi_dir,
				     inode->bi_dir_offset))
				ret = reattach_inode(trans, inode);
				ret = reattach_inode(trans, inode, snapshot);
			break;
		}
		ret = 0;
@@ -1114,7 +1188,7 @@ static int check_path(struct btree_trans *trans,
				break;
			}

			ret = reattach_inode(trans, inode);
			ret = reattach_inode(trans, inode, snapshot);
			break;
		}

@@ -1160,7 +1234,7 @@ static int check_directory_structure(struct bch_fs *c)
			break;
		}

		ret = check_path(&trans, &path, &u);
		ret = check_path(&trans, &path, &u, iter.pos.snapshot);
		if (ret)
			break;
	}