mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 04:44:45 +01:00
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>
This commit is contained in:
parent
9ae77198d4
commit
831faabed8
6 changed files with 40 additions and 37 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue