summaryrefslogtreecommitdiff
path: root/fs/bcachefs/fsck.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/fsck.c')
-rw-r--r--fs/bcachefs/fsck.c607
1 files changed, 277 insertions, 330 deletions
diff --git a/fs/bcachefs/fsck.c b/fs/bcachefs/fsck.c
index 471e93a3f00c..d6fd25f1db1f 100644
--- a/fs/bcachefs/fsck.c
+++ b/fs/bcachefs/fsck.c
@@ -15,6 +15,7 @@
#include "io_misc.h"
#include "keylist.h"
#include "namei.h"
+#include "progress.h"
#include "recovery_passes.h"
#include "snapshot.h"
#include "super.h"
@@ -53,10 +54,9 @@ static int dirent_points_to_inode(struct bch_fs *c,
{
int ret = dirent_points_to_inode_nowarn(c, dirent, inode);
if (ret) {
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
dirent_inode_mismatch_msg(&buf, c, dirent, inode);
bch_warn(c, "%s", buf.buf);
- printbuf_exit(&buf);
}
return ret;
}
@@ -126,7 +126,7 @@ static int lookup_dirent_in_snapshot(struct btree_trans *trans,
struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
*target = le64_to_cpu(d.v->d_inum);
*type = d.v->d_type;
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return 0;
}
@@ -137,7 +137,6 @@ static int lookup_dirent_in_snapshot(struct btree_trans *trans,
static int find_snapshot_tree_subvol(struct btree_trans *trans,
u32 tree_id, u32 *subvol)
{
- struct btree_iter iter;
struct bkey_s_c k;
int ret;
@@ -151,13 +150,11 @@ static int find_snapshot_tree_subvol(struct btree_trans *trans,
if (s.v->subvol) {
*subvol = le32_to_cpu(s.v->subvol);
- goto found;
+ return 0;
}
}
- ret = bch_err_throw(trans->c, ENOENT_no_snapshot_tree_subvol);
-found:
- bch2_trans_iter_exit(trans, &iter);
- return ret;
+
+ return ret ?: bch_err_throw(trans->c, ENOENT_no_snapshot_tree_subvol);
}
/* Get lost+found, create if it doesn't exist: */
@@ -167,7 +164,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
{
struct bch_fs *c = trans->c;
struct qstr lostfound_str = QSTR("lost+found");
- struct btree_iter lostfound_iter = {};
+ struct btree_iter lostfound_iter = { NULL };
u64 inum = 0;
unsigned d_type = 0;
int ret;
@@ -193,8 +190,7 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
return ret;
if (!subvol.inode) {
- struct btree_iter iter;
- struct bkey_i_subvolume *subvol = bch2_bkey_get_mut_typed(trans, &iter,
+ struct bkey_i_subvolume *subvol = bch2_bkey_get_mut_typed(trans,
BTREE_ID_subvolumes, POS(0, subvolid),
0, subvolume);
ret = PTR_ERR_OR_ZERO(subvol);
@@ -202,7 +198,6 @@ static int lookup_lostfound(struct btree_trans *trans, u32 snapshot,
return ret;
subvol->v.inode = cpu_to_le64(reattaching_inum);
- bch2_trans_iter_exit(trans, &iter);
}
subvol_inum root_inum = {
@@ -253,14 +248,13 @@ create_lostfound:
* XXX: we could have a nicer log message here if we had a nice way to
* walk backpointers to print a path
*/
- struct printbuf path = PRINTBUF;
+ CLASS(printbuf, path)();
ret = bch2_inum_to_path(trans, root_inum, &path);
if (ret)
goto err;
bch_notice(c, "creating %s/lost+found in subvol %llu snapshot %u",
path.buf, root_inum.subvol, snapshot);
- printbuf_exit(&path);
u64 now = bch2_current_time(c);
u64 cpu = raw_smp_processor_id();
@@ -276,8 +270,8 @@ create_lostfound:
if (ret)
goto err;
- bch2_btree_iter_set_snapshot(trans, &lostfound_iter, snapshot);
- ret = bch2_btree_iter_traverse(trans, &lostfound_iter);
+ bch2_btree_iter_set_snapshot(&lostfound_iter, snapshot);
+ ret = bch2_btree_iter_traverse(&lostfound_iter);
if (ret)
goto err;
@@ -293,7 +287,7 @@ create_lostfound:
BTREE_UPDATE_internal_snapshot_node);
err:
bch_err_msg(c, ret, "creating lost+found");
- bch2_trans_iter_exit(trans, &lostfound_iter);
+ bch2_trans_iter_exit(&lostfound_iter);
return ret;
}
@@ -334,11 +328,11 @@ static inline bool inode_should_reattach(struct bch_inode_unpacked *inode)
static int maybe_delete_dirent(struct btree_trans *trans, struct bpos d_pos, u32 snapshot)
{
- struct btree_iter iter;
- struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_dirents,
- SPOS(d_pos.inode, d_pos.offset, snapshot),
- BTREE_ITER_intent|
- BTREE_ITER_with_updates);
+ CLASS(btree_iter, iter)(trans, BTREE_ID_dirents,
+ SPOS(d_pos.inode, d_pos.offset, snapshot),
+ BTREE_ITER_intent|
+ BTREE_ITER_with_updates);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter);
int ret = bkey_err(k);
if (ret)
return ret;
@@ -351,16 +345,15 @@ static int maybe_delete_dirent(struct btree_trans *trans, struct bpos d_pos, u32
struct bkey_i *k = bch2_trans_kmalloc(trans, sizeof(*k));
ret = PTR_ERR_OR_ZERO(k);
if (ret)
- goto err;
+ return ret;
bkey_init(&k->k);
k->k.type = KEY_TYPE_whiteout;
k->k.p = iter.pos;
- ret = bch2_trans_update(trans, &iter, k, BTREE_UPDATE_internal_snapshot_node);
+ return bch2_trans_update(trans, &iter, k, BTREE_UPDATE_internal_snapshot_node);
}
-err:
- bch2_trans_iter_exit(trans, &iter);
- return ret;
+
+ return 0;
}
static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked *inode)
@@ -374,9 +367,8 @@ static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked *
if (inode->bi_subvol) {
inode->bi_parent_subvol = BCACHEFS_ROOT_SUBVOL;
- struct btree_iter subvol_iter;
struct bkey_i_subvolume *subvol =
- bch2_bkey_get_mut_typed(trans, &subvol_iter,
+ bch2_bkey_get_mut_typed(trans,
BTREE_ID_subvolumes, POS(0, inode->bi_subvol),
0, subvolume);
ret = PTR_ERR_OR_ZERO(subvol);
@@ -384,7 +376,6 @@ static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked *
return ret;
subvol->v.fs_path_parent = BCACHEFS_ROOT_SUBVOL;
- bch2_trans_iter_exit(trans, &subvol_iter);
u64 root_inum;
ret = subvol_lookup(trans, inode->bi_parent_subvol,
@@ -455,8 +446,7 @@ static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked *
* whiteouts for the dirent we just created.
*/
if (!inode->bi_subvol && bch2_snapshot_is_leaf(c, inode->bi_snapshot) <= 0) {
- snapshot_id_list whiteouts_done;
- struct btree_iter iter;
+ CLASS(snapshot_id_list, whiteouts_done)();
struct bkey_s_c k;
darray_init(&whiteouts_done);
@@ -475,19 +465,16 @@ static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked *
struct bch_inode_unpacked child_inode;
ret = bch2_inode_unpack(k, &child_inode);
if (ret)
- break;
+ return ret;
if (!inode_should_reattach(&child_inode)) {
- ret = maybe_delete_dirent(trans,
- SPOS(lostfound.bi_inum, inode->bi_dir_offset,
- dirent_snapshot),
- k.k->p.snapshot);
- if (ret)
- break;
-
- ret = snapshot_list_add(c, &whiteouts_done, k.k->p.snapshot);
+ ret = maybe_delete_dirent(trans,
+ SPOS(lostfound.bi_inum, inode->bi_dir_offset,
+ dirent_snapshot),
+ k.k->p.snapshot) ?:
+ snapshot_list_add(c, &whiteouts_done, k.k->p.snapshot);
if (ret)
- break;
+ return ret;
} else {
iter.snapshot = k.k->p.snapshot;
child_inode.bi_dir = inode->bi_dir;
@@ -496,11 +483,9 @@ static int reattach_inode(struct btree_trans *trans, struct bch_inode_unpacked *
ret = bch2_inode_write_flags(trans, &iter, &child_inode,
BTREE_UPDATE_internal_snapshot_node);
if (ret)
- break;
+ return ret;
}
}
- darray_exit(&whiteouts_done);
- bch2_trans_iter_exit(trans, &iter);
}
return ret;
@@ -510,7 +495,11 @@ static struct bkey_s_c_dirent dirent_get_by_pos(struct btree_trans *trans,
struct btree_iter *iter,
struct bpos pos)
{
- return bch2_bkey_get_iter_typed(trans, iter, BTREE_ID_dirents, pos, 0, dirent);
+ bch2_trans_iter_init(trans, iter, BTREE_ID_dirents, pos, 0);
+ struct bkey_s_c_dirent d = bch2_bkey_get_typed(iter, dirent);
+ if (bkey_err(d.s_c))
+ bch2_trans_iter_exit(iter);
+ return d;
}
static int remove_backpointer(struct btree_trans *trans,
@@ -534,7 +523,7 @@ static int remove_backpointer(struct btree_trans *trans,
int ret = bkey_err(d) ?:
dirent_points_to_inode(c, d, inode) ?:
bch2_fsck_remove_dirent(trans, d.k->p);
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -585,9 +574,9 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub
new_inode.bi_subvol = subvolid;
int ret = bch2_inode_create(trans, &inode_iter, &new_inode, snapshotid, cpu) ?:
- bch2_btree_iter_traverse(trans, &inode_iter) ?:
+ bch2_btree_iter_traverse(&inode_iter) ?:
bch2_inode_write(trans, &inode_iter, &new_inode);
- bch2_trans_iter_exit(trans, &inode_iter);
+ bch2_trans_iter_exit(&inode_iter);
if (ret)
return ret;
@@ -609,8 +598,7 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub
if (ret)
return ret;
- struct btree_iter iter;
- struct bkey_i_snapshot *s = bch2_bkey_get_mut_typed(trans, &iter,
+ struct bkey_i_snapshot *s = bch2_bkey_get_mut_typed(trans,
BTREE_ID_snapshots, POS(0, snapshotid),
0, snapshot);
ret = PTR_ERR_OR_ZERO(s);
@@ -622,9 +610,8 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub
s->v.subvol = cpu_to_le32(subvolid);
SET_BCH_SNAPSHOT_SUBVOL(&s->v, true);
- bch2_trans_iter_exit(trans, &iter);
- struct bkey_i_snapshot_tree *st = bch2_bkey_get_mut_typed(trans, &iter,
+ struct bkey_i_snapshot_tree *st = bch2_bkey_get_mut_typed(trans,
BTREE_ID_snapshot_trees, POS(0, snapshot_tree),
0, snapshot_tree);
ret = PTR_ERR_OR_ZERO(st);
@@ -634,8 +621,6 @@ static int reconstruct_subvol(struct btree_trans *trans, u32 snapshotid, u32 sub
if (!st->v.master_subvol)
st->v.master_subvol = cpu_to_le32(subvolid);
-
- bch2_trans_iter_exit(trans, &iter);
return 0;
}
@@ -647,11 +632,8 @@ static int reconstruct_inode(struct btree_trans *trans, enum btree_id btree, u32
switch (btree) {
case BTREE_ID_extents: {
- struct btree_iter iter = {};
-
- bch2_trans_iter_init(trans, &iter, BTREE_ID_extents, SPOS(inum, U64_MAX, snapshot), 0);
- struct bkey_s_c k = bch2_btree_iter_peek_prev_min(trans, &iter, POS(inum, 0));
- bch2_trans_iter_exit(trans, &iter);
+ CLASS(btree_iter, iter)(trans, BTREE_ID_extents, SPOS(inum, U64_MAX, snapshot), 0);
+ struct bkey_s_c k = bch2_btree_iter_peek_prev_min(&iter, POS(inum, 0));
int ret = bkey_err(k);
if (ret)
return ret;
@@ -683,11 +665,15 @@ static inline void snapshots_seen_exit(struct snapshots_seen *s)
darray_exit(&s->ids);
}
-static inline void snapshots_seen_init(struct snapshots_seen *s)
+static inline struct snapshots_seen snapshots_seen_init(void)
{
- memset(s, 0, sizeof(*s));
+ return (struct snapshots_seen) {};
}
+DEFINE_CLASS(snapshots_seen, struct snapshots_seen,
+ snapshots_seen_exit(&_T),
+ snapshots_seen_init(), void)
+
static int snapshots_seen_add_inorder(struct bch_fs *c, struct snapshots_seen *s, u32 id)
{
u32 *i;
@@ -815,9 +801,13 @@ static void inode_walker_exit(struct inode_walker *w)
static struct inode_walker inode_walker_init(void)
{
- return (struct inode_walker) { 0, };
+ return (struct inode_walker) {};
}
+DEFINE_CLASS(inode_walker, struct inode_walker,
+ inode_walker_exit(&_T),
+ inode_walker_init(), void)
+
static int add_inode(struct bch_fs *c, struct inode_walker *w,
struct bkey_s_c inode)
{
@@ -841,7 +831,6 @@ static int get_inodes_all_snapshots(struct btree_trans *trans,
struct inode_walker *w, u64 inum)
{
struct bch_fs *c = trans->c;
- struct btree_iter iter;
struct bkey_s_c k;
int ret;
@@ -861,7 +850,6 @@ static int get_inodes_all_snapshots(struct btree_trans *trans,
if (ret)
break;
}
- bch2_trans_iter_exit(trans, &iter);
if (ret)
return ret;
@@ -877,7 +865,6 @@ static int get_visible_inodes(struct btree_trans *trans,
u64 inum)
{
struct bch_fs *c = trans->c;
- struct btree_iter iter;
struct bkey_s_c k;
int ret;
@@ -901,7 +888,6 @@ static int get_visible_inodes(struct btree_trans *trans,
if (ret)
break;
}
- bch2_trans_iter_exit(trans, &iter);
return ret;
}
@@ -917,7 +903,7 @@ lookup_inode_for_snapshot(struct btree_trans *trans, struct inode_walker *w, str
if (!i)
return NULL;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
int ret = 0;
if (fsck_err_on(k.k->p.snapshot != i->inode.bi_snapshot,
@@ -967,10 +953,8 @@ lookup_inode_for_snapshot(struct btree_trans *trans, struct inode_walker *w, str
goto fsck_err;
}
- printbuf_exit(&buf);
return i;
fsck_err:
- printbuf_exit(&buf);
return ERR_PTR(ret);
}
@@ -1004,27 +988,25 @@ int bch2_fsck_update_backpointers(struct btree_trans *trans,
return 0;
struct bkey_i_dirent *d = bkey_i_to_dirent(new);
- struct inode_walker target = inode_walker_init();
- int ret = 0;
+ CLASS(inode_walker, target)();
if (d->v.d_type == DT_SUBVOL) {
bch_err(trans->c, "%s does not support DT_SUBVOL", __func__);
- ret = -BCH_ERR_fsck_repair_unimplemented;
+ return bch_err_throw(trans->c, fsck_repair_unimplemented);
} else {
- ret = get_visible_inodes(trans, &target, s, le64_to_cpu(d->v.d_inum));
+ int ret = get_visible_inodes(trans, &target, s, le64_to_cpu(d->v.d_inum));
if (ret)
- goto err;
+ return ret;
darray_for_each(target.inodes, i) {
i->inode.bi_dir_offset = d->k.p.offset;
ret = __bch2_fsck_write_inode(trans, &i->inode);
if (ret)
- goto err;
+ return ret;
}
+
+ return 0;
}
-err:
- inode_walker_exit(&target);
- return ret;
}
static struct bkey_s_c_dirent inode_get_dirent(struct btree_trans *trans,
@@ -1044,11 +1026,9 @@ static struct bkey_s_c_dirent inode_get_dirent(struct btree_trans *trans,
static int check_inode_deleted_list(struct btree_trans *trans, struct bpos p)
{
- struct btree_iter iter;
- struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_deleted_inodes, p, 0);
- int ret = bkey_err(k) ?: k.k->type == KEY_TYPE_set;
- bch2_trans_iter_exit(trans, &iter);
- return ret;
+ CLASS(btree_iter, iter)(trans, BTREE_ID_deleted_inodes, p, 0);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter);
+ return bkey_err(k) ?: k.k->type == KEY_TYPE_set;
}
static int check_inode_dirent_inode(struct btree_trans *trans,
@@ -1056,7 +1036,7 @@ static int check_inode_dirent_inode(struct btree_trans *trans,
bool *write_inode)
{
struct bch_fs *c = trans->c;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
u32 inode_snapshot = inode->bi_snapshot;
struct btree_iter dirent_iter = {};
@@ -1105,8 +1085,7 @@ static int check_inode_dirent_inode(struct btree_trans *trans,
out:
ret = 0;
fsck_err:
- bch2_trans_iter_exit(trans, &dirent_iter);
- printbuf_exit(&buf);
+ bch2_trans_iter_exit(&dirent_iter);
bch_err_fn(c, ret);
return ret;
}
@@ -1118,7 +1097,7 @@ static int check_inode(struct btree_trans *trans,
struct snapshots_seen *s)
{
struct bch_fs *c = trans->c;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
struct bch_inode_unpacked u;
bool do_update = false;
int ret;
@@ -1234,7 +1213,7 @@ static int check_inode(struct btree_trans *trans,
*/
ret = check_inode_deleted_list(trans, k.k->p);
if (ret < 0)
- goto err_noprint;
+ return ret;
fsck_err_on(!ret,
trans, unlinked_inode_not_on_deleted_list,
@@ -1255,7 +1234,7 @@ static int check_inode(struct btree_trans *trans,
u.bi_inum, u.bi_snapshot)) {
ret = bch2_inode_rm_snapshot(trans, u.bi_inum, iter->pos.snapshot);
bch_err_msg(c, ret, "in fsck deleting inode");
- goto err_noprint;
+ return ret;
}
ret = 0;
}
@@ -1316,40 +1295,37 @@ do_update:
ret = __bch2_fsck_write_inode(trans, &u);
bch_err_msg(c, ret, "in fsck updating inode");
if (ret)
- goto err_noprint;
+ return ret;
}
err:
fsck_err:
bch_err_fn(c, ret);
-err_noprint:
- printbuf_exit(&buf);
return ret;
}
int bch2_check_inodes(struct bch_fs *c)
{
struct bch_inode_unpacked snapshot_root = {};
- struct snapshots_seen s;
- snapshots_seen_init(&s);
+ CLASS(btree_trans, trans)(c);
+ CLASS(snapshots_seen, s)();
+
+ struct progress_indicator_state progress;
+ bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_inodes));
- int ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
+ return for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
POS_MIN,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
- NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
- check_inode(trans, &iter, k, &snapshot_root, &s)));
-
- snapshots_seen_exit(&s);
- bch_err_fn(c, ret);
- return ret;
+ NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
+ progress_update_iter(trans, &progress, &iter);
+ check_inode(trans, &iter, k, &snapshot_root, &s);
+ }));
}
static int find_oldest_inode_needs_reattach(struct btree_trans *trans,
struct bch_inode_unpacked *inode)
{
struct bch_fs *c = trans->c;
- struct btree_iter iter;
struct bkey_s_c k;
int ret = 0;
@@ -1381,7 +1357,6 @@ static int find_oldest_inode_needs_reattach(struct btree_trans *trans,
*inode = parent_inode;
}
- bch2_trans_iter_exit(trans, &iter);
return ret;
}
@@ -1390,7 +1365,7 @@ static int check_unreachable_inode(struct btree_trans *trans,
struct btree_iter *iter,
struct bkey_s_c k)
{
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
int ret = 0;
if (!bkey_is_inode(k.k))
@@ -1414,7 +1389,6 @@ static int check_unreachable_inode(struct btree_trans *trans,
buf.buf)))
ret = reattach_inode(trans, &inode);
fsck_err:
- printbuf_exit(&buf);
return ret;
}
@@ -1430,14 +1404,17 @@ fsck_err:
*/
int bch2_check_unreachable_inodes(struct bch_fs *c)
{
- int ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
+ struct progress_indicator_state progress;
+ bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_inodes));
+
+ CLASS(btree_trans, trans)(c);
+ return for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
POS_MIN,
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
- NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
- check_unreachable_inode(trans, &iter, k)));
- bch_err_fn(c, ret);
- return ret;
+ NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
+ progress_update_iter(trans, &progress, &iter);
+ check_unreachable_inode(trans, &iter, k);
+ }));
}
static inline bool btree_matches_i_mode(enum btree_id btree, unsigned mode)
@@ -1461,14 +1438,13 @@ static int check_key_has_inode(struct btree_trans *trans,
struct bkey_s_c k)
{
struct bch_fs *c = trans->c;
- struct printbuf buf = PRINTBUF;
- struct btree_iter iter2 = {};
+ CLASS(printbuf, buf)();
int ret = PTR_ERR_OR_ZERO(i);
if (ret)
return ret;
if (k.k->type == KEY_TYPE_whiteout)
- goto out;
+ return 0;
bool have_inode = i && !i->whiteout;
@@ -1476,7 +1452,7 @@ static int check_key_has_inode(struct btree_trans *trans,
goto reconstruct;
if (have_inode && btree_matches_i_mode(iter->btree_id, i->inode.bi_mode))
- goto out;
+ return 0;
prt_printf(&buf, ", ");
@@ -1556,8 +1532,6 @@ static int check_key_has_inode(struct btree_trans *trans,
out:
err:
fsck_err:
- bch2_trans_iter_exit(trans, &iter2);
- printbuf_exit(&buf);
bch_err_fn(c, ret);
return ret;
delete:
@@ -1583,7 +1557,6 @@ static int maybe_reconstruct_inum_btree(struct btree_trans *trans,
u64 inum, u32 snapshot,
enum btree_id btree)
{
- struct btree_iter iter;
struct bkey_s_c k;
int ret = 0;
@@ -1594,7 +1567,6 @@ static int maybe_reconstruct_inum_btree(struct btree_trans *trans,
ret = 1;
break;
}
- bch2_trans_iter_exit(trans, &iter);
if (ret <= 0)
return ret;
@@ -1627,23 +1599,28 @@ static int check_i_sectors_notnested(struct btree_trans *trans, struct inode_wal
if (i->inode.bi_sectors == i->count)
continue;
+ CLASS(printbuf, buf)();
+ lockrestart_do(trans,
+ bch2_inum_snapshot_to_path(trans,
+ i->inode.bi_inum,
+ i->inode.bi_snapshot, NULL, &buf));
+
count2 = bch2_count_inode_sectors(trans, w->last_pos.inode, i->inode.bi_snapshot);
if (w->recalculate_sums)
i->count = count2;
if (i->count != count2) {
- bch_err_ratelimited(c, "fsck counted i_sectors wrong for inode %llu:%u: got %llu should be %llu",
- w->last_pos.inode, i->inode.bi_snapshot, i->count, count2);
+ bch_err_ratelimited(c, "fsck counted i_sectors wrong: got %llu should be %llu\n%s",
+ i->count, count2, buf.buf);
i->count = count2;
}
if (fsck_err_on(!(i->inode.bi_flags & BCH_INODE_i_sectors_dirty) &&
i->inode.bi_sectors != i->count,
trans, inode_i_sectors_wrong,
- "inode %llu:%u has incorrect i_sectors: got %llu, should be %llu",
- w->last_pos.inode, i->inode.bi_snapshot,
- i->inode.bi_sectors, i->count)) {
+ "incorrect i_sectors: got %llu, should be %llu\n%s",
+ i->inode.bi_sectors, i->count, buf.buf)) {
i->inode.bi_sectors = i->count;
ret = bch2_fsck_write_inode(trans, &i->inode);
if (ret)
@@ -1686,11 +1663,15 @@ static void extent_ends_exit(struct extent_ends *extent_ends)
darray_exit(&extent_ends->e);
}
-static void extent_ends_init(struct extent_ends *extent_ends)
+static struct extent_ends extent_ends_init(void)
{
- memset(extent_ends, 0, sizeof(*extent_ends));
+ return (struct extent_ends) {};
}
+DEFINE_CLASS(extent_ends, struct extent_ends,
+ extent_ends_exit(&_T),
+ extent_ends_init(), void)
+
static int extent_ends_at(struct bch_fs *c,
struct extent_ends *extent_ends,
struct snapshots_seen *seen,
@@ -1730,17 +1711,17 @@ static int overlapping_extents_found(struct btree_trans *trans,
struct extent_end *extent_end)
{
struct bch_fs *c = trans->c;
- struct printbuf buf = PRINTBUF;
- struct btree_iter iter1, iter2 = {};
+ CLASS(printbuf, buf)();
+ struct btree_iter iter2 = {};
struct bkey_s_c k1, k2;
int ret;
BUG_ON(bkey_le(pos1, bkey_start_pos(&pos2)));
- bch2_trans_iter_init(trans, &iter1, btree, pos1,
- BTREE_ITER_all_snapshots|
- BTREE_ITER_not_extents);
- k1 = bch2_btree_iter_peek_max(trans, &iter1, POS(pos1.inode, U64_MAX));
+ CLASS(btree_iter, iter1)(trans, btree, pos1,
+ BTREE_ITER_all_snapshots|
+ BTREE_ITER_not_extents);
+ k1 = bch2_btree_iter_peek_max(&iter1, POS(pos1.inode, U64_MAX));
ret = bkey_err(k1);
if (ret)
goto err;
@@ -1760,12 +1741,12 @@ static int overlapping_extents_found(struct btree_trans *trans,
goto err;
}
- bch2_trans_copy_iter(trans, &iter2, &iter1);
+ bch2_trans_copy_iter(&iter2, &iter1);
while (1) {
- bch2_btree_iter_advance(trans, &iter2);
+ bch2_btree_iter_advance(&iter2);
- k2 = bch2_btree_iter_peek_max(trans, &iter2, POS(pos1.inode, U64_MAX));
+ k2 = bch2_btree_iter_peek_max(&iter2, POS(pos1.inode, U64_MAX));
ret = bkey_err(k2);
if (ret)
goto err;
@@ -1834,9 +1815,7 @@ static int overlapping_extents_found(struct btree_trans *trans,
}
fsck_err:
err:
- bch2_trans_iter_exit(trans, &iter2);
- bch2_trans_iter_exit(trans, &iter1);
- printbuf_exit(&buf);
+ bch2_trans_iter_exit(&iter2);
return ret;
}
@@ -1893,16 +1872,16 @@ static int check_extent_overbig(struct btree_trans *trans, struct btree_iter *it
bkey_for_each_crc(k.k, ptrs, crc, i)
if (crc_is_encoded(crc) &&
crc.uncompressed_size > encoded_extent_max_sectors) {
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
bch2_bkey_val_to_text(&buf, c, k);
bch_err(c, "overbig encoded extent, please report this:\n %s", buf.buf);
- printbuf_exit(&buf);
}
return 0;
}
+noinline_for_stack
static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
struct bkey_s_c k,
struct inode_walker *inode,
@@ -1911,7 +1890,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
struct disk_reservation *res)
{
struct bch_fs *c = trans->c;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
int ret = 0;
ret = bch2_check_key_has_snapshot(trans, iter, k);
@@ -1965,11 +1944,12 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
"extent type past end of inode %llu:%u, i_size %llu\n%s",
i->inode.bi_inum, i->inode.bi_snapshot, i->inode.bi_size,
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
- ret = bch2_fpunch_snapshot(trans,
- SPOS(i->inode.bi_inum,
- last_block,
- i->inode.bi_snapshot),
- POS(i->inode.bi_inum, U64_MAX));
+ ret = snapshots_seen_add_inorder(c, s, i->inode.bi_snapshot) ?:
+ bch2_fpunch_snapshot(trans,
+ SPOS(i->inode.bi_inum,
+ last_block,
+ i->inode.bi_snapshot),
+ POS(i->inode.bi_inum, U64_MAX));
if (ret)
goto err;
@@ -1979,6 +1959,10 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
}
}
+ ret = check_extent_overbig(trans, iter, k);
+ if (ret)
+ goto err;
+
ret = bch2_trans_commit(trans, res, NULL, BCH_TRANS_COMMIT_no_enospc);
if (ret)
goto err;
@@ -2004,7 +1988,6 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
out:
err:
fsck_err:
- printbuf_exit(&buf);
bch_err_fn(c, ret);
return ret;
}
@@ -2015,49 +1998,48 @@ fsck_err:
*/
int bch2_check_extents(struct bch_fs *c)
{
- struct inode_walker w = inode_walker_init();
- struct snapshots_seen s;
- struct extent_ends extent_ends;
struct disk_reservation res = { 0 };
- snapshots_seen_init(&s);
- extent_ends_init(&extent_ends);
+ CLASS(btree_trans, trans)(c);
+ CLASS(snapshots_seen, s)();
+ CLASS(inode_walker, w)();
+ CLASS(extent_ends, extent_ends)();
+
+ struct progress_indicator_state progress;
+ bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_extents));
- int ret = bch2_trans_run(c,
- for_each_btree_key(trans, iter, BTREE_ID_extents,
+ int ret = for_each_btree_key(trans, iter, BTREE_ID_extents,
POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k, ({
+ progress_update_iter(trans, &progress, &iter);
bch2_disk_reservation_put(c, &res);
- check_extent(trans, &iter, k, &w, &s, &extent_ends, &res) ?:
- check_extent_overbig(trans, &iter, k);
+ check_extent(trans, &iter, k, &w, &s, &extent_ends, &res);
})) ?:
- check_i_sectors_notnested(trans, &w));
+ check_i_sectors_notnested(trans, &w);
bch2_disk_reservation_put(c, &res);
- extent_ends_exit(&extent_ends);
- inode_walker_exit(&w);
- snapshots_seen_exit(&s);
-
- bch_err_fn(c, ret);
return ret;
}
int bch2_check_indirect_extents(struct bch_fs *c)
{
+ CLASS(btree_trans, trans)(c);
struct disk_reservation res = { 0 };
- int ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter, BTREE_ID_reflink,
+ struct progress_indicator_state progress;
+ bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_reflink));
+
+ int ret = for_each_btree_key_commit(trans, iter, BTREE_ID_reflink,
POS_MIN,
BTREE_ITER_prefetch, k,
&res, NULL,
BCH_TRANS_COMMIT_no_enospc, ({
+ progress_update_iter(trans, &progress, &iter);
bch2_disk_reservation_put(c, &res);
check_extent_overbig(trans, &iter, k);
- })));
+ }));
bch2_disk_reservation_put(c, &res);
- bch_err_fn(c, ret);
return ret;
}
@@ -2116,7 +2098,6 @@ static int check_subdir_dirents_count(struct btree_trans *trans, struct inode_wa
/* find a subvolume that's a descendent of @snapshot: */
static int find_snapshot_subvol(struct btree_trans *trans, u32 snapshot, u32 *subvolid)
{
- struct btree_iter iter;
struct bkey_s_c k;
int ret;
@@ -2126,16 +2107,13 @@ static int find_snapshot_subvol(struct btree_trans *trans, u32 snapshot, u32 *su
struct bkey_s_c_subvolume s = bkey_s_c_to_subvolume(k);
if (bch2_snapshot_is_ancestor(trans->c, le32_to_cpu(s.v->snapshot), snapshot)) {
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
*subvolid = k.k->p.offset;
- goto found;
+ return 0;
}
}
- if (!ret)
- ret = -ENOENT;
-found:
- bch2_trans_iter_exit(trans, &iter);
- return ret;
+
+ return ret ?: -ENOENT;
}
noinline_for_stack
@@ -2143,14 +2121,13 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
struct bkey_s_c_dirent d)
{
struct bch_fs *c = trans->c;
- struct btree_iter subvol_iter = {};
struct bch_inode_unpacked subvol_root;
u32 parent_subvol = le32_to_cpu(d.v->d_parent_subvol);
u32 target_subvol = le32_to_cpu(d.v->d_child_subvol);
u32 parent_snapshot;
u32 new_parent_subvol = 0;
u64 parent_inum;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
int ret = 0;
ret = subvol_lookup(trans, parent_subvol, &parent_snapshot, &parent_inum);
@@ -2195,26 +2172,23 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
struct bkey_i_dirent *new_dirent = bch2_bkey_make_mut_typed(trans, iter, &d.s_c, 0, dirent);
ret = PTR_ERR_OR_ZERO(new_dirent);
if (ret)
- goto err;
+ return ret;
new_dirent->v.d_parent_subvol = cpu_to_le32(new_parent_subvol);
}
- struct bkey_s_c_subvolume s =
- bch2_bkey_get_iter_typed(trans, &subvol_iter,
- BTREE_ID_subvolumes, POS(0, target_subvol),
- 0, subvolume);
+ CLASS(btree_iter, subvol_iter)(trans, BTREE_ID_subvolumes, POS(0, target_subvol), 0);
+ struct bkey_s_c_subvolume s = bch2_bkey_get_typed(&subvol_iter, subvolume);
ret = bkey_err(s.s_c);
if (ret && !bch2_err_matches(ret, ENOENT))
- goto err;
+ return ret;
if (ret) {
if (fsck_err(trans, dirent_to_missing_subvol,
"dirent points to missing subvolume\n%s",
(bch2_bkey_val_to_text(&buf, c, d.s_c), buf.buf)))
return bch2_fsck_remove_dirent(trans, d.k->p);
- ret = 0;
- goto out;
+ return 0;
}
if (le32_to_cpu(s.v->fs_path_parent) != parent_subvol) {
@@ -2226,7 +2200,7 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
ret = bch2_inum_to_path(trans, (subvol_inum) { s.k->p.offset,
le64_to_cpu(s.v->inode) }, &buf);
if (ret)
- goto err;
+ return ret;
prt_newline(&buf);
bch2_bkey_val_to_text(&buf, c, s.s_c);
@@ -2235,7 +2209,7 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
bch2_bkey_make_mut_typed(trans, &subvol_iter, &s.s_c, 0, subvolume);
ret = PTR_ERR_OR_ZERO(n);
if (ret)
- goto err;
+ return ret;
n->v.fs_path_parent = cpu_to_le32(parent_subvol);
}
@@ -2247,12 +2221,11 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
ret = bch2_inode_find_by_inum_snapshot(trans, target_inum, target_snapshot,
&subvol_root, 0);
if (ret && !bch2_err_matches(ret, ENOENT))
- goto err;
+ return ret;
if (ret) {
bch_err(c, "subvol %u points to missing inode root %llu", target_subvol, target_inum);
- ret = bch_err_throw(c, fsck_repair_unimplemented);
- goto err;
+ return bch_err_throw(c, fsck_repair_unimplemented);
}
if (fsck_err_on(!ret && parent_subvol != subvol_root.bi_parent_subvol,
@@ -2264,17 +2237,13 @@ static int check_dirent_to_subvol(struct btree_trans *trans, struct btree_iter *
subvol_root.bi_snapshot = le32_to_cpu(s.v->snapshot);
ret = __bch2_fsck_write_inode(trans, &subvol_root);
if (ret)
- goto err;
+ return ret;
}
ret = bch2_check_dirent_target(trans, iter, d, &subvol_root, true);
if (ret)
- goto err;
-out:
-err:
+ return ret;
fsck_err:
- bch2_trans_iter_exit(trans, &subvol_iter);
- printbuf_exit(&buf);
return ret;
}
@@ -2288,39 +2257,37 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
{
struct bch_fs *c = trans->c;
struct inode_walker_entry *i;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
int ret = 0;
ret = bch2_check_key_has_snapshot(trans, iter, k);
- if (ret) {
- ret = ret < 0 ? ret : 0;
- goto out;
- }
+ if (ret)
+ return ret < 0 ? ret : 0;
ret = snapshots_seen_update(c, s, iter->btree_id, k.k->p);
if (ret)
- goto err;
+ return ret;
if (k.k->type == KEY_TYPE_whiteout)
- goto out;
+ return 0;
if (dir->last_pos.inode != k.k->p.inode && dir->have_inodes) {
ret = check_subdir_dirents_count(trans, dir);
if (ret)
- goto err;
+ return ret;
}
i = walk_inode(trans, dir, k);
ret = PTR_ERR_OR_ZERO(i);
- if (ret < 0)
- goto err;
+ if (ret)
+ return ret;
ret = check_key_has_inode(trans, iter, dir, i, k);
if (ret)
- goto err;
+ return ret;
if (!i || i->whiteout)
- goto out;
+ return 0;
if (dir->first_this_inode)
*hash_info = bch2_hash_info_init(c, &i->inode);
@@ -2331,15 +2298,11 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
ret = bch2_str_hash_check_key(trans, s, &bch2_dirent_hash_desc, hash_info,
iter, k, need_second_pass);
if (ret < 0)
- goto err;
- if (ret) {
- /* dirent has been deleted */
- ret = 0;
- goto out;
- }
-
+ return ret;
+ if (ret)
+ return 0; /* dirent has been deleted */
if (k.k->type != KEY_TYPE_dirent)
- goto out;
+ return 0;
struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
@@ -2364,13 +2327,13 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
d.v->d_type, &name, NULL, target);
ret = PTR_ERR_OR_ZERO(new_d);
if (ret)
- goto out;
+ return ret;
new_d->k.p.inode = d.k->p.inode;
new_d->k.p.snapshot = d.k->p.snapshot;
struct btree_iter dup_iter = {};
- ret = bch2_hash_delete_at(trans,
+ return bch2_hash_delete_at(trans,
bch2_dirent_hash_desc, hash_info, iter,
BTREE_UPDATE_internal_snapshot_node) ?:
bch2_str_hash_repair_key(trans, s,
@@ -2378,17 +2341,16 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
iter, bkey_i_to_s_c(&new_d->k_i),
&dup_iter, bkey_s_c_null,
need_second_pass);
- goto out;
}
if (d.v->d_type == DT_SUBVOL) {
ret = check_dirent_to_subvol(trans, iter, d);
if (ret)
- goto err;
+ return ret;
} else {
ret = get_visible_inodes(trans, target, s, le64_to_cpu(d.v->d_inum));
if (ret)
- goto err;
+ return ret;
if (!target->inodes.nr) {
ret = maybe_reconstruct_inum(trans, le64_to_cpu(d.v->d_inum),
@@ -2405,13 +2367,13 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
buf.buf))) {
ret = bch2_fsck_remove_dirent(trans, d.k->p);
if (ret)
- goto err;
+ return ret;
}
darray_for_each(target->inodes, i) {
ret = bch2_check_dirent_target(trans, iter, d, &i->inode, true);
if (ret)
- goto err;
+ return ret;
}
darray_for_each(target->deletes, i)
@@ -2422,36 +2384,37 @@ static int check_dirent(struct btree_trans *trans, struct btree_iter *iter,
(printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k),
buf.buf))) {
- struct btree_iter delete_iter;
- bch2_trans_iter_init(trans, &delete_iter,
+ CLASS(btree_iter, delete_iter)(trans,
BTREE_ID_dirents,
SPOS(k.k->p.inode, k.k->p.offset, *i),
BTREE_ITER_intent);
- ret = bch2_btree_iter_traverse(trans, &delete_iter) ?:
+ ret = bch2_btree_iter_traverse(&delete_iter) ?:
bch2_hash_delete_at(trans, bch2_dirent_hash_desc,
hash_info,
&delete_iter,
BTREE_UPDATE_internal_snapshot_node);
- bch2_trans_iter_exit(trans, &delete_iter);
if (ret)
- goto err;
+ return ret;
}
}
+ /*
+ * Cannot access key values after doing a transaction commit without
+ * revalidating:
+ */
+ bool have_dir = d.v->d_type == DT_DIR;
+
ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
if (ret)
- goto err;
+ return ret;
for_each_visible_inode(c, s, dir, d.k->p.snapshot, i) {
- if (d.v->d_type == DT_DIR)
+ if (have_dir)
i->count++;
i->i_size += bkey_bytes(d.k);
}
-out:
-err:
fsck_err:
- printbuf_exit(&buf);
return ret;
}
@@ -2461,23 +2424,26 @@ fsck_err:
*/
int bch2_check_dirents(struct bch_fs *c)
{
- struct inode_walker dir = inode_walker_init();
- struct inode_walker target = inode_walker_init();
- struct snapshots_seen s;
struct bch_hash_info hash_info;
+ CLASS(btree_trans, trans)(c);
+ CLASS(snapshots_seen, s)();
+ CLASS(inode_walker, dir)();
+ CLASS(inode_walker, target)();
+ struct progress_indicator_state progress;
bool need_second_pass = false, did_second_pass = false;
int ret;
-
- snapshots_seen_init(&s);
again:
- ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter, BTREE_ID_dirents,
+ bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_dirents));
+
+ ret = for_each_btree_key_commit(trans, iter, BTREE_ID_dirents,
POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
- NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
+ NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
+ progress_update_iter(trans, &progress, &iter);
check_dirent(trans, &iter, k, &hash_info, &dir, &target, &s,
- &need_second_pass)) ?:
- check_subdir_count_notnested(trans, &dir));
+ &need_second_pass);
+ })) ?:
+ check_subdir_count_notnested(trans, &dir);
if (!ret && need_second_pass && !did_second_pass) {
bch_info(c, "check_dirents requires second pass");
@@ -2490,10 +2456,6 @@ again:
ret = -EINVAL;
}
- snapshots_seen_exit(&s);
- inode_walker_exit(&dir);
- inode_walker_exit(&target);
- bch_err_fn(c, ret);
return ret;
}
@@ -2536,21 +2498,22 @@ static int check_xattr(struct btree_trans *trans, struct btree_iter *iter,
*/
int bch2_check_xattrs(struct bch_fs *c)
{
- struct inode_walker inode = inode_walker_init();
struct bch_hash_info hash_info;
- int ret = 0;
+ CLASS(btree_trans, trans)(c);
+ CLASS(inode_walker, inode)();
- ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter, BTREE_ID_xattrs,
+ struct progress_indicator_state progress;
+ bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_xattrs));
+
+ int ret = for_each_btree_key_commit(trans, iter, BTREE_ID_xattrs,
POS(BCACHEFS_ROOT_INO, 0),
BTREE_ITER_prefetch|BTREE_ITER_all_snapshots,
k,
NULL, NULL,
- BCH_TRANS_COMMIT_no_enospc,
- check_xattr(trans, &iter, k, &hash_info, &inode)));
-
- inode_walker_exit(&inode);
- bch_err_fn(c, ret);
+ BCH_TRANS_COMMIT_no_enospc, ({
+ progress_update_iter(trans, &progress, &iter);
+ check_xattr(trans, &iter, k, &hash_info, &inode);
+ }));
return ret;
}
@@ -2615,23 +2578,23 @@ fsck_err:
/* Get root directory, create if it doesn't exist: */
int bch2_check_root(struct bch_fs *c)
{
- int ret = bch2_trans_commit_do(c, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
- check_root_trans(trans));
- bch_err_fn(c, ret);
- return ret;
+ CLASS(btree_trans, trans)(c);
+ return commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
+ check_root_trans(trans));
}
static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter, struct bkey_s_c k)
{
struct bch_fs *c = trans->c;
- struct btree_iter parent_iter = {};
- darray_u32 subvol_path = {};
- struct printbuf buf = PRINTBUF;
+ CLASS(darray_u32, subvol_path)();
+ CLASS(printbuf, buf)();
int ret = 0;
if (k.k->type != KEY_TYPE_subvolume)
return 0;
+ CLASS(btree_iter, parent_iter)(trans, BTREE_ID_subvolumes, POS_MIN, 0);
+
subvol_inum start = {
.subvol = k.k->p.offset,
.inum = le64_to_cpu(bkey_s_c_to_subvolume(k).v->inode),
@@ -2640,7 +2603,7 @@ static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter,
while (k.k->p.offset != BCACHEFS_ROOT_SUBVOL) {
ret = darray_push(&subvol_path, k.k->p.offset);
if (ret)
- goto err;
+ return ret;
struct bkey_s_c_subvolume s = bkey_s_c_to_subvolume(k);
@@ -2659,20 +2622,18 @@ static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter,
ret = bch2_inum_to_path(trans, start, &buf);
if (ret)
- goto err;
+ return ret;
if (fsck_err(trans, subvol_loop, "%s", buf.buf))
ret = reattach_subvol(trans, s);
break;
}
- bch2_trans_iter_exit(trans, &parent_iter);
- bch2_trans_iter_init(trans, &parent_iter,
- BTREE_ID_subvolumes, POS(0, parent), 0);
- k = bch2_btree_iter_peek_slot(trans, &parent_iter);
+ bch2_btree_iter_set_pos(&parent_iter, POS(0, parent));
+ k = bch2_btree_iter_peek_slot(&parent_iter);
ret = bkey_err(k);
if (ret)
- goto err;
+ return ret;
if (fsck_err_on(k.k->type != KEY_TYPE_subvolume,
trans, subvol_unreachable,
@@ -2680,52 +2641,49 @@ static int check_subvol_path(struct btree_trans *trans, struct btree_iter *iter,
(printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, s.s_c),
buf.buf))) {
- ret = reattach_subvol(trans, s);
- break;
+ return reattach_subvol(trans, s);
}
}
fsck_err:
-err:
- printbuf_exit(&buf);
- darray_exit(&subvol_path);
- bch2_trans_iter_exit(trans, &parent_iter);
return ret;
}
int bch2_check_subvolume_structure(struct bch_fs *c)
{
- int ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter,
+ CLASS(btree_trans, trans)(c);
+
+ struct progress_indicator_state progress;
+ bch2_progress_init(&progress, c, BIT_ULL(BTREE_ID_subvolumes));
+
+ return for_each_btree_key_commit(trans, iter,
BTREE_ID_subvolumes, POS_MIN, BTREE_ITER_prefetch, k,
- NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
- check_subvol_path(trans, &iter, k)));
- bch_err_fn(c, ret);
- return ret;
+ NULL, NULL, BCH_TRANS_COMMIT_no_enospc, ({
+ progress_update_iter(trans, &progress, &iter);
+ check_subvol_path(trans, &iter, k);
+ }));
}
static int bch2_bi_depth_renumber_one(struct btree_trans *trans,
u64 inum, u32 snapshot,
u32 new_depth)
{
- struct btree_iter iter;
- struct bkey_s_c k = bch2_bkey_get_iter(trans, &iter, BTREE_ID_inodes,
- SPOS(0, inum, snapshot), 0);
+ CLASS(btree_iter, iter)(trans, BTREE_ID_inodes, SPOS(0, inum, snapshot), 0);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(&iter);
struct bch_inode_unpacked inode;
int ret = bkey_err(k) ?:
!bkey_is_inode(k.k) ? -BCH_ERR_ENOENT_inode
: bch2_inode_unpack(k, &inode);
if (ret)
- goto err;
+ return ret;
if (inode.bi_depth != new_depth) {
inode.bi_depth = new_depth;
- ret = __bch2_fsck_write_inode(trans, &inode) ?:
- bch2_trans_commit(trans, NULL, NULL, 0);
+ return __bch2_fsck_write_inode(trans, &inode) ?:
+ bch2_trans_commit(trans, NULL, NULL, 0);
}
-err:
- bch2_trans_iter_exit(trans, &iter);
- return ret;
+
+ return 0;
}
static int bch2_bi_depth_renumber(struct btree_trans *trans, darray_u64 *path,
@@ -2750,9 +2708,8 @@ static int bch2_bi_depth_renumber(struct btree_trans *trans, darray_u64 *path,
static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
{
struct bch_fs *c = trans->c;
- struct btree_iter inode_iter = {};
- darray_u64 path = {};
- struct printbuf buf = PRINTBUF;
+ CLASS(darray_u64, path)();
+ CLASS(printbuf, buf)();
u32 snapshot = inode_k.k->p.snapshot;
bool redo_bi_depth = false;
u32 min_bi_depth = U32_MAX;
@@ -2765,6 +2722,8 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
if (ret)
return ret;
+ CLASS(btree_iter, inode_iter)(trans, BTREE_ID_inodes, POS_MIN, 0);
+
/*
* If we're running full fsck, check_dirents() will have already ran,
* and we shouldn't see any missing backpointers here - otherwise that's
@@ -2782,7 +2741,7 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
goto out;
if (!ret && (ret = dirent_points_to_inode(c, d, &inode)))
- bch2_trans_iter_exit(trans, &dirent_iter);
+ bch2_trans_iter_exit(&dirent_iter);
if (bch2_err_matches(ret, ENOENT)) {
printbuf_reset(&buf);
@@ -2792,15 +2751,14 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
goto out;
}
- bch2_trans_iter_exit(trans, &dirent_iter);
+ bch2_trans_iter_exit(&dirent_iter);
ret = darray_push(&path, inode.bi_inum);
if (ret)
return ret;
- bch2_trans_iter_exit(trans, &inode_iter);
- inode_k = bch2_bkey_get_iter(trans, &inode_iter, BTREE_ID_inodes,
- SPOS(0, inode.bi_dir, snapshot), 0);
+ bch2_btree_iter_set_pos(&inode_iter, SPOS(0, inode.bi_dir, snapshot));
+ inode_k = bch2_btree_iter_peek_slot(&inode_iter);
struct bch_inode_unpacked parent_inode;
ret = bkey_err(inode_k) ?:
@@ -2857,9 +2815,6 @@ static int check_path_loop(struct btree_trans *trans, struct bkey_s_c inode_k)
ret = bch2_bi_depth_renumber(trans, &path, snapshot, min_bi_depth);
out:
fsck_err:
- bch2_trans_iter_exit(trans, &inode_iter);
- darray_exit(&path);
- printbuf_exit(&buf);
bch_err_fn(c, ret);
return ret;
}
@@ -2870,8 +2825,8 @@ fsck_err:
*/
int bch2_check_directory_structure(struct bch_fs *c)
{
- int ret = bch2_trans_run(c,
- for_each_btree_key_reverse_commit(trans, iter, BTREE_ID_inodes, POS_MIN,
+ CLASS(btree_trans, trans)(c);
+ return for_each_btree_key_reverse_commit(trans, iter, BTREE_ID_inodes, POS_MIN,
BTREE_ITER_intent|
BTREE_ITER_prefetch|
BTREE_ITER_all_snapshots, k,
@@ -2883,10 +2838,7 @@ int bch2_check_directory_structure(struct bch_fs *c)
continue;
check_path_loop(trans, k);
- })));
-
- bch_err_fn(c, ret);
- return ret;
+ }));
}
struct nlink_table {
@@ -2970,8 +2922,8 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c,
struct nlink_table *t,
u64 start, u64 *end)
{
- int ret = bch2_trans_run(c,
- for_each_btree_key(trans, iter, BTREE_ID_inodes,
+ CLASS(btree_trans, trans)(c);
+ int ret = for_each_btree_key(trans, iter, BTREE_ID_inodes,
POS(0, start),
BTREE_ITER_intent|
BTREE_ITER_prefetch|
@@ -3006,7 +2958,7 @@ static int check_nlinks_find_hardlinks(struct bch_fs *c,
break;
}
0;
- })));
+ }));
bch_err_fn(c, ret);
return ret;
@@ -3016,12 +2968,10 @@ noinline_for_stack
static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links,
u64 range_start, u64 range_end)
{
- struct snapshots_seen s;
-
- snapshots_seen_init(&s);
+ CLASS(btree_trans, trans)(c);
+ CLASS(snapshots_seen, s)();
- int ret = bch2_trans_run(c,
- for_each_btree_key(trans, iter, BTREE_ID_dirents, POS_MIN,
+ int ret = for_each_btree_key(trans, iter, BTREE_ID_dirents, POS_MIN,
BTREE_ITER_intent|
BTREE_ITER_prefetch|
BTREE_ITER_all_snapshots, k, ({
@@ -3038,9 +2988,7 @@ static int check_nlinks_walk_dirents(struct bch_fs *c, struct nlink_table *links
le64_to_cpu(d.v->d_inum), d.k->p.snapshot);
}
0;
- })));
-
- snapshots_seen_exit(&s);
+ }));
bch_err_fn(c, ret);
return ret;
@@ -3094,14 +3042,14 @@ static int check_nlinks_update_hardlinks(struct bch_fs *c,
struct nlink_table *links,
u64 range_start, u64 range_end)
{
+ CLASS(btree_trans, trans)(c);
size_t idx = 0;
- int ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
+ int ret = for_each_btree_key_commit(trans, iter, BTREE_ID_inodes,
POS(0, range_start),
BTREE_ITER_intent|BTREE_ITER_prefetch|BTREE_ITER_all_snapshots, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
- check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end)));
+ check_nlinks_update_inode(trans, &iter, k, links, &idx, range_end));
if (ret < 0) {
bch_err(c, "error in fsck walking inodes: %s", bch2_err_str(ret));
return ret;
@@ -3140,7 +3088,6 @@ int bch2_check_nlinks(struct bch_fs *c)
} while (next_iter_range_start != U64_MAX);
kvfree(links.d);
- bch_err_fn(c, ret);
return ret;
}
@@ -3175,15 +3122,13 @@ int bch2_fix_reflink_p(struct bch_fs *c)
if (c->sb.version >= bcachefs_metadata_version_reflink_p_fix)
return 0;
- int ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter,
+ CLASS(btree_trans, trans)(c);
+ return for_each_btree_key_commit(trans, iter,
BTREE_ID_extents, POS_MIN,
BTREE_ITER_intent|BTREE_ITER_prefetch|
BTREE_ITER_all_snapshots, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
- fix_reflink_p_key(trans, &iter, k)));
- bch_err_fn(c, ret);
- return ret;
+ fix_reflink_p_key(trans, &iter, k));
}
#ifndef NO_BCACHEFS_CHARDEV
@@ -3209,6 +3154,8 @@ static int bch2_fsck_offline_thread_fn(struct thread_with_stdio *stdio)
if (ret)
return ret;
+ thr->c->recovery_task = current;
+
ret = bch2_fs_start(thr->c);
if (ret)
goto err;