diff options
| author | Gao Xiang <hsiangkao@linux.alibaba.com> | 2025-11-27 15:31:19 +0800 |
|---|---|---|
| committer | Gao Xiang <hsiangkao@linux.alibaba.com> | 2025-11-28 22:00:07 +0800 |
| commit | 831faabed8129246c9802af9ad9581a2c1e9eeb9 (patch) | |
| tree | 4f58c14af78725f3fe51f280caa8eab981a34db6 | |
| parent | 9ae77198d4815c63fc8ebacc659c71d150d1e51b (diff) | |
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: Gao Xiang <hsiangkao@linux.alibaba.com>
| -rw-r--r-- | fs/erofs/compress.h | 4 | ||||
| -rw-r--r-- | fs/erofs/decompressor.c | 20 | ||||
| -rw-r--r-- | fs/erofs/decompressor_deflate.c | 10 | ||||
| -rw-r--r-- | fs/erofs/decompressor_lzma.c | 10 | ||||
| -rw-r--r-- | fs/erofs/decompressor_zstd.c | 12 | ||||
| -rw-r--r-- | fs/erofs/zdata.c | 21 |
6 files changed, 40 insertions, 37 deletions
diff --git a/fs/erofs/compress.h b/fs/erofs/compress.h index 510e922c5193..1ee4ad934c1f 100644 --- a/fs/erofs/compress.h +++ b/fs/erofs/compress.h @@ -23,8 +23,8 @@ 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, - struct page **pagepool); + const char *(*decompress)(struct z_erofs_decompress_req *rq, + struct page **pagepool); int (*init)(void); void (*exit)(void); char *name; diff --git a/fs/erofs/decompressor.c b/fs/erofs/decompressor.c index 2f4cef67cf64..f9d29f43666f 100644 --- a/fs/erofs/decompressor.c +++ b/fs/erofs/decompressor.c @@ -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,8 +255,8 @@ 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, - struct page **pagepool) +static const char *z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, + struct page **pagepool) { unsigned int dst_maptype; void *dst; @@ -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,11 +287,11 @@ 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, - struct page **pagepool) +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; const unsigned int bs = rq->sb->s_blocksize; @@ -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, diff --git a/fs/erofs/decompressor_deflate.c b/fs/erofs/decompressor_deflate.c index 6909b2d529c7..e9c4b740ef89 100644 --- a/fs/erofs/decompressor_deflate.c +++ b/fs/erofs/decompressor_deflate.c @@ -157,8 +157,6 @@ again: 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,8 +176,8 @@ failed_zinit: return err; } -static int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq, - struct page **pgpl) +static const char *z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq, + struct page **pgpl) { #ifdef CONFIG_EROFS_FS_ZIP_ACCEL int err; @@ -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 = { diff --git a/fs/erofs/decompressor_lzma.c b/fs/erofs/decompressor_lzma.c index 832cffb83a66..7784ced90145 100644 --- a/fs/erofs/decompressor_lzma.c +++ b/fs/erofs/decompressor_lzma.c @@ -146,8 +146,8 @@ again: return err; } -static int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq, - struct page **pgpl) +static const char *z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq, + struct page **pgpl) { struct super_block *sb = rq->sb; struct z_erofs_stream_dctx dctx = { .rq = rq, .no = -1, .ni = 0 }; @@ -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 @@ again: 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 @@ again: 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 = { diff --git a/fs/erofs/decompressor_zstd.c b/fs/erofs/decompressor_zstd.c index e38d93bb2104..50fadff89cbc 100644 --- a/fs/erofs/decompressor_zstd.c +++ b/fs/erofs/decompressor_zstd.c @@ -135,8 +135,8 @@ 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, - struct page **pgpl) +static const char *z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, + struct page **pgpl) { struct super_block *sb = rq->sb; struct z_erofs_stream_dctx dctx = { .rq = rq, .no = -1, .ni = 0 }; @@ -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 @@ failed_zinit: 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 = { diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index bc80cfe482f7..461a929e0825 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -1267,12 +1267,13 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, int err) struct erofs_sb_info *const sbi = EROFS_SB(be->sb); struct z_erofs_pcluster *pcl = be->pcl; unsigned int pclusterpages = z_erofs_pclusterpages(pcl); - const struct z_erofs_decompressor *decomp = + const struct z_erofs_decompressor *alg = z_erofs_decomp[pcl->algorithmformat]; + bool try_free = true; int i, j, jtop, err2; struct page *page; bool overlapped; - bool try_free = true; + const char *reason; mutex_lock(&pcl->lock); be->nr_pages = PAGE_ALIGN(pcl->length + pcl->pageofs_out) >> PAGE_SHIFT; @@ -1304,8 +1305,8 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, int err) err2 = z_erofs_parse_in_bvecs(be, &overlapped); if (err2) err = err2; - if (!err) - err = decomp->decompress(&(struct z_erofs_decompress_req) { + if (!err) { + reason = alg->decompress(&(struct z_erofs_decompress_req) { .sb = be->sb, .in = be->compressed_pages, .out = be->decompressed_pages, @@ -1322,6 +1323,18 @@ static int z_erofs_decompress_pcluster(struct z_erofs_backend *be, int err) .gfp = pcl->besteffort ? GFP_KERNEL : GFP_NOWAIT | __GFP_NORETRY }, be->pagepool); + if (IS_ERR(reason)) { + erofs_err(be->sb, "failed to decompress (%s) %ld @ pa %llu size %u => %u", + alg->name, PTR_ERR(reason), pcl->pos, + pcl->pclustersize, pcl->length); + err = PTR_ERR(reason); + } else if (unlikely(reason)) { + erofs_err(be->sb, "failed to decompress (%s) %s @ pa %llu size %u => %u", + alg->name, reason, pcl->pos, + pcl->pclustersize, pcl->length); + err = -EFSCORRUPTED; + } + } /* must handle all compressed pages before actual file pages */ if (pcl->from_meta) { |