]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
erofs: enable error reporting for z_erofs_fixup_insize()
authorGao Xiang <hsiangkao@linux.alibaba.com>
Thu, 27 Nov 2025 07:31:22 +0000 (15:31 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Sun, 30 Nov 2025 15:49:32 +0000 (23:49 +0800)
Enable propagation of detailed errors to callers.

Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
fs/erofs/compress.h
fs/erofs/decompressor.c
fs/erofs/decompressor_crypto.c
fs/erofs/decompressor_deflate.c
fs/erofs/decompressor_lzma.c
fs/erofs/decompressor_zstd.c

index 91dbc8bb5ddf34d12dd4893ee66bbb1bd7d32ccc..84c8e52581f47c85e962b1d05ec6b4c4415396a8 100644 (file)
@@ -72,8 +72,8 @@ struct z_erofs_stream_dctx {
 
 const char *z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx,
                                void **dst, void **src, struct page **pgpl);
-int z_erofs_fixup_insize(struct z_erofs_decompress_req *rq, const char *padbuf,
-                        unsigned int padbufsize);
+const char *z_erofs_fixup_insize(struct z_erofs_decompress_req *rq,
+                                const char *padbuf, unsigned int padbufsize);
 int __init z_erofs_init_decompressor(void);
 void z_erofs_exit_decompressor(void);
 int z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
index 638b5f87bd0c7f356196905d5bd262db9ad97de0..d5d0902763917b447186bc5a0b18727510559c0a 100644 (file)
@@ -178,21 +178,21 @@ static void *z_erofs_lz4_handle_overlap(const struct z_erofs_decompress_req *rq,
 }
 
 /*
- * Get the exact inputsize with zero_padding feature.
- *  - For LZ4, it should work if zero_padding feature is on (5.3+);
- *  - For MicroLZMA, it'd be enabled all the time.
+ * Get the exact on-disk size of the compressed data:
+ *  - For LZ4, it should apply if the zero_padding feature is on (5.3+);
+ *  - For others, zero_padding is enabled all the time.
  */
-int z_erofs_fixup_insize(struct z_erofs_decompress_req *rq, const char *padbuf,
-                        unsigned int padbufsize)
+const char *z_erofs_fixup_insize(struct z_erofs_decompress_req *rq,
+                                const char *padbuf, unsigned int padbufsize)
 {
        const char *padend;
 
        padend = memchr_inv(padbuf, 0, padbufsize);
        if (!padend)
-               return -EFSCORRUPTED;
+               return "compressed data start not found";
        rq->inputsize -= padend - padbuf;
        rq->pageofs_in += padend - padbuf;
-       return 0;
+       return NULL;
 }
 
 static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst)
@@ -200,6 +200,7 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst
        bool support_0padding = false, may_inplace = false;
        unsigned int inputmargin;
        u8 *out, *headpage, *src;
+       const char *reason;
        int ret, maptype;
 
        DBG_BUGON(*rq->in == NULL);
@@ -208,12 +209,12 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst
        /* LZ4 decompression inplace is only safe if zero_padding is enabled */
        if (erofs_sb_has_zero_padding(EROFS_SB(rq->sb))) {
                support_0padding = true;
-               ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
+               reason = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
                                min_t(unsigned int, rq->inputsize,
                                      rq->sb->s_blocksize - rq->pageofs_in));
-               if (ret) {
+               if (reason) {
                        kunmap_local(headpage);
-                       return ret;
+                       return IS_ERR(reason) ? PTR_ERR(reason) : -EFSCORRUPTED;
                }
                may_inplace = !((rq->pageofs_in + rq->inputsize) &
                                (rq->sb->s_blocksize - 1));
index 97b77ab6443211f320deb7f38d3a6b696ba4b9ea..5ef6f71d3b7f362bb8f347af10e88d9bed91fb4e 100644 (file)
@@ -9,16 +9,17 @@ static int __z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
        struct sg_table st_src, st_dst;
        struct acomp_req *req;
        struct crypto_wait wait;
+       const char *reason;
        u8 *headpage;
        int ret;
 
        headpage = kmap_local_page(*rq->in);
-       ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
+       reason = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
                                min_t(unsigned int, rq->inputsize,
                                      rq->sb->s_blocksize - rq->pageofs_in));
        kunmap_local(headpage);
-       if (ret)
-               return ret;
+       if (reason)
+               return IS_ERR(reason) ? PTR_ERR(reason) : -EFSCORRUPTED;
 
        req = acomp_request_alloc(tfm);
        if (!req)
