Commit 831faabe authored by Gao Xiang's avatar Gao Xiang
Browse files

erofs: improve decompression error reporting



Change the return type of decompress() from `int` to `const char *` to
provide more informative error diagnostics:

 - A NULL return indicates successful decompression;

 - If IS_ERR(ptr) is true, the return value encodes a standard negative
   errno (e.g., -ENOMEM, -EOPNOTSUPP) identifying the specific error;

 - Otherwise, a non-NULL return points to a human-readable error string,
   and the corresponding error code should be treated as -EFSCORRUPTED.

Signed-off-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>
parent 9ae77198
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ struct z_erofs_decompress_req {
struct z_erofs_decompressor {
	int (*config)(struct super_block *sb, struct erofs_super_block *dsb,
		      void *data, int size);
	int (*decompress)(struct z_erofs_decompress_req *rq,
	const char *(*decompress)(struct z_erofs_decompress_req *rq,
				  struct page **pagepool);
	int (*init)(void);
	void (*exit)(void);
+9 −11
Original line number Diff line number Diff line
@@ -235,8 +235,6 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst
					  rq->inputsize, rq->outputsize);

	if (ret != rq->outputsize) {
		erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]",
			  ret, rq->inputsize, inputmargin, rq->outputsize);
		if (ret >= 0)
			memset(out + ret, 0, rq->outputsize - ret);
		ret = -EFSCORRUPTED;
@@ -257,7 +255,7 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst
	return ret;
}

static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
static const char *z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
					  struct page **pagepool)
{
	unsigned int dst_maptype;
@@ -273,14 +271,14 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
		/* general decoding path which can be used for all cases */
		ret = z_erofs_lz4_prepare_dstpages(rq, pagepool);
		if (ret < 0)
			return ret;
			return ERR_PTR(ret);
		if (ret > 0) {
			dst = page_address(*rq->out);
			dst_maptype = 1;
		} else {
			dst = erofs_vm_map_ram(rq->out, rq->outpages);
			if (!dst)
				return -ENOMEM;
				return ERR_PTR(-ENOMEM);
			dst_maptype = 2;
		}
	}
@@ -289,10 +287,10 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
		kunmap_local(dst);
	else if (dst_maptype == 2)
		vm_unmap_ram(dst, rq->outpages);
	return ret;
	return ERR_PTR(ret);
}

static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
static const char *z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
					   struct page **pagepool)
{
	const unsigned int nrpages_in = rq->inpages, nrpages_out = rq->outpages;
@@ -301,7 +299,7 @@ static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
	u8 *kin;

	if (rq->outputsize > rq->inputsize)
		return -EOPNOTSUPP;
		return ERR_PTR(-EOPNOTSUPP);
	if (rq->alg == Z_EROFS_COMPRESSION_INTERLACED) {
		cur = bs - (rq->pageofs_out & (bs - 1));
		pi = (rq->pageofs_in + rq->inputsize - cur) & ~PAGE_MASK;
@@ -341,7 +339,7 @@ static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
		kunmap_local(kin);
	}
	DBG_BUGON(ni > nrpages_in);
	return 0;
	return NULL;
}

int z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx, void **dst,
+4 −6
Original line number Diff line number Diff line
@@ -157,8 +157,6 @@ static int __z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
				break;
			if (zerr == Z_STREAM_END && !rq->outputsize)
				break;
			erofs_err(sb, "failed to decompress %d in[%u] out[%u]",
				  zerr, rq->inputsize, rq->outputsize);
			err = -EFSCORRUPTED;
			break;
		}
@@ -178,7 +176,7 @@ static int __z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
	return err;
}

static int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
static const char *z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
					      struct page **pgpl)
{
#ifdef CONFIG_EROFS_FS_ZIP_ACCEL
@@ -187,11 +185,11 @@ static int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
	if (!rq->partial_decoding) {
		err = z_erofs_crypto_decompress(rq, pgpl);
		if (err != -EOPNOTSUPP)
			return err;
			return ERR_PTR(err);

	}
#endif
	return __z_erofs_deflate_decompress(rq, pgpl);
	return ERR_PTR(__z_erofs_deflate_decompress(rq, pgpl));
}

const struct z_erofs_decompressor z_erofs_deflate_decomp = {
+4 −6
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ static int z_erofs_load_lzma_config(struct super_block *sb,
	return err;
}

static int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
static const char *z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
					   struct page **pgpl)
{
	struct super_block *sb = rq->sb;
@@ -162,7 +162,7 @@ static int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
			min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
	if (err) {
		kunmap_local(dctx.kin);
		return err;
		return ERR_PTR(err);
	}

	/* 2. get an available lzma context */
@@ -207,8 +207,6 @@ static int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
		if (xz_err != XZ_OK) {
			if (xz_err == XZ_STREAM_END && !rq->outputsize)
				break;
			erofs_err(sb, "failed to decompress %d in[%u] out[%u]",
				  xz_err, rq->inputsize, rq->outputsize);
			err = -EFSCORRUPTED;
			break;
		}
@@ -223,7 +221,7 @@ static int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
	z_erofs_lzma_head = strm;
	spin_unlock(&z_erofs_lzma_lock);
	wake_up(&z_erofs_lzma_wq);
	return err;
	return ERR_PTR(err);
}

const struct z_erofs_decompressor z_erofs_lzma_decomp = {
+4 −8
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ static int z_erofs_load_zstd_config(struct super_block *sb,
	return strm ? -ENOMEM : 0;
}

static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
static const char *z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
					   struct page **pgpl)
{
	struct super_block *sb = rq->sb;
@@ -152,7 +152,7 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
			min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
	if (err) {
		kunmap_local(dctx.kin);
		return err;
		return ERR_PTR(err);
	}

	/* 2. get an available ZSTD context */
@@ -191,10 +191,6 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
		if (zstd_is_error(zerr) ||
		    ((rq->outputsize + dctx.avail_out) && (!zerr || (zerr > 0 &&
				!(rq->inputsize + in_buf.size - in_buf.pos))))) {
			erofs_err(sb, "failed to decompress in[%u] out[%u]: %s",
				  rq->inputsize, rq->outputsize,
				  zstd_is_error(zerr) ? zstd_get_error_name(zerr) :
					"unexpected end of stream");
			err = -EFSCORRUPTED;
			break;
		}
@@ -210,7 +206,7 @@ static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
	z_erofs_zstd_head = strm;
	spin_unlock(&z_erofs_zstd_lock);
	wake_up(&z_erofs_zstd_wq);
	return err;
	return ERR_PTR(err);
}

const struct z_erofs_decompressor z_erofs_zstd_decomp = {
Loading