summaryrefslogtreecommitdiff
path: root/fs/bcachefs/fsck.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-03-25 15:10:15 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:18 -0400
commit424eb881300467a21a108d04c9dd08a6f8c007dc (patch)
tree760482adf8b16aa98b03932d5fabaab8e514c998 /fs/bcachefs/fsck.c
parent5df4be3f62c9bde73db801504b3db2693b28328c (diff)
bcachefs: Only get btree iters from btree transactions
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/fsck.c')
-rw-r--r--fs/bcachefs/fsck.c146
1 files changed, 74 insertions, 72 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 439f758d8178..41284d38db2f 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -16,6 +16,23 @@
#define QSTR(n) { { { .len = strlen(n) } }, .name = n }
+static s64 bch2_count_inode_sectors(struct btree_trans *trans, u64 inum)
+{
+ struct btree_iter *iter;
+ struct bkey_s_c k;
+ u64 sectors = 0;
+
+ for_each_btree_key(trans, iter, BTREE_ID_EXTENTS, POS(inum, 0), 0, k) {
+ if (k.k->p.inode != inum)
+ break;
+
+ if (bkey_extent_is_allocation(k.k))
+ sectors += k.k->size;
+ }
+
+ return bch2_trans_iter_free(trans, iter) ?: sectors;
+}
+
static int remove_dirent(struct bch_fs *c, struct btree_iter *iter,
struct bkey_s_c_dirent dirent)
{
@@ -181,44 +198,32 @@ err:
return ret;
}
-/* fsck hasn't been converted to new transactions yet: */
-static int fsck_hash_delete_at(const struct bch_hash_desc desc,
+static int fsck_hash_delete_at(struct btree_trans *trans,
+ const struct bch_hash_desc desc,
struct bch_hash_info *info,
- struct btree_iter *orig_iter)
+ struct btree_iter *iter)
{
- struct btree_trans trans;
- struct btree_iter *iter;
int ret;
-
- bch2_btree_iter_unlock(orig_iter);
-
- bch2_trans_init(&trans, orig_iter->c);
retry:
- bch2_trans_begin(&trans);
-
- iter = bch2_trans_copy_iter(&trans, orig_iter);
- if (IS_ERR(iter)) {
- ret = PTR_ERR(iter);
- goto err;
- }
-
- ret = bch2_hash_delete_at(&trans, desc, info, iter) ?:
- bch2_trans_commit(&trans, NULL, NULL,
+ ret = bch2_hash_delete_at(trans, desc, info, iter) ?:
+ bch2_trans_commit(trans, NULL, NULL,
BTREE_INSERT_ATOMIC|
BTREE_INSERT_NOFAIL|
BTREE_INSERT_LAZY_RW);
-err:
- if (ret == -EINTR)
- goto retry;
+ if (ret == -EINTR) {
+ ret = bch2_btree_iter_traverse(iter);
+ if (!ret)
+ goto retry;
+ }
- bch2_trans_exit(&trans);
return ret;
}
-static int hash_check_duplicates(const struct bch_hash_desc desc,
- struct hash_check *h, struct bch_fs *c,
- struct btree_iter *k_iter, struct bkey_s_c k)
+static int hash_check_duplicates(struct btree_trans *trans,
+ const struct bch_hash_desc desc, struct hash_check *h,
+ struct btree_iter *k_iter, struct bkey_s_c k)
{
+ struct bch_fs *c = trans->c;
struct btree_iter *iter;
struct bkey_s_c k2;
char buf[200];
@@ -239,7 +244,7 @@ static int hash_check_duplicates(const struct bch_hash_desc desc,
"duplicate hash table keys:\n%s",
(bch2_bkey_val_to_text(&PBUF(buf), c,
k), buf))) {
- ret = fsck_hash_delete_at(desc, &h->info, k_iter);
+ ret = fsck_hash_delete_at(trans, desc, &h->info, k_iter);
if (ret)
return ret;
ret = 1;
@@ -274,9 +279,9 @@ static bool key_has_correct_hash(const struct bch_hash_desc desc,
hash <= k.k->p.offset;
}
-static int hash_check_key(const struct bch_hash_desc desc,
- struct btree_trans *trans, struct hash_check *h,
- struct btree_iter *k_iter, struct bkey_s_c k)
+static int hash_check_key(struct btree_trans *trans,
+ const struct bch_hash_desc desc, struct hash_check *h,
+ struct btree_iter *k_iter, struct bkey_s_c k)
{
struct bch_fs *c = trans->c;
char buf[200];
@@ -312,7 +317,7 @@ static int hash_check_key(const struct bch_hash_desc desc,
return 1;
}
- ret = hash_check_duplicates(desc, h, c, k_iter, k);
+ ret = hash_check_duplicates(trans, desc, h, k_iter, k);
fsck_err:
return ret;
}
@@ -417,14 +422,17 @@ noinline_for_stack
static int check_extents(struct bch_fs *c)
{
struct inode_walker w = inode_walker_init();
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
u64 i_sectors;
int ret = 0;
+ bch2_trans_init(&trans, c);
+
bch_verbose(c, "checking extents");
- for_each_btree_key(&iter, c, BTREE_ID_EXTENTS,
+ for_each_btree_key(&trans, iter, BTREE_ID_EXTENTS,
POS(BCACHEFS_ROOT_INO, 0), 0, k) {
ret = walk_inode(c, &w, k.k->p.inode);
if (ret)
@@ -437,7 +445,7 @@ static int check_extents(struct bch_fs *c)
!S_ISREG(w.inode.bi_mode) && !S_ISLNK(w.inode.bi_mode), c,
"extent type %u for non regular file, inode %llu mode %o",
k.k->type, k.k->p.inode, w.inode.bi_mode)) {
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_unlock(&trans);
ret = bch2_inode_truncate(c, k.k->p.inode, 0);
if (ret)
@@ -449,14 +457,14 @@ static int check_extents(struct bch_fs *c)
w.have_inode &&
!(w.inode.bi_flags & BCH_INODE_I_SECTORS_DIRTY) &&
w.inode.bi_sectors !=
- (i_sectors = bch2_count_inode_sectors(c, w.cur_inum)),
+ (i_sectors = bch2_count_inode_sectors(&trans, w.cur_inum)),
c, "i_sectors wrong: got %llu, should be %llu",
w.inode.bi_sectors, i_sectors)) {
struct bkey_inode_buf p;
w.inode.bi_sectors = i_sectors;
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_unlock(&trans);
bch2_inode_pack(&p, &w.inode);
@@ -470,7 +478,7 @@ static int check_extents(struct bch_fs *c)
}
/* revalidate iterator: */
- k = bch2_btree_iter_peek(&iter);
+ k = bch2_btree_iter_peek(iter);
}
if (fsck_err_on(w.have_inode &&
@@ -479,7 +487,7 @@ static int check_extents(struct bch_fs *c)
k.k->p.offset > round_up(w.inode.bi_size, PAGE_SIZE) >> 9, c,
"extent type %u offset %llu past end of inode %llu, i_size %llu",
k.k->type, k.k->p.offset, k.k->p.inode, w.inode.bi_size)) {
- bch2_btree_iter_unlock(&iter);
+ bch2_trans_unlock(&trans);
ret = bch2_inode_truncate(c, k.k->p.inode,
w.inode.bi_size);
@@ -490,7 +498,7 @@ static int check_extents(struct bch_fs *c)
}
err:
fsck_err:
- return bch2_btree_iter_unlock(&iter) ?: ret;
+ return bch2_trans_exit(&trans) ?: ret;
}
/*
@@ -688,7 +696,8 @@ static int check_xattrs(struct bch_fs *c)
if (w.first_this_inode && w.have_inode)
hash_check_set_inode(&h, c, &w.inode);
- ret = hash_check_key(bch2_xattr_hash_desc, &trans, &h, iter, k);
+ ret = hash_check_key(&trans, bch2_xattr_hash_desc,
+ &h, iter, k);
if (ret)
goto fsck_err;
}
@@ -863,13 +872,16 @@ static int check_directory_structure(struct bch_fs *c,
struct inode_bitmap dirs_done = { NULL, 0 };
struct pathbuf path = { 0, 0, NULL };
struct pathbuf_entry *e;
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
struct bkey_s_c_dirent dirent;
bool had_unreachable;
u64 d_inum;
int ret = 0;
+ bch2_trans_init(&trans, c);
+
bch_verbose(c, "checking directory structure");
/* DFS: */
@@ -894,7 +906,7 @@ next:
if (e->offset == U64_MAX)
goto up;
- for_each_btree_key(&iter, c, BTREE_ID_DIRENTS,
+ for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS,
POS(e->inum, e->offset + 1), 0, k) {
if (k.k->p.inode != e->inum)
break;
@@ -914,7 +926,7 @@ next:
if (fsck_err_on(inode_bitmap_test(&dirs_done, d_inum), c,
"directory %llu has multiple hardlinks",
d_inum)) {
- ret = remove_dirent(c, &iter, dirent);
+ ret = remove_dirent(c, iter, dirent);
if (ret)
goto err;
continue;
@@ -931,10 +943,14 @@ next:
goto err;
}
- bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_iter_free(&trans, iter);
+ if (ret) {
+ bch_err(c, "btree error %i in fsck", ret);
+ goto err;
+ }
goto next;
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_iter_free(&trans, iter);
if (ret) {
bch_err(c, "btree error %i in fsck", ret);
goto err;
@@ -943,7 +959,7 @@ up:
path.nr--;
}
- for_each_btree_key(&iter, c, BTREE_ID_INODES, POS_MIN, 0, k) {
+ for_each_btree_key(&trans, iter, BTREE_ID_INODES, POS_MIN, 0, k) {
if (k.k->type != KEY_TYPE_inode)
continue;
@@ -956,7 +972,7 @@ up:
if (fsck_err_on(!inode_bitmap_test(&dirs_done, k.k->p.inode), c,
"unreachable directory found (inum %llu)",
k.k->p.inode)) {
- bch2_btree_iter_unlock(&iter);
+ bch2_btree_iter_unlock(iter);
ret = reattach_inode(c, lostfound_inode, k.k->p.inode);
if (ret) {
@@ -966,7 +982,7 @@ up:
had_unreachable = true;
}
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_iter_free(&trans, iter);
if (ret)
goto err;
@@ -985,7 +1001,7 @@ out:
return ret;
err:
fsck_err:
- ret = bch2_btree_iter_unlock(&iter) ?: ret;
+ ret = bch2_trans_exit(&trans) ?: ret;
goto out;
}
@@ -1022,15 +1038,18 @@ noinline_for_stack
static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
u64 range_start, u64 *range_end)
{
- struct btree_iter iter;
+ struct btree_trans trans;
+ struct btree_iter *iter;
struct bkey_s_c k;
struct bkey_s_c_dirent d;
u64 d_inum;
int ret;
+ bch2_trans_init(&trans, c);
+
inc_link(c, links, range_start, range_end, BCACHEFS_ROOT_INO, false);
- for_each_btree_key(&iter, c, BTREE_ID_DIRENTS, POS_MIN, 0, k) {
+ for_each_btree_key(&trans, iter, BTREE_ID_DIRENTS, POS_MIN, 0, k) {
switch (k.k->type) {
case KEY_TYPE_dirent:
d = bkey_s_c_to_dirent(k);
@@ -1046,32 +1065,15 @@ static int bch2_gc_walk_dirents(struct bch_fs *c, nlink_table *links,
break;
}
- bch2_btree_iter_cond_resched(&iter);
+ bch2_trans_cond_resched(&trans);
}
- ret = bch2_btree_iter_unlock(&iter);
+ ret = bch2_trans_exit(&trans);
if (ret)
bch_err(c, "error in fs gc: btree error %i while walking dirents", ret);
return ret;
}
-s64 bch2_count_inode_sectors(struct bch_fs *c, u64 inum)
-{
- struct btree_iter iter;
- struct bkey_s_c k;
- u64 sectors = 0;
-
- for_each_btree_key(&iter, c, BTREE_ID_EXTENTS, POS(inum, 0), 0, k) {
- if (k.k->p.inode != inum)
- break;
-
- if (bkey_extent_is_allocation(k.k))
- sectors += k.k->size;
- }
-
- return bch2_btree_iter_unlock(&iter) ?: sectors;
-}
-
static int check_inode_nlink(struct bch_fs *c,
struct bch_inode_unpacked *lostfound_inode,
struct bch_inode_unpacked *u,
@@ -1253,7 +1255,7 @@ static int check_inode(struct btree_trans *trans,
bch_verbose(c, "recounting sectors for inode %llu",
u.bi_inum);
- sectors = bch2_count_inode_sectors(c, u.bi_inum);
+ sectors = bch2_count_inode_sectors(trans, u.bi_inum);
if (sectors < 0) {
bch_err(c, "error in fs gc: error %i "
"recounting inode sectors",
@@ -1346,7 +1348,7 @@ peek_nlinks: link = genradix_iter_peek(&nlinks_iter, links);
genradix_iter_advance(&nlinks_iter, links);
bch2_btree_iter_next(iter);
- bch2_btree_iter_cond_resched(iter);
+ bch2_trans_cond_resched(&trans);
}
fsck_err:
bch2_trans_exit(&trans);