index afc73abd8db50ae7d2f5c2fc12cb6673a6e081fd..3fb73000ed2752528039214030b8d8419a8d065c 100644 (file)
@@ -103,16 +103,16 @@ static const char *__z_erofs_deflate_decompress(struct z_erofs_decompress_req *r
        struct super_block *sb = rq->sb;
        struct z_erofs_stream_dctx dctx = { .rq = rq, .no = -1, .ni = 0 };
        struct z_erofs_deflate *strm;
-       const char *reason = NULL;
-       int zerr, err;
+       const char *reason;
+       int zerr;
 
        /* 1. get the exact DEFLATE compressed size */
        dctx.kin = kmap_local_page(*rq->in);
-       err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
+       reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
                        min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
-       if (err) {
+       if (reason) {
                kunmap_local(dctx.kin);
-               return ERR_PTR(err);
+               return reason;
        }
 
        /* 2. get an available DEFLATE context */
@@ -130,7 +130,7 @@ again:
        /* 3. multi-call decompress */
        zerr = zlib_inflateInit2(&strm->z, -MAX_WBITS);
        if (zerr != Z_OK) {
-               err = -EINVAL;
+               reason = ERR_PTR(-EINVAL);
                goto failed_zinit;
        }
 
@@ -161,12 +161,11 @@ again:
                        reason = (zerr == Z_DATA_ERROR ?
                                "corrupted compressed data" :
                                "unexpected end of stream");
-                       err = -EFSCORRUPTED;
                        break;
                }
        }
-       if (zlib_inflateEnd(&strm->z) != Z_OK && !err)
-               err = -EIO;
+       if (zlib_inflateEnd(&strm->z) != Z_OK && !reason)
+               reason = ERR_PTR(-EIO);
        if (dctx.kout)
                kunmap_local(dctx.kout);
 failed_zinit:
@@ -177,7 +176,7 @@ failed_zinit:
        z_erofs_deflate_head = strm;
        spin_unlock(&z_erofs_deflate_lock);
        wake_up(&z_erofs_deflate_wq);
-       return reason ?: ERR_PTR(err);
+       return reason;
 }
 
 static const char *z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq,
index 0161f3375efd65ab2d68140a27f6efcd3147b5a6..b4ea6978faae6e86e51f21fe86844d5a908922d6 100644 (file)
@@ -154,16 +154,15 @@ static const char *z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
        struct xz_buf buf = {};
        struct z_erofs_lzma *strm;
        enum xz_ret xz_err;
-       const char *reason = NULL;
-       int err;
+       const char *reason;
 
        /* 1. get the exact LZMA compressed size */
        dctx.kin = kmap_local_page(*rq->in);
-       err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
+       reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
                        min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
-       if (err) {
+       if (reason) {
                kunmap_local(dctx.kin);
-               return ERR_PTR(err);
+               return reason;
        }
 
        /* 2. get an available lzma context */
@@ -224,7 +223,7 @@ again:
        z_erofs_lzma_head = strm;
        spin_unlock(&z_erofs_lzma_lock);
        wake_up(&z_erofs_lzma_wq);
-       return reason ?: ERR_PTR(err);
+       return reason;
 }
 
 const struct z_erofs_decompressor z_erofs_lzma_decomp = {
index ae51faeb504dc03192d34ba2988059aa1d0111a9..beae49165c69146dbd1f7c95e03b4a68de074163 100644 (file)
@@ -143,17 +143,17 @@ static const char *z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
        zstd_in_buffer in_buf = { NULL, 0, 0 };
        zstd_out_buffer out_buf = { NULL, 0, 0 };
        struct z_erofs_zstd *strm;
-       const char *reason = NULL;
        zstd_dstream *stream;
-       int zerr, err;
+       const char *reason;
+       int zerr;
 
        /* 1. get the exact compressed size */
        dctx.kin = kmap_local_page(*rq->in);
-       err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
+       reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in,
                        min(rq->inputsize, sb->s_blocksize - rq->pageofs_in));
-       if (err) {
+       if (reason) {
                kunmap_local(dctx.kin);
-               return ERR_PTR(err);
+               return reason;
        }
 
        /* 2. get an available ZSTD context */
@@ -162,7 +162,7 @@ static const char *z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq,
        /* 3. multi-call decompress */
        stream = zstd_init_dstream(z_erofs_zstd_max_dictsize, strm->wksp, strm->wkspsz);
        if (!stream) {
-               err = -ENOMEM;
+               reason = ERR_PTR(-ENOMEM);
                goto failed_zinit;
        }
 
@@ -208,7 +208,7 @@ failed_zinit:
        z_erofs_zstd_head = strm;
        spin_unlock(&z_erofs_zstd_lock);
        wake_up(&z_erofs_zstd_wq);
-       return reason ?: ERR_PTR(err);
+       return reason;
 }
 
 const struct z_erofs_decompressor z_erofs_zstd_decomp = {