__bch2_count_fsck_err(c, id, buf->buf, &repeat, &print, &suppress);
- int ret = bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations);
+ int ret = bch2_run_explicit_recovery_pass_printbuf(c, buf,
+ BCH_RECOVERY_PASS_check_allocations);
if (insert) {
print = true;
return PTR_ERR(a);
if (a->v.data_type && type && a->v.data_type != type) {
- bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations);
- log_fsck_err(trans, bucket_metadata_type_mismatch,
- "bucket %llu:%llu gen %u different types of data in same bucket: %s, %s\n"
- "while marking %s",
- iter.pos.inode, iter.pos.offset, a->v.gen,
- bch2_data_type_str(a->v.data_type),
- bch2_data_type_str(type),
- bch2_data_type_str(type));
+ struct printbuf buf = PRINTBUF;
+ bch2_log_msg_start(c, &buf);
+ prt_printf(&buf, "bucket %llu:%llu gen %u different types of data in same bucket: %s, %s\n"
+ "while marking %s\n",
+ iter.pos.inode, iter.pos.offset, a->v.gen,
+ bch2_data_type_str(a->v.data_type),
+ bch2_data_type_str(type),
+ bch2_data_type_str(type));
+
+ bool repeat = false, print = true, suppress = false;
+ bch2_count_fsck_err(c, bucket_metadata_type_mismatch, buf.buf,
+ &repeat, &print, &suppress);
+
+ bch2_run_explicit_recovery_pass_printbuf(c, &buf,
+ BCH_RECOVERY_PASS_check_allocations);
+
+ if (suppress)
+ prt_printf(&buf, "Ratelimiting new instances of previous error\n");
+ if (print)
+ bch2_print_string_as_lines(KERN_ERR, buf.buf);
+ printbuf_exit(&buf);
ret = -BCH_ERR_metadata_bucket_inconsistency;
goto err;
}
ret = bch2_trans_update(trans, &iter, &a->k_i, 0);
}
err:
-fsck_err:
bch2_trans_iter_exit(trans, &iter);
return ret;
}
__bch2_inconsistent_error(c, out);
return -BCH_ERR_btree_need_topology_repair;
} else {
- return bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_topology) ?:
+ return bch2_run_explicit_recovery_pass_printbuf(c, out, BCH_RECOVERY_PASS_check_topology) ?:
-BCH_ERR_btree_node_read_validate_error;
}
}
/*
* For when we need to rewind recovery passes and run a pass we skipped:
*/
-static int __bch2_run_explicit_recovery_pass(struct bch_fs *c,
+static int __bch2_run_explicit_recovery_pass(struct printbuf *out,
+ struct bch_fs *c,
enum bch_recovery_pass pass)
{
if (c->curr_recovery_pass == ARRAY_SIZE(recovery_pass_fns))
if (pass < BCH_RECOVERY_PASS_set_may_go_rw &&
c->curr_recovery_pass >= BCH_RECOVERY_PASS_set_may_go_rw) {
if (print)
- bch_info(c, "need recovery pass %s (%u), but already rw",
- bch2_recovery_passes[pass], pass);
+ prt_printf(out, "need recovery pass %s (%u), but already rw",
+ bch2_recovery_passes[pass], pass);
return -BCH_ERR_cannot_rewind_recovery;
}
if (print)
- bch_info(c, "running explicit recovery pass %s (%u), currently at %s (%u)",
- bch2_recovery_passes[pass], pass,
- bch2_recovery_passes[c->curr_recovery_pass], c->curr_recovery_pass);
+ prt_printf(out, "running explicit recovery pass %s (%u), currently at %s (%u)",
+ bch2_recovery_passes[pass], pass,
+ bch2_recovery_passes[c->curr_recovery_pass], c->curr_recovery_pass);
c->opts.recovery_passes |= BIT_ULL(pass);
}
}
-int bch2_run_explicit_recovery_pass(struct bch_fs *c,
+int bch2_run_explicit_recovery_pass_printbuf(struct bch_fs *c,
+ struct printbuf *out,
enum bch_recovery_pass pass)
{
+ bch2_printbuf_make_room(out, 1024);
+ out->atomic++;
+
unsigned long flags;
spin_lock_irqsave(&c->recovery_pass_lock, flags);
- int ret = __bch2_run_explicit_recovery_pass(c, pass);
+ int ret = __bch2_run_explicit_recovery_pass(out, c, pass);
spin_unlock_irqrestore(&c->recovery_pass_lock, flags);
+
+ --out->atomic;
+ return ret;
+}
+
+int bch2_run_explicit_recovery_pass(struct bch_fs *c,
+ enum bch_recovery_pass pass)
+{
+ struct printbuf buf = PRINTBUF;
+ bch2_log_msg_start(c, &buf);
+ unsigned len = buf.pos;
+
+ int ret = bch2_run_explicit_recovery_pass_printbuf(c, &buf, pass);
+
+ if (len != buf.pos)
+ bch2_print_string_as_lines(KERN_NOTICE, buf.buf);
+ printbuf_exit(&buf);
return ret;
}
u64 bch2_fsck_recovery_passes(void);
+int bch2_run_explicit_recovery_pass_printbuf(struct bch_fs *,
+ struct printbuf *,
+ enum bch_recovery_pass);
int bch2_run_explicit_recovery_pass(struct bch_fs *, enum bch_recovery_pass);
int bch2_run_explicit_recovery_pass_persistent_locked(struct bch_fs *, enum bch_recovery_pass);
int bch2_run_explicit_recovery_pass_persistent(struct bch_fs *, enum bch_recovery_pass);