Commit 2efbc351 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Improve decompression error messages

Ratelimit them, and use the new bch2_write_op_error() helper that prints
path and file offset.

Reported-by: https://github.com/koverstreet/bcachefs/issues/819


Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent c9c8a17f
Loading
Loading
Loading
Loading
+22 −9
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#include "compress.h"
#include "error.h"
#include "extents.h"
#include "io_write.h"
#include "opts.h"
#include "super-io.h"

@@ -254,11 +255,14 @@ static int __bio_uncompress(struct bch_fs *c, struct bio *src,
	goto out;
}

int bch2_bio_uncompress_inplace(struct bch_fs *c, struct bio *bio,
				struct bch_extent_crc_unpacked *crc)
int bch2_bio_uncompress_inplace(struct bch_write_op *op,
				struct bio *bio)
{
	struct bch_fs *c = op->c;
	struct bch_extent_crc_unpacked *crc = &op->crc;
	struct bbuf data = { NULL };
	size_t dst_len = crc->uncompressed_size << 9;
	int ret = 0;

	/* bio must own its pages: */
	BUG_ON(!bio->bi_vcnt);
@@ -266,17 +270,26 @@ int bch2_bio_uncompress_inplace(struct bch_fs *c, struct bio *bio,

	if (crc->uncompressed_size << 9	> c->opts.encoded_extent_max ||
	    crc->compressed_size << 9	> c->opts.encoded_extent_max) {
		bch_err(c, "error rewriting existing data: extent too big");
		struct printbuf buf = PRINTBUF;
		bch2_write_op_error(&buf, op);
		prt_printf(&buf, "error rewriting existing data: extent too big");
		bch_err_ratelimited(c, "%s", buf.buf);
		printbuf_exit(&buf);
		return -EIO;
	}

	data = __bounce_alloc(c, dst_len, WRITE);

	if (__bio_uncompress(c, bio, data.b, *crc)) {
		if (!c->opts.no_data_io)
			bch_err(c, "error rewriting existing data: decompression error");
		bio_unmap_or_unbounce(c, data);
		return -EIO;
		if (!c->opts.no_data_io) {
			struct printbuf buf = PRINTBUF;
			bch2_write_op_error(&buf, op);
			prt_printf(&buf, "error rewriting existing data: decompression error");
			bch_err_ratelimited(c, "%s", buf.buf);
			printbuf_exit(&buf);
		}
		ret = -EIO;
		goto err;
	}

	/*
@@ -293,9 +306,9 @@ int bch2_bio_uncompress_inplace(struct bch_fs *c, struct bio *bio,
	crc->uncompressed_size	= crc->live_size;
	crc->offset		= 0;
	crc->csum		= (struct bch_csum) { 0, 0 };

err:
	bio_unmap_or_unbounce(c, data);
	return 0;
	return ret;
}

int bch2_bio_uncompress(struct bch_fs *c, struct bio *src,
+2 −2
Original line number Diff line number Diff line
@@ -47,8 +47,8 @@ static inline enum bch_compression_type bch2_compression_opt_to_type(unsigned v)
	return __bch2_compression_opt_to_type[bch2_compression_decode(v).type];
}

int bch2_bio_uncompress_inplace(struct bch_fs *, struct bio *,
				struct bch_extent_crc_unpacked *);
struct bch_write_op;
int bch2_bio_uncompress_inplace(struct bch_write_op *, struct bio *);
int bch2_bio_uncompress(struct bch_fs *, struct bio *, struct bio *,
		       struct bvec_iter, struct bch_extent_crc_unpacked);
unsigned bch2_bio_compress(struct bch_fs *, struct bio *, size_t *,
+2 −2
Original line number Diff line number Diff line
@@ -406,7 +406,7 @@ static void __bch2_write_op_error(struct printbuf *out, struct bch_write_op *op,
		   op->flags & BCH_WRITE_MOVE ? "(internal move)" : "");
}

static void bch2_write_op_error(struct printbuf *out, struct bch_write_op *op)
void bch2_write_op_error(struct printbuf *out, struct bch_write_op *op)
{
	__bch2_write_op_error(out, op, op->pos.offset);
}
@@ -873,7 +873,7 @@ static enum prep_encoded_ret {
		if (bch2_crc_cmp(op->crc.csum, csum) && !c->opts.no_data_io)
			return PREP_ENCODED_CHECKSUM_ERR;

		if (bch2_bio_uncompress_inplace(c, bio, &op->crc))
		if (bch2_bio_uncompress_inplace(op, bio))
			return PREP_ENCODED_ERR;
	}

+2 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ static inline void bch2_latency_acct(struct bch_dev *ca, u64 submit_time, int rw
void bch2_submit_wbio_replicas(struct bch_write_bio *, struct bch_fs *,
			       enum bch_data_type, const struct bkey_i *, bool);

void bch2_write_op_error(struct printbuf *out, struct bch_write_op *op);

#define BCH_WRITE_FLAGS()		\
	x(ALLOC_NOWAIT)			\
	x(CACHED)			\