summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-04-19 22:19:18 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2021-05-19 15:33:45 -0400
commit86059dc101d61e3289bd93e5ca299e84affde9cf (patch)
tree9ca0046773d660241795b67835e7728acc7cba28
parent78324ed35e7489ffea33587296e072cc15e42da0 (diff)
bcachefs: Lookup/create lost+found lazily
This is prep work for subvolumes - each subvolume will have its own lost+found. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/fsck.c222
1 files changed, 111 insertions, 111 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index cfe606342032..1ce038846476 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -38,9 +38,9 @@ static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum)
return ret ?: sectors;
}
-static int lookup_inode(struct btree_trans *trans, u64 inode_nr,
- struct bch_inode_unpacked *inode,
- u32 *snapshot)
+static int __lookup_inode(struct btree_trans *trans, u64 inode_nr,
+ struct bch_inode_unpacked *inode,
+ u32 *snapshot)
{
struct btree_iter *iter;
struct bkey_s_c k;
@@ -63,19 +63,34 @@ err:
return ret;
}
-static int write_inode(struct btree_trans *trans,
- struct bch_inode_unpacked *inode,
- u32 snapshot)
+static int lookup_inode(struct btree_trans *trans, u64 inode_nr,
+ struct bch_inode_unpacked *inode,
+ u32 *snapshot)
+{
+ return lockrestart_do(trans, __lookup_inode(trans, inode_nr, inode, snapshot));
+}
+
+static int __write_inode(struct btree_trans *trans,
+ struct bch_inode_unpacked *inode,
+ u32 snapshot)
{
struct btree_iter *inode_iter =
bch2_trans_get_iter(trans, BTREE_ID_inodes,
SPOS(0, inode->bi_inum, snapshot),
BTREE_ITER_INTENT);
+ int ret = bch2_inode_write(trans, inode_iter, inode);
+ bch2_trans_iter_put(trans, inode_iter);
+ return ret;
+}
+
+static int write_inode(struct btree_trans *trans,
+ struct bch_inode_unpacked *inode,
+ u32 snapshot)
+{
int ret = __bch2_trans_do(trans, NULL, NULL,
BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW,
- bch2_inode_write(trans, inode_iter, inode));
- bch2_trans_iter_put(trans, inode_iter);
+ __write_inode(trans, inode, snapshot));
if (ret)
bch_err(trans->c, "error in fsck: error %i updating inode", ret);
return ret;
@@ -114,57 +129,101 @@ static int remove_dirent(struct btree_trans *trans, struct bpos pos)
return ret;
}
-static int __reattach_inode(struct btree_trans *trans,
- struct bch_inode_unpacked *lostfound,
- u64 inum)
+/* Get lost+found, create if it doesn't exist: */
+static int lookup_lostfound(struct btree_trans *trans,
+ struct bch_inode_unpacked *lostfound)
{
- struct bch_hash_info dir_hash =
- bch2_hash_info_init(trans->c, lostfound);
- struct bch_inode_unpacked inode_u;
+ struct bch_fs *c = trans->c;
+ struct bch_inode_unpacked root;
+ struct bch_hash_info root_hash_info;
+ struct qstr lostfound_str = QSTR("lost+found");
+ u64 inum;
+ u32 snapshot;
+ int ret;
+
+ ret = lookup_inode(trans, BCACHEFS_ROOT_INO, &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,
+ &lostfound_str);
+ if (!inum) {
+ bch_notice(c, "creating lost+found");
+ goto create_lostfound;
+ }
+
+ ret = lookup_inode(trans, inum, lostfound, &snapshot);
+ if (ret && ret != -ENOENT) {
+ /*
+ * The check_dirents pass has already run, dangling dirents
+ * shouldn't exist here:
+ */
+ bch_err(c, "error looking up lost+found: %i", ret);
+ return ret;
+ }
+
+ if (ret == -ENOENT) {
+create_lostfound:
+ bch2_inode_init_early(c, lostfound);
+
+ ret = __bch2_trans_do(trans, NULL, NULL,
+ BTREE_INSERT_NOFAIL|
+ BTREE_INSERT_LAZY_RW,
+ bch2_create_trans(trans,
+ BCACHEFS_ROOT_INO, &root,
+ lostfound,
+ &lostfound_str,
+ 0, 0, S_IFDIR|0700, 0, NULL, NULL));
+ if (ret)
+ bch_err(c, "error creating lost+found: %i", ret);
+ }
+
+ return 0;
+}
+
+static int reattach_inode(struct btree_trans *trans,
+ struct bch_inode_unpacked *inode)
+{
+ struct bch_hash_info dir_hash;
+ struct bch_inode_unpacked lostfound;
char name_buf[20];
struct qstr name;
u64 dir_offset = 0;
- u32 snapshot;
int ret;
- snprintf(name_buf, sizeof(name_buf), "%llu", inum);
- name = (struct qstr) QSTR(name_buf);
-
- ret = lookup_inode(trans, inum, &inode_u, &snapshot);
+ ret = lookup_lostfound(trans, &lostfound);
if (ret)
return ret;
- if (S_ISDIR(inode_u.bi_mode)) {
- lostfound->bi_nlink++;
+ if (S_ISDIR(inode->bi_mode)) {
+ lostfound.bi_nlink++;
- ret = write_inode(trans, lostfound, U32_MAX);
+ ret = write_inode(trans, &lostfound, U32_MAX);
if (ret)
return ret;
}
- ret = bch2_dirent_create(trans, lostfound->bi_inum, &dir_hash,
- mode_to_type(inode_u.bi_mode),
- &name, inum, &dir_offset,
- BCH_HASH_SET_MUST_CREATE);
- if (ret)
- return ret;
+ dir_hash = bch2_hash_info_init(trans->c, &lostfound);
- inode_u.bi_dir = lostfound->bi_inum;
- inode_u.bi_dir_offset = dir_offset;
+ snprintf(name_buf, sizeof(name_buf), "%llu", inode->bi_inum);
+ name = (struct qstr) QSTR(name_buf);
- return write_inode(trans, &inode_u, U32_MAX);
-}
+ ret = __bch2_trans_do(trans, NULL, NULL, BTREE_INSERT_LAZY_RW,
+ bch2_dirent_create(trans, lostfound.bi_inum, &dir_hash,
+ mode_to_type(inode->bi_mode),
+ &name, inode->bi_inum, &dir_offset,
+ BCH_HASH_SET_MUST_CREATE));
+ if (ret) {
+ bch_err(trans->c, "error %i reattaching inode %llu",
+ ret, inode->bi_inum);
+ return ret;
+ }
-static int reattach_inode(struct btree_trans *trans,
- struct bch_inode_unpacked *lostfound,
- u64 inum)
-{
- int ret = __bch2_trans_do(trans, NULL, NULL, BTREE_INSERT_LAZY_RW,
- __reattach_inode(trans, lostfound, inum));
- if (ret)
- bch_err(trans->c, "error %i reattaching inode %llu", ret, inum);
+ inode->bi_dir = lostfound.bi_inum;
+ inode->bi_dir_offset = dir_offset;
- return ret;
+ return write_inode(trans, inode, U32_MAX);
}
static int remove_backpointer(struct btree_trans *trans,
@@ -931,58 +990,6 @@ create_root:
BTREE_INSERT_LAZY_RW);
}
-/* Get lost+found, create if it doesn't exist: */
-static int check_lostfound(struct bch_fs *c,
- struct bch_inode_unpacked *root_inode,
- struct bch_inode_unpacked *lostfound_inode)
-{
- struct qstr lostfound = QSTR("lost+found");
- struct bch_hash_info root_hash_info =
- bch2_hash_info_init(c, root_inode);
- u64 inum;
- u32 snapshot;
- int ret;
-
- bch_verbose(c, "checking lost+found");
-
- inum = bch2_dirent_lookup(c, BCACHEFS_ROOT_INO, &root_hash_info,
- &lostfound);
- if (!inum) {
- bch_notice(c, "creating lost+found");
- goto create_lostfound;
- }
-
- ret = bch2_trans_do(c, NULL, NULL, 0,
- lookup_inode(&trans, inum, lostfound_inode, &snapshot));
- if (ret && ret != -ENOENT)
- return ret;
-
- if (fsck_err_on(ret, c, "lost+found missing"))
- goto create_lostfound;
-
- if (fsck_err_on(!S_ISDIR(lostfound_inode->bi_mode), c,
- "lost+found inode not a directory"))
- goto create_lostfound;
-
- return 0;
-fsck_err:
- return ret;
-create_lostfound:
- bch2_inode_init_early(c, lostfound_inode);
-
- ret = bch2_trans_do(c, NULL, NULL,
- BTREE_INSERT_NOFAIL|
- BTREE_INSERT_LAZY_RW,
- bch2_create_trans(&trans,
- BCACHEFS_ROOT_INO, root_inode,
- lostfound_inode, &lostfound,
- 0, 0, S_IFDIR|0700, 0, NULL, NULL));
- if (ret)
- bch_err(c, "error creating lost+found: %i", ret);
-
- return ret;
-}
-
struct pathbuf {
size_t nr;
size_t size;
@@ -1014,7 +1021,6 @@ static int path_down(struct pathbuf *p, u64 inum)
}
static int check_path(struct btree_trans *trans,
- struct bch_inode_unpacked *lostfound,
struct pathbuf *p,
struct bch_inode_unpacked *inode)
{
@@ -1038,7 +1044,7 @@ static int check_path(struct btree_trans *trans,
inode->bi_nlink,
inode->bi_dir,
inode->bi_dir_offset))
- ret = reattach_inode(trans, lostfound, inode->bi_inum);
+ ret = reattach_inode(trans, inode);
break;
}
ret = 0;
@@ -1067,12 +1073,11 @@ static int check_path(struct btree_trans *trans,
break;
}
- ret = reattach_inode(trans, lostfound, inode->bi_inum);
+ ret = reattach_inode(trans, inode);
break;
}
- ret = lockrestart_do(trans,
- lookup_inode(trans, inode->bi_dir, inode, &snapshot));
+ ret = lookup_inode(trans, inode->bi_dir, inode, &snapshot);
if (ret) {
/* Should have been caught in dirents pass */
bch_err(c, "error looking up parent directory: %i", ret);
@@ -1090,8 +1095,7 @@ fsck_err:
* After check_dirents(), if an inode backpointer doesn't exist that means it's
* unreachable:
*/
-static int check_directory_structure(struct bch_fs *c,
- struct bch_inode_unpacked *lostfound)
+static int check_directory_structure(struct bch_fs *c)
{
struct btree_trans trans;
struct btree_iter *iter;
@@ -1113,7 +1117,7 @@ static int check_directory_structure(struct bch_fs *c,
break;
}
- ret = check_path(&trans, lostfound, &path, &u);
+ ret = check_path(&trans, &path, &u);
if (ret)
break;
}
@@ -1190,7 +1194,6 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
}
static int check_inode_nlink(struct btree_trans *trans,
- struct bch_inode_unpacked *lostfound_inode,
struct btree_iter *iter,
struct bkey_s_c_inode inode,
unsigned nlink)
@@ -1238,7 +1241,6 @@ fsck_err:
noinline_for_stack
static int bch2_gc_walk_inodes(struct bch_fs *c,
- struct bch_inode_unpacked *lostfound_inode,
nlink_table *links,
u64 range_start, u64 range_end)
{
@@ -1259,7 +1261,7 @@ static int bch2_gc_walk_inodes(struct bch_fs *c,
continue;
link = genradix_ptr(links, k.k->p.offset - range_start);
- ret = check_inode_nlink(&trans, lostfound_inode, iter,
+ ret = check_inode_nlink(&trans, iter,
bkey_s_c_to_inode(k), link ? link->count : 0);
if (ret)
break;
@@ -1275,8 +1277,7 @@ static int bch2_gc_walk_inodes(struct bch_fs *c,
}
noinline_for_stack
-static int check_nlinks(struct bch_fs *c,
- struct bch_inode_unpacked *lostfound_inode)
+static int check_nlinks(struct bch_fs *c)
{
nlink_table links;
u64 this_iter_range_start, next_iter_range_start = 0;
@@ -1296,7 +1297,7 @@ static int check_nlinks(struct bch_fs *c,
if (ret)
break;
- ret = bch2_gc_walk_inodes(c, lostfound_inode, &links,
+ ret = bch2_gc_walk_inodes(c, &links,
this_iter_range_start,
next_iter_range_start);
if (ret)
@@ -1316,16 +1317,15 @@ static int check_nlinks(struct bch_fs *c,
*/
int bch2_fsck_full(struct bch_fs *c)
{
- struct bch_inode_unpacked root_inode, lostfound_inode;
+ struct bch_inode_unpacked root_inode;
return check_inodes(c, true) ?:
check_extents(c) ?:
check_dirents(c) ?:
check_xattrs(c) ?:
check_root(c, &root_inode) ?:
- check_lostfound(c, &root_inode, &lostfound_inode) ?:
- check_directory_structure(c, &lostfound_inode) ?:
- check_nlinks(c, &lostfound_inode);
+ check_directory_structure(c) ?:
+ check_nlinks(c);
}
int bch2_fsck_walk_inodes_only(struct bch_fs *c)