summaryrefslogtreecommitdiff
path: root/fs/bcachefs/backpointers.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/backpointers.c')
-rw-r--r--fs/bcachefs/backpointers.c167
1 files changed, 70 insertions, 97 deletions
diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c
index 77d93beb3c8f..45d3db41225a 100644
--- a/fs/bcachefs/backpointers.c
+++ b/fs/bcachefs/backpointers.c
@@ -108,7 +108,7 @@ static noinline int backpointer_mod_err(struct btree_trans *trans,
bool insert)
{
struct bch_fs *c = trans->c;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
bool will_check = c->recovery.passes_to_run &
BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers);
int ret = 0;
@@ -144,8 +144,8 @@ static noinline int backpointer_mod_err(struct btree_trans *trans,
if (!will_check && __bch2_inconsistent_error(c, &buf))
ret = bch_err_throw(c, erofs_unfixed_errors);
- bch_err(c, "%s", buf.buf);
- printbuf_exit(&buf);
+ if (buf.buf)
+ bch_err(c, "%s", buf.buf);
return ret;
}
@@ -154,12 +154,10 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
struct bkey_i_backpointer *bp,
bool insert)
{
- struct btree_iter bp_iter;
- struct bkey_s_c k = bch2_bkey_get_iter(trans, &bp_iter, BTREE_ID_backpointers,
- bp->k.p,
- BTREE_ITER_intent|
- BTREE_ITER_slots|
- BTREE_ITER_with_updates);
+ CLASS(btree_iter, bp_iter)(trans, BTREE_ID_backpointers, bp->k.p,
+ BTREE_ITER_intent|
+ BTREE_ITER_with_updates);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(&bp_iter);
int ret = bkey_err(k);
if (ret)
return ret;
@@ -170,7 +168,7 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
memcmp(bkey_s_c_to_backpointer(k).v, &bp->v, sizeof(bp->v)))) {
ret = backpointer_mod_err(trans, orig_k, bp, k, insert);
if (ret)
- goto err;
+ return ret;
}
if (!insert) {
@@ -178,10 +176,7 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
set_bkey_val_u64s(&bp->k, 0);
}
- ret = bch2_trans_update(trans, &bp_iter, &bp->k_i, 0);
-err:
- bch2_trans_iter_exit(trans, &bp_iter);
- return ret;
+ return bch2_trans_update(trans, &bp_iter, &bp->k_i, 0);
}
static int bch2_backpointer_del(struct btree_trans *trans, struct bpos pos)
@@ -208,7 +203,7 @@ static int backpointer_target_not_found(struct btree_trans *trans,
bool commit)
{
struct bch_fs *c = trans->c;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
int ret = 0;
/*
@@ -244,7 +239,7 @@ static int backpointer_target_not_found(struct btree_trans *trans,
"%s", buf.buf)) {
ret = bch2_backpointer_del(trans, bp.k->p);
if (ret || !commit)
- goto out;
+ return ret;
/*
* Normally, on transaction commit from inside a transaction,
@@ -262,9 +257,7 @@ static int backpointer_target_not_found(struct btree_trans *trans,
*/
ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
}
-out:
fsck_err:
- printbuf_exit(&buf);
return ret;
}
@@ -284,7 +277,7 @@ static struct btree *__bch2_backpointer_get_node(struct btree_trans *trans,
0,
bp.v->level - 1,
0);
- struct btree *b = bch2_btree_iter_peek_node(trans, iter);
+ struct btree *b = bch2_btree_iter_peek_node(iter);
if (IS_ERR_OR_NULL(b))
goto err;
@@ -302,7 +295,7 @@ static struct btree *__bch2_backpointer_get_node(struct btree_trans *trans,
b = ret ? ERR_PTR(ret) : NULL;
}
err:
- bch2_trans_iter_exit(trans, iter);
+ bch2_trans_iter_exit(iter);
return b;
}
@@ -324,9 +317,9 @@ static struct bkey_s_c __bch2_backpointer_get_key(struct btree_trans *trans,
0,
bp.v->level,
iter_flags);
- struct bkey_s_c k = bch2_btree_iter_peek_slot(trans, iter);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(iter);
if (bkey_err(k)) {
- bch2_trans_iter_exit(trans, iter);
+ bch2_trans_iter_exit(iter);
return k;
}
@@ -346,7 +339,7 @@ static struct bkey_s_c __bch2_backpointer_get_key(struct btree_trans *trans,
extent_matches_bp(c, bp.v->btree_id, bp.v->level, k, bp))
return k;
- bch2_trans_iter_exit(trans, iter);
+ bch2_trans_iter_exit(iter);
if (!bp.v->level) {
int ret = backpointer_target_not_found(trans, bp, k, last_flushed, commit);
@@ -386,44 +379,42 @@ static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, st
return 0;
struct bch_fs *c = trans->c;
- struct btree_iter alloc_iter = {};
- struct bkey_s_c alloc_k;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
int ret = 0;
struct bpos bucket;
if (!bp_pos_to_bucket_nodev_noerror(c, k.k->p, &bucket)) {
ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
if (ret)
- goto out;
+ return ret;
if (fsck_err(trans, backpointer_to_missing_device,
"backpointer for missing device:\n%s",
(bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
ret = bch2_backpointer_del(trans, k.k->p);
- goto out;
+ return ret;
}
- alloc_k = bch2_bkey_get_iter(trans, &alloc_iter, BTREE_ID_alloc, bucket, 0);
- ret = bkey_err(alloc_k);
- if (ret)
- goto out;
-
- if (alloc_k.k->type != KEY_TYPE_alloc_v4) {
- ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
+ {
+ CLASS(btree_iter, alloc_iter)(trans, BTREE_ID_alloc, bucket, 0);
+ struct bkey_s_c alloc_k = bch2_btree_iter_peek_slot(&alloc_iter);
+ ret = bkey_err(alloc_k);
if (ret)
- goto out;
+ return ret;
- if (fsck_err(trans, backpointer_to_missing_alloc,
- "backpointer for nonexistent alloc key: %llu:%llu:0\n%s",
- alloc_iter.pos.inode, alloc_iter.pos.offset,
- (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
- ret = bch2_backpointer_del(trans, k.k->p);
+ if (alloc_k.k->type != KEY_TYPE_alloc_v4) {
+ ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
+ if (ret)
+ return ret;
+
+ if (fsck_err(trans, backpointer_to_missing_alloc,
+ "backpointer for nonexistent alloc key: %llu:%llu:0\n%s",
+ alloc_iter.pos.inode, alloc_iter.pos.offset,
+ (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
+ ret = bch2_backpointer_del(trans, k.k->p);
+ }
}
-out:
fsck_err:
- bch2_trans_iter_exit(trans, &alloc_iter);
- printbuf_exit(&buf);
return ret;
}
@@ -434,14 +425,13 @@ int bch2_check_btree_backpointers(struct bch_fs *c)
bch2_bkey_buf_init(&last_flushed);
bkey_init(&last_flushed.k->k);
- int ret = bch2_trans_run(c,
- for_each_btree_key_commit(trans, iter,
+ CLASS(btree_trans, trans)(c);
+ int ret = for_each_btree_key_commit(trans, iter,
BTREE_ID_backpointers, POS_MIN, 0, k,
NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
- bch2_check_backpointer_has_valid_bucket(trans, k, &last_flushed)));
+ bch2_check_backpointer_has_valid_bucket(trans, k, &last_flushed));
bch2_bkey_buf_exit(&last_flushed, c);
- bch_err_fn(c, ret);
return ret;
}
@@ -471,7 +461,7 @@ static int check_extent_checksum(struct btree_trans *trans,
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(extent);
const union bch_extent_entry *entry;
struct extent_ptr_decoded p;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
void *data_buf = NULL;
struct bio *bio = NULL;
size_t bytes;
@@ -530,7 +520,6 @@ err:
kvfree(data_buf);
enumerated_ref_put(&ca->io_ref[READ],
BCH_DEV_READ_REF_check_extent_checksums);
- printbuf_exit(&buf);
return ret;
}
@@ -541,32 +530,30 @@ static int check_bp_exists(struct btree_trans *trans,
{
struct bch_fs *c = trans->c;
struct btree_iter other_extent_iter = {};
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
if (bpos_lt(bp->k.p, s->bp_start) ||
bpos_gt(bp->k.p, s->bp_end))
return 0;
- struct btree_iter bp_iter;
- struct bkey_s_c bp_k = bch2_bkey_get_iter(trans, &bp_iter, BTREE_ID_backpointers, bp->k.p, 0);
+ CLASS(btree_iter, bp_iter)(trans, BTREE_ID_backpointers, bp->k.p, 0);
+ struct bkey_s_c bp_k = bch2_btree_iter_peek_slot(&bp_iter);
int ret = bkey_err(bp_k);
if (ret)
- goto err;
+ return ret;
if (bp_k.k->type != KEY_TYPE_backpointer ||
memcmp(bkey_s_c_to_backpointer(bp_k).v, &bp->v, sizeof(bp->v))) {
ret = bch2_btree_write_buffer_maybe_flush(trans, orig_k, &s->last_flushed);
if (ret)
- goto err;
+ return ret;
goto check_existing_bp;
}
out:
err:
fsck_err:
- bch2_trans_iter_exit(trans, &other_extent_iter);
- bch2_trans_iter_exit(trans, &bp_iter);
- printbuf_exit(&buf);
+ bch2_trans_iter_exit(&other_extent_iter);
return ret;
check_existing_bp:
/* Do we have a backpointer for a different extent? */
@@ -726,13 +713,13 @@ static int check_btree_root_to_backpointers(struct btree_trans *trans,
retry:
bch2_trans_node_iter_init(trans, &iter, btree_id, POS_MIN,
0, bch2_btree_id_root(c, btree_id)->b->c.level, 0);
- b = bch2_btree_iter_peek_node(trans, &iter);
+ b = bch2_btree_iter_peek_node(&iter);
ret = PTR_ERR_OR_ZERO(b);
if (ret)
goto err;
if (b != btree_node_root(c, b)) {
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
goto retry;
}
@@ -741,7 +728,7 @@ retry:
k = bkey_i_to_s_c(&b->key);
ret = check_extent_to_backpointers(trans, s, btree_id, b->c.level + 1, k);
err:
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -841,6 +828,7 @@ static int bch2_check_extents_to_backpointers_pass(struct btree_trans *trans,
check_extent_to_backpointers(trans, s, btree_id, level, k) ?:
bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
}));
+ bch2_trans_iter_exit(&iter);
if (ret)
return ret;
@@ -895,11 +883,10 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
u32 sectors[ALLOC_SECTORS_NR];
memset(sectors, 0, sizeof(sectors));
- struct bch_dev *ca = bch2_dev_bucket_tryget_noerror(trans->c, alloc_k.k->p);
+ CLASS(bch2_dev_bucket_tryget_noerror, ca)(trans->c, alloc_k.k->p);
if (!ca)
return 0;
- struct btree_iter iter;
struct bkey_s_c bp_k;
int ret = 0;
for_each_btree_key_max_norestart(trans, iter, BTREE_ID_backpointers,
@@ -915,7 +902,7 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
bp.v->pad)) {
ret = bch2_backpointer_del(trans, bp_k.k->p);
if (ret)
- break;
+ return ret;
need_commit = true;
continue;
@@ -930,14 +917,13 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
sectors[alloc_counter] += bp.v->bucket_len;
};
- bch2_trans_iter_exit(trans, &iter);
if (ret)
- goto err;
+ return ret;
if (need_commit) {
ret = bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
if (ret)
- goto err;
+ return ret;
}
if (sectors[ALLOC_dirty] != a->dirty_sectors ||
@@ -946,15 +932,14 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_backpointer_bucket_gen) {
ret = bch2_backpointers_maybe_flush(trans, alloc_k, last_flushed);
if (ret)
- goto err;
+ return ret;
}
if (sectors[ALLOC_dirty] > a->dirty_sectors ||
sectors[ALLOC_cached] > a->cached_sectors ||
sectors[ALLOC_stripe] > a->stripe_sectors) {
- ret = check_bucket_backpointers_to_extents(trans, ca, alloc_k.k->p) ?:
+ return check_bucket_backpointers_to_extents(trans, ca, alloc_k.k->p) ?:
bch_err_throw(c, transaction_restart_nested);
- goto err;
}
bool empty = (sectors[ALLOC_dirty] +
@@ -970,9 +955,8 @@ static int check_bucket_backpointer_mismatch(struct btree_trans *trans, struct b
*had_mismatch = true;
}
-err:
- bch2_dev_put(ca);
- return ret;
+
+ return 0;
}
static bool backpointer_node_has_missing(struct bch_fs *c, struct bkey_s_c k)
@@ -1024,7 +1008,7 @@ static int btree_node_get_and_pin(struct btree_trans *trans, struct bkey_i *k,
{
struct btree_iter iter;
bch2_trans_node_iter_init(trans, &iter, btree, k->k.p, 0, level, 0);
- struct btree *b = bch2_btree_iter_peek_node(trans, &iter);
+ struct btree *b = bch2_btree_iter_peek_node(&iter);
int ret = PTR_ERR_OR_ZERO(b);
if (ret)
goto err;
@@ -1032,7 +1016,7 @@ static int btree_node_get_and_pin(struct btree_trans *trans, struct bkey_i *k,
if (b)
bch2_node_pin(trans->c, b);
err:
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -1068,6 +1052,7 @@ static int bch2_pin_backpointer_nodes_with_missing(struct btree_trans *trans,
bch2_btree_node_prefetch(trans, path, tmp.k, path->btree_id, path->level - 1);
}));
+ bch2_trans_iter_exit(&iter);
if (ret)
return ret;
@@ -1097,6 +1082,7 @@ static int bch2_pin_backpointer_nodes_with_missing(struct btree_trans *trans,
ret;
}));
+ bch2_trans_iter_exit(&iter);
if (ret)
return ret;
@@ -1107,7 +1093,7 @@ int bch2_check_extents_to_backpointers(struct bch_fs *c)
{
int ret = 0;
- struct btree_trans *trans = bch2_trans_get(c);
+ CLASS(btree_trans, trans)(c);
struct extents_to_bp_state s = { .bp_start = POS_MIN };
bch2_bkey_buf_init(&s.last_flushed);
@@ -1146,7 +1132,7 @@ int bch2_check_extents_to_backpointers(struct bch_fs *c)
if (!bpos_eq(s.bp_start, POS_MIN) ||
!bpos_eq(s.bp_end, SPOS_MAX)) {
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
prt_str(&buf, "check_extents_to_backpointers(): ");
bch2_bpos_to_text(&buf, s.bp_start);
@@ -1154,7 +1140,6 @@ int bch2_check_extents_to_backpointers(struct bch_fs *c)
bch2_bpos_to_text(&buf, s.bp_end);
bch_verbose(c, "%s", buf.buf);
- printbuf_exit(&buf);
}
ret = bch2_check_extents_to_backpointers_pass(trans, &s);
@@ -1169,11 +1154,8 @@ int bch2_check_extents_to_backpointers(struct bch_fs *c)
bch2_bucket_bitmap_free(&ca->bucket_backpointer_empty);
}
err:
- bch2_trans_put(trans);
bch2_bkey_buf_exit(&s.last_flushed, c);
bch2_btree_cache_unpin(c);
-
- bch_err_fn(c, ret);
return ret;
}
@@ -1182,17 +1164,13 @@ static int check_bucket_backpointer_pos_mismatch(struct btree_trans *trans,
bool *had_mismatch,
struct bkey_buf *last_flushed)
{
- struct btree_iter alloc_iter;
- struct bkey_s_c k = bch2_bkey_get_iter(trans, &alloc_iter,
- BTREE_ID_alloc, bucket,
- BTREE_ITER_cached);
+ CLASS(btree_iter, alloc_iter)(trans, BTREE_ID_alloc, bucket, BTREE_ITER_cached);
+ struct bkey_s_c k = bch2_btree_iter_peek_slot(&alloc_iter);
int ret = bkey_err(k);
if (ret)
return ret;
- ret = check_bucket_backpointer_mismatch(trans, k, had_mismatch, last_flushed);
- bch2_trans_iter_exit(trans, &alloc_iter);
- return ret;
+ return check_bucket_backpointer_mismatch(trans, k, had_mismatch, last_flushed);
}
int bch2_check_bucket_backpointer_mismatch(struct btree_trans *trans,
@@ -1211,7 +1189,7 @@ int bch2_check_bucket_backpointer_mismatch(struct btree_trans *trans,
u64 nr = ca->bucket_backpointer_mismatch.nr;
u64 allowed = copygc ? ca->mi.nbuckets >> 7 : 0;
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
__bch2_log_msg_start(ca->name, &buf);
prt_printf(&buf, "Detected missing backpointers in bucket %llu, now have %llu/%llu with missing\n",
@@ -1222,7 +1200,6 @@ int bch2_check_bucket_backpointer_mismatch(struct btree_trans *trans,
nr < allowed ? RUN_RECOVERY_PASS_ratelimit : 0);
bch2_print_str(c, KERN_ERR, buf.buf);
- printbuf_exit(&buf);
return 0;
}
@@ -1252,7 +1229,7 @@ static int check_one_backpointer(struct btree_trans *trans,
if (ret)
return ret;
- bch2_trans_iter_exit(trans, &iter);
+ bch2_trans_iter_exit(&iter);
return ret;
}
@@ -1299,7 +1276,7 @@ static int bch2_check_backpointers_to_extents_pass(struct btree_trans *trans,
int bch2_check_backpointers_to_extents(struct bch_fs *c)
{
- struct btree_trans *trans = bch2_trans_get(c);
+ CLASS(btree_trans, trans)(c);
struct bbpos start = (struct bbpos) { .btree = 0, .pos = POS_MIN, }, end;
int ret;
@@ -1319,7 +1296,7 @@ int bch2_check_backpointers_to_extents(struct bch_fs *c)
if (bbpos_cmp(start, BBPOS_MIN) ||
bbpos_cmp(end, BBPOS_MAX)) {
- struct printbuf buf = PRINTBUF;
+ CLASS(printbuf, buf)();
prt_str(&buf, "check_backpointers_to_extents(): ");
bch2_bbpos_to_text(&buf, start);
@@ -1327,7 +1304,6 @@ int bch2_check_backpointers_to_extents(struct bch_fs *c)
bch2_bbpos_to_text(&buf, end);
bch_verbose(c, "%s", buf.buf);
- printbuf_exit(&buf);
}
ret = bch2_check_backpointers_to_extents_pass(trans, start, end);
@@ -1336,11 +1312,8 @@ int bch2_check_backpointers_to_extents(struct bch_fs *c)
start = bbpos_successor(end);
}
- bch2_trans_put(trans);
bch2_btree_cache_unpin(c);
-
- bch_err_fn(c, ret);
return ret;
}