Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'erofs-for-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs

Pull erofs updates from Gao Xiang:

- Fix a WARNING caused by a recent FSDAX misdetection regression

- Fix the filesystem stacking limit for file-backed mounts

- Print more informative diagnostics on decompression errors

- Switch the on-disk definition `erofs_fs.h` to the MIT license

- Minor cleanups

* tag 'erofs-for-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs:
erofs: switch on-disk header `erofs_fs.h` to MIT license
erofs: get rid of raw bi_end_io() usage
erofs: enable error reporting for z_erofs_fixup_insize()
erofs: enable error reporting for z_erofs_stream_switch_bufs()
erofs: improve Zstd, LZMA and DEFLATE error strings
erofs: improve decompression error reporting
erofs: tidy up z_erofs_lz4_handle_overlap()
erofs: limit the level of fs stacking for file-backed mounts
erofs: correct FSDAX detection

+178 -148
+6 -6
fs/erofs/compress.h
··· 23 23 struct z_erofs_decompressor { 24 24 int (*config)(struct super_block *sb, struct erofs_super_block *dsb, 25 25 void *data, int size); 26 - int (*decompress)(struct z_erofs_decompress_req *rq, 27 - struct page **pagepool); 26 + const char *(*decompress)(struct z_erofs_decompress_req *rq, 27 + struct page **pagepool); 28 28 int (*init)(void); 29 29 void (*exit)(void); 30 30 char *name; ··· 70 70 bool bounced; /* is the bounce buffer used now? */ 71 71 }; 72 72 73 - int z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx, void **dst, 74 - void **src, struct page **pgpl); 75 - int z_erofs_fixup_insize(struct z_erofs_decompress_req *rq, const char *padbuf, 76 - unsigned int padbufsize); 73 + const char *z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx, 74 + void **dst, void **src, struct page **pgpl); 75 + const char *z_erofs_fixup_insize(struct z_erofs_decompress_req *rq, 76 + const char *padbuf, unsigned int padbufsize); 77 77 int __init z_erofs_init_decompressor(void); 78 78 void z_erofs_exit_decompressor(void); 79 79 int z_erofs_crypto_decompress(struct z_erofs_decompress_req *rq,
+75 -74
fs/erofs/decompressor.c
··· 105 105 return kaddr ? 1 : 0; 106 106 } 107 107 108 - static void *z_erofs_lz4_handle_overlap(struct z_erofs_decompress_req *rq, 108 + static void *z_erofs_lz4_handle_overlap(const struct z_erofs_decompress_req *rq, 109 109 void *inpage, void *out, unsigned int *inputmargin, 110 110 int *maptype, bool may_inplace) 111 111 { 112 - unsigned int oend, omargin, total, i; 112 + unsigned int oend, omargin, cnt, i; 113 113 struct page **in; 114 - void *src, *tmp; 114 + void *src; 115 115 116 - if (rq->inplace_io) { 117 - oend = rq->pageofs_out + rq->outputsize; 118 - omargin = PAGE_ALIGN(oend) - oend; 119 - if (rq->partial_decoding || !may_inplace || 120 - omargin < LZ4_DECOMPRESS_INPLACE_MARGIN(rq->inputsize)) 121 - goto docopy; 122 - 116 + /* 117 + * If in-place I/O isn't used, for example, the bounce compressed cache 118 + * can hold data for incomplete read requests. Just map the compressed 119 + * buffer as well and decompress directly. 120 + */ 121 + if (!rq->inplace_io) { 122 + if (rq->inpages <= 1) { 123 + *maptype = 0; 124 + return inpage; 125 + } 126 + kunmap_local(inpage); 127 + src = erofs_vm_map_ram(rq->in, rq->inpages); 128 + if (!src) 129 + return ERR_PTR(-ENOMEM); 130 + *maptype = 1; 131 + return src; 132 + } 133 + /* 134 + * Then, deal with in-place I/Os. The reasons why in-place I/O is useful 135 + * are: (1) It minimizes memory footprint during the I/O submission, 136 + * which is useful for slow storage (including network devices and 137 + * low-end HDDs/eMMCs) but with a lot inflight I/Os; (2) If in-place 138 + * decompression can also be applied, it will reuse the unique buffer so 139 + * that no extra CPU D-cache is polluted with temporary compressed data 140 + * for extreme performance. 141 + */ 142 + oend = rq->pageofs_out + rq->outputsize; 143 + omargin = PAGE_ALIGN(oend) - oend; 144 + if (!rq->partial_decoding && may_inplace && 145 + omargin >= LZ4_DECOMPRESS_INPLACE_MARGIN(rq->inputsize)) { 123 146 for (i = 0; i < rq->inpages; ++i) 124 147 if (rq->out[rq->outpages - rq->inpages + i] != 125 148 rq->in[i]) 126 - goto docopy; 127 - kunmap_local(inpage); 128 - *maptype = 3; 129 - return out + ((rq->outpages - rq->inpages) << PAGE_SHIFT); 149 + break; 150 + if (i >= rq->inpages) { 151 + kunmap_local(inpage); 152 + *maptype = 3; 153 + return out + ((rq->outpages - rq->inpages) << PAGE_SHIFT); 154 + } 130 155 } 131 - 132 - if (rq->inpages <= 1) { 133 - *maptype = 0; 134 - return inpage; 135 - } 136 - kunmap_local(inpage); 137 - src = erofs_vm_map_ram(rq->in, rq->inpages); 138 - if (!src) 139 - return ERR_PTR(-ENOMEM); 140 - *maptype = 1; 141 - return src; 142 - 143 - docopy: 144 - /* Or copy compressed data which can be overlapped to per-CPU buffer */ 145 - in = rq->in; 156 + /* 157 + * If in-place decompression can't be applied, copy compressed data that 158 + * may potentially overlap during decompression to a per-CPU buffer. 159 + */ 146 160 src = z_erofs_get_gbuf(rq->inpages); 147 161 if (!src) { 148 162 DBG_BUGON(1); ··· 164 150 return ERR_PTR(-EFAULT); 165 151 } 166 152 167 - tmp = src; 168 - total = rq->inputsize; 169 - while (total) { 170 - unsigned int page_copycnt = 171 - min_t(unsigned int, total, PAGE_SIZE - *inputmargin); 172 - 153 + for (i = 0, in = rq->in; i < rq->inputsize; i += cnt, ++in) { 154 + cnt = min_t(u32, rq->inputsize - i, PAGE_SIZE - *inputmargin); 173 155 if (!inpage) 174 156 inpage = kmap_local_page(*in); 175 - memcpy(tmp, inpage + *inputmargin, page_copycnt); 157 + memcpy(src + i, inpage + *inputmargin, cnt); 176 158 kunmap_local(inpage); 177 159 inpage = NULL; 178 - tmp += page_copycnt; 179 - total -= page_copycnt; 180 - ++in; 181 160 *inputmargin = 0; 182 161 } 183 162 *maptype = 2; ··· 178 171 } 179 172 180 173 /* 181 - * Get the exact inputsize with zero_padding feature. 182 - * - For LZ4, it should work if zero_padding feature is on (5.3+); 183 - * - For MicroLZMA, it'd be enabled all the time. 174 + * Get the exact on-disk size of the compressed data: 175 + * - For LZ4, it should apply if the zero_padding feature is on (5.3+); 176 + * - For others, zero_padding is enabled all the time. 184 177 */ 185 - int z_erofs_fixup_insize(struct z_erofs_decompress_req *rq, const char *padbuf, 186 - unsigned int padbufsize) 178 + const char *z_erofs_fixup_insize(struct z_erofs_decompress_req *rq, 179 + const char *padbuf, unsigned int padbufsize) 187 180 { 188 181 const char *padend; 189 182 190 183 padend = memchr_inv(padbuf, 0, padbufsize); 191 184 if (!padend) 192 - return -EFSCORRUPTED; 185 + return "compressed data start not found"; 193 186 rq->inputsize -= padend - padbuf; 194 187 rq->pageofs_in += padend - padbuf; 195 - return 0; 188 + return NULL; 196 189 } 197 190 198 191 static int z_erofs_lz4_decompress_mem(struct z_erofs_decompress_req *rq, u8 *dst) ··· 200 193 bool support_0padding = false, may_inplace = false; 201 194 unsigned int inputmargin; 202 195 u8 *out, *headpage, *src; 196 + const char *reason; 203 197 int ret, maptype; 204 198 205 199 DBG_BUGON(*rq->in == NULL); ··· 209 201 /* LZ4 decompression inplace is only safe if zero_padding is enabled */ 210 202 if (erofs_sb_has_zero_padding(EROFS_SB(rq->sb))) { 211 203 support_0padding = true; 212 - ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in, 204 + reason = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in, 213 205 min_t(unsigned int, rq->inputsize, 214 206 rq->sb->s_blocksize - rq->pageofs_in)); 215 - if (ret) { 207 + if (reason) { 216 208 kunmap_local(headpage); 217 - return ret; 209 + return IS_ERR(reason) ? PTR_ERR(reason) : -EFSCORRUPTED; 218 210 } 219 211 may_inplace = !((rq->pageofs_in + rq->inputsize) & 220 212 (rq->sb->s_blocksize - 1)); ··· 236 228 rq->inputsize, rq->outputsize); 237 229 238 230 if (ret != rq->outputsize) { 239 - erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]", 240 - ret, rq->inputsize, inputmargin, rq->outputsize); 241 231 if (ret >= 0) 242 232 memset(out + ret, 0, rq->outputsize - ret); 243 233 ret = -EFSCORRUPTED; ··· 256 250 return ret; 257 251 } 258 252 259 - static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, 260 - struct page **pagepool) 253 + static const char *z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, 254 + struct page **pagepool) 261 255 { 262 256 unsigned int dst_maptype; 263 257 void *dst; ··· 272 266 /* general decoding path which can be used for all cases */ 273 267 ret = z_erofs_lz4_prepare_dstpages(rq, pagepool); 274 268 if (ret < 0) 275 - return ret; 269 + return ERR_PTR(ret); 276 270 if (ret > 0) { 277 271 dst = page_address(*rq->out); 278 272 dst_maptype = 1; 279 273 } else { 280 274 dst = erofs_vm_map_ram(rq->out, rq->outpages); 281 275 if (!dst) 282 - return -ENOMEM; 276 + return ERR_PTR(-ENOMEM); 283 277 dst_maptype = 2; 284 278 } 285 279 } ··· 288 282 kunmap_local(dst); 289 283 else if (dst_maptype == 2) 290 284 vm_unmap_ram(dst, rq->outpages); 291 - return ret; 285 + return ERR_PTR(ret); 292 286 } 293 287 294 - static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq, 295 - struct page **pagepool) 288 + static const char *z_erofs_transform_plain(struct z_erofs_decompress_req *rq, 289 + struct page **pagepool) 296 290 { 297 291 const unsigned int nrpages_in = rq->inpages, nrpages_out = rq->outpages; 298 292 const unsigned int bs = rq->sb->s_blocksize; ··· 300 294 u8 *kin; 301 295 302 296 if (rq->outputsize > rq->inputsize) 303 - return -EOPNOTSUPP; 297 + return ERR_PTR(-EOPNOTSUPP); 304 298 if (rq->alg == Z_EROFS_COMPRESSION_INTERLACED) { 305 299 cur = bs - (rq->pageofs_out & (bs - 1)); 306 300 pi = (rq->pageofs_in + rq->inputsize - cur) & ~PAGE_MASK; ··· 340 334 kunmap_local(kin); 341 335 } 342 336 DBG_BUGON(ni > nrpages_in); 343 - return 0; 337 + return NULL; 344 338 } 345 339 346 - int z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx, void **dst, 347 - void **src, struct page **pgpl) 340 + const char *z_erofs_stream_switch_bufs(struct z_erofs_stream_dctx *dctx, 341 + void **dst, void **src, struct page **pgpl) 348 342 { 349 343 struct z_erofs_decompress_req *rq = dctx->rq; 350 - struct super_block *sb = rq->sb; 351 344 struct page **pgo, *tmppage; 352 345 unsigned int j; 353 346 354 347 if (!dctx->avail_out) { 355 - if (++dctx->no >= rq->outpages || !rq->outputsize) { 356 - erofs_err(sb, "insufficient space for decompressed data"); 357 - return -EFSCORRUPTED; 358 - } 348 + if (++dctx->no >= rq->outpages || !rq->outputsize) 349 + return "insufficient space for decompressed data"; 359 350 360 351 if (dctx->kout) 361 352 kunmap_local(dctx->kout); ··· 363 360 *pgo = erofs_allocpage(pgpl, rq->gfp); 364 361 if (!*pgo) { 365 362 dctx->kout = NULL; 366 - return -ENOMEM; 363 + return ERR_PTR(-ENOMEM); 367 364 } 368 365 set_page_private(*pgo, Z_EROFS_SHORTLIVED_PAGE); 369 366 } ··· 377 374 } 378 375 379 376 if (dctx->inbuf_pos == dctx->inbuf_sz && rq->inputsize) { 380 - if (++dctx->ni >= rq->inpages) { 381 - erofs_err(sb, "invalid compressed data"); 382 - return -EFSCORRUPTED; 383 - } 377 + if (++dctx->ni >= rq->inpages) 378 + return "invalid compressed data"; 384 379 if (dctx->kout) /* unlike kmap(), take care of the orders */ 385 380 kunmap_local(dctx->kout); 386 381 kunmap_local(dctx->kin); ··· 413 412 continue; 414 413 tmppage = erofs_allocpage(pgpl, rq->gfp); 415 414 if (!tmppage) 416 - return -ENOMEM; 415 + return ERR_PTR(-ENOMEM); 417 416 set_page_private(tmppage, Z_EROFS_SHORTLIVED_PAGE); 418 417 copy_highpage(tmppage, rq->in[j]); 419 418 rq->in[j] = tmppage; 420 419 } 421 - return 0; 420 + return NULL; 422 421 } 423 422 424 423 const struct z_erofs_decompressor *z_erofs_decomp[] = {
+4 -3
fs/erofs/decompressor_crypto.c
··· 9 9 struct sg_table st_src, st_dst; 10 10 struct acomp_req *req; 11 11 struct crypto_wait wait; 12 + const char *reason; 12 13 u8 *headpage; 13 14 int ret; 14 15 15 16 headpage = kmap_local_page(*rq->in); 16 - ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in, 17 + reason = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in, 17 18 min_t(unsigned int, rq->inputsize, 18 19 rq->sb->s_blocksize - rq->pageofs_in)); 19 20 kunmap_local(headpage); 20 - if (ret) 21 - return ret; 21 + if (reason) 22 + return IS_ERR(reason) ? PTR_ERR(reason) : -EFSCORRUPTED; 22 23 23 24 req = acomp_request_alloc(tfm); 24 25 if (!req)
+19 -18
fs/erofs/decompressor_deflate.c
··· 97 97 return -ENOMEM; 98 98 } 99 99 100 - static int __z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq, 101 - struct page **pgpl) 100 + static const char *__z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq, 101 + struct page **pgpl) 102 102 { 103 103 struct super_block *sb = rq->sb; 104 104 struct z_erofs_stream_dctx dctx = { .rq = rq, .no = -1, .ni = 0 }; 105 105 struct z_erofs_deflate *strm; 106 - int zerr, err; 106 + const char *reason; 107 + int zerr; 107 108 108 109 /* 1. get the exact DEFLATE compressed size */ 109 110 dctx.kin = kmap_local_page(*rq->in); 110 - err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in, 111 + reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in, 111 112 min(rq->inputsize, sb->s_blocksize - rq->pageofs_in)); 112 - if (err) { 113 + if (reason) { 113 114 kunmap_local(dctx.kin); 114 - return err; 115 + return reason; 115 116 } 116 117 117 118 /* 2. get an available DEFLATE context */ ··· 130 129 /* 3. multi-call decompress */ 131 130 zerr = zlib_inflateInit2(&strm->z, -MAX_WBITS); 132 131 if (zerr != Z_OK) { 133 - err = -EIO; 132 + reason = ERR_PTR(-EINVAL); 134 133 goto failed_zinit; 135 134 } 136 135 ··· 144 143 while (1) { 145 144 dctx.avail_out = strm->z.avail_out; 146 145 dctx.inbuf_sz = strm->z.avail_in; 147 - err = z_erofs_stream_switch_bufs(&dctx, 146 + reason = z_erofs_stream_switch_bufs(&dctx, 148 147 (void **)&strm->z.next_out, 149 148 (void **)&strm->z.next_in, pgpl); 150 - if (err) 149 + if (reason) 151 150 break; 152 151 strm->z.avail_out = dctx.avail_out; 153 152 strm->z.avail_in = dctx.inbuf_sz; ··· 158 157 break; 159 158 if (zerr == Z_STREAM_END && !rq->outputsize) 160 159 break; 161 - erofs_err(sb, "failed to decompress %d in[%u] out[%u]", 162 - zerr, rq->inputsize, rq->outputsize); 163 - err = -EFSCORRUPTED; 160 + reason = (zerr == Z_DATA_ERROR ? 161 + "corrupted compressed data" : 162 + "unexpected end of stream"); 164 163 break; 165 164 } 166 165 } 167 - if (zlib_inflateEnd(&strm->z) != Z_OK && !err) 168 - err = -EIO; 166 + if (zlib_inflateEnd(&strm->z) != Z_OK && !reason) 167 + reason = ERR_PTR(-EIO); 169 168 if (dctx.kout) 170 169 kunmap_local(dctx.kout); 171 170 failed_zinit: ··· 176 175 z_erofs_deflate_head = strm; 177 176 spin_unlock(&z_erofs_deflate_lock); 178 177 wake_up(&z_erofs_deflate_wq); 179 - return err; 178 + return reason; 180 179 } 181 180 182 - static int z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq, 183 - struct page **pgpl) 181 + static const char *z_erofs_deflate_decompress(struct z_erofs_decompress_req *rq, 182 + struct page **pgpl) 184 183 { 185 184 #ifdef CONFIG_EROFS_FS_ZIP_ACCEL 186 185 int err; ··· 188 187 if (!rq->partial_decoding) { 189 188 err = z_erofs_crypto_decompress(rq, pgpl); 190 189 if (err != -EOPNOTSUPP) 191 - return err; 190 + return ERR_PTR(err); 192 191 193 192 } 194 193 #endif
+13 -13
fs/erofs/decompressor_lzma.c
··· 146 146 return err; 147 147 } 148 148 149 - static int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq, 150 - struct page **pgpl) 149 + static const char *z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq, 150 + struct page **pgpl) 151 151 { 152 152 struct super_block *sb = rq->sb; 153 153 struct z_erofs_stream_dctx dctx = { .rq = rq, .no = -1, .ni = 0 }; 154 154 struct xz_buf buf = {}; 155 155 struct z_erofs_lzma *strm; 156 156 enum xz_ret xz_err; 157 - int err; 157 + const char *reason; 158 158 159 159 /* 1. get the exact LZMA compressed size */ 160 160 dctx.kin = kmap_local_page(*rq->in); 161 - err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in, 161 + reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in, 162 162 min(rq->inputsize, sb->s_blocksize - rq->pageofs_in)); 163 - if (err) { 163 + if (reason) { 164 164 kunmap_local(dctx.kin); 165 - return err; 165 + return reason; 166 166 } 167 167 168 168 /* 2. get an available lzma context */ ··· 188 188 dctx.avail_out = buf.out_size - buf.out_pos; 189 189 dctx.inbuf_sz = buf.in_size; 190 190 dctx.inbuf_pos = buf.in_pos; 191 - err = z_erofs_stream_switch_bufs(&dctx, (void **)&buf.out, 192 - (void **)&buf.in, pgpl); 193 - if (err) 191 + reason = z_erofs_stream_switch_bufs(&dctx, (void **)&buf.out, 192 + (void **)&buf.in, pgpl); 193 + if (reason) 194 194 break; 195 195 196 196 if (buf.out_size == buf.out_pos) { ··· 207 207 if (xz_err != XZ_OK) { 208 208 if (xz_err == XZ_STREAM_END && !rq->outputsize) 209 209 break; 210 - erofs_err(sb, "failed to decompress %d in[%u] out[%u]", 211 - xz_err, rq->inputsize, rq->outputsize); 212 - err = -EFSCORRUPTED; 210 + reason = (xz_err == XZ_DATA_ERROR ? 211 + "corrupted compressed data" : 212 + "unexpected end of stream"); 213 213 break; 214 214 } 215 215 } while (1); ··· 223 223 z_erofs_lzma_head = strm; 224 224 spin_unlock(&z_erofs_lzma_lock); 225 225 wake_up(&z_erofs_lzma_wq); 226 - return err; 226 + return reason; 227 227 } 228 228 229 229 const struct z_erofs_decompressor z_erofs_lzma_decomp = {
+13 -15
fs/erofs/decompressor_zstd.c
··· 135 135 return strm ? -ENOMEM : 0; 136 136 } 137 137 138 - static int z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, 139 - struct page **pgpl) 138 + static const char *z_erofs_zstd_decompress(struct z_erofs_decompress_req *rq, 139 + struct page **pgpl) 140 140 { 141 141 struct super_block *sb = rq->sb; 142 142 struct z_erofs_stream_dctx dctx = { .rq = rq, .no = -1, .ni = 0 }; ··· 144 144 zstd_out_buffer out_buf = { NULL, 0, 0 }; 145 145 struct z_erofs_zstd *strm; 146 146 zstd_dstream *stream; 147 - int zerr, err; 147 + const char *reason; 148 + int zerr; 148 149 149 150 /* 1. get the exact compressed size */ 150 151 dctx.kin = kmap_local_page(*rq->in); 151 - err = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in, 152 + reason = z_erofs_fixup_insize(rq, dctx.kin + rq->pageofs_in, 152 153 min(rq->inputsize, sb->s_blocksize - rq->pageofs_in)); 153 - if (err) { 154 + if (reason) { 154 155 kunmap_local(dctx.kin); 155 - return err; 156 + return reason; 156 157 } 157 158 158 159 /* 2. get an available ZSTD context */ ··· 162 161 /* 3. multi-call decompress */ 163 162 stream = zstd_init_dstream(z_erofs_zstd_max_dictsize, strm->wksp, strm->wkspsz); 164 163 if (!stream) { 165 - err = -EIO; 164 + reason = ERR_PTR(-ENOMEM); 166 165 goto failed_zinit; 167 166 } 168 167 ··· 175 174 do { 176 175 dctx.inbuf_sz = in_buf.size; 177 176 dctx.inbuf_pos = in_buf.pos; 178 - err = z_erofs_stream_switch_bufs(&dctx, &out_buf.dst, 177 + reason = z_erofs_stream_switch_bufs(&dctx, &out_buf.dst, 179 178 (void **)&in_buf.src, pgpl); 180 - if (err) 179 + if (reason) 181 180 break; 182 181 183 182 if (out_buf.size == out_buf.pos) { ··· 192 191 if (zstd_is_error(zerr) || 193 192 ((rq->outputsize + dctx.avail_out) && (!zerr || (zerr > 0 && 194 193 !(rq->inputsize + in_buf.size - in_buf.pos))))) { 195 - erofs_err(sb, "failed to decompress in[%u] out[%u]: %s", 196 - rq->inputsize, rq->outputsize, 197 - zstd_is_error(zerr) ? zstd_get_error_name(zerr) : 198 - "unexpected end of stream"); 199 - err = -EFSCORRUPTED; 194 + reason = zstd_is_error(zerr) ? zstd_get_error_name(zerr) : 195 + "unexpected end of stream"; 200 196 break; 201 197 } 202 198 } while (rq->outputsize + dctx.avail_out); ··· 208 210 z_erofs_zstd_head = strm; 209 211 spin_unlock(&z_erofs_zstd_lock); 210 212 wake_up(&z_erofs_zstd_wq); 211 - return err; 213 + return reason; 212 214 } 213 215 214 216 const struct z_erofs_decompressor z_erofs_zstd_decomp = {
+1 -1
fs/erofs/erofs_fs.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only OR Apache-2.0 */ 1 + /* SPDX-License-Identifier: MIT */ 2 2 /* 3 3 * EROFS (Enhanced ROM File System) on-disk format definition 4 4 *
+1 -1
fs/erofs/fileio.c
··· 34 34 if (rq->bio.bi_end_io) { 35 35 if (ret < 0 && !rq->bio.bi_status) 36 36 rq->bio.bi_status = errno_to_blk_status(ret); 37 - rq->bio.bi_end_io(&rq->bio); 38 37 } else { 39 38 bio_for_each_folio_all(fi, &rq->bio) { 40 39 DBG_BUGON(folio_test_uptodate(fi.folio)); 41 40 erofs_onlinefolio_end(fi.folio, ret, false); 42 41 } 43 42 } 43 + bio_endio(&rq->bio); 44 44 bio_uninit(&rq->bio); 45 45 kfree(rq); 46 46 }
+2 -2
fs/erofs/fscache.c
··· 185 185 186 186 if (IS_ERR_VALUE(transferred_or_error)) 187 187 io->bio.bi_status = errno_to_blk_status(transferred_or_error); 188 - io->bio.bi_end_io(&io->bio); 188 + bio_endio(&io->bio); 189 189 BUILD_BUG_ON(offsetof(struct erofs_fscache_bio, io) != 0); 190 190 erofs_fscache_io_put(&io->io); 191 191 } ··· 216 216 if (!ret) 217 217 return; 218 218 bio->bi_status = errno_to_blk_status(ret); 219 - bio->bi_end_io(bio); 219 + bio_endio(bio); 220 220 } 221 221 222 222 static int erofs_fscache_meta_read_folio(struct file *data, struct folio *folio)
+27 -11
fs/erofs/super.c
··· 174 174 if (!erofs_is_fileio_mode(sbi)) { 175 175 dif->dax_dev = fs_dax_get_by_bdev(file_bdev(file), 176 176 &dif->dax_part_off, NULL, NULL); 177 - if (!dif->dax_dev && test_opt(&sbi->opt, DAX_ALWAYS)) { 178 - erofs_info(sb, "DAX unsupported by %s. Turning off DAX.", 179 - dif->path); 180 - clear_opt(&sbi->opt, DAX_ALWAYS); 181 - } 182 177 } else if (!S_ISREG(file_inode(file)->i_mode)) { 183 178 fput(file); 184 179 return -EINVAL; 180 + } 181 + if (!dif->dax_dev && test_opt(&sbi->opt, DAX_ALWAYS)) { 182 + erofs_info(sb, "DAX unsupported by %s. Turning off DAX.", 183 + dif->path); 184 + clear_opt(&sbi->opt, DAX_ALWAYS); 185 185 } 186 186 dif->file = file; 187 187 } ··· 215 215 ondisk_extradevs, sbi->devs->extra_devices); 216 216 return -EINVAL; 217 217 } 218 - if (!ondisk_extradevs) { 219 - if (test_opt(&sbi->opt, DAX_ALWAYS) && !sbi->dif0.dax_dev) { 220 - erofs_info(sb, "DAX unsupported by block device. Turning off DAX."); 221 - clear_opt(&sbi->opt, DAX_ALWAYS); 222 - } 223 - return 0; 218 + 219 + if (test_opt(&sbi->opt, DAX_ALWAYS) && !sbi->dif0.dax_dev) { 220 + erofs_info(sb, "DAX unsupported by block device. Turning off DAX."); 221 + clear_opt(&sbi->opt, DAX_ALWAYS); 224 222 } 223 + if (!ondisk_extradevs) 224 + return 0; 225 225 226 226 if (!sbi->devs->extra_devices && !erofs_is_fscache_mode(sb)) 227 227 sbi->devs->flatdev = true; ··· 639 639 640 640 sbi->blkszbits = PAGE_SHIFT; 641 641 if (!sb->s_bdev) { 642 + /* 643 + * (File-backed mounts) EROFS claims it's safe to nest other 644 + * fs contexts (including its own) due to self-controlled RO 645 + * accesses/contexts and no side-effect changes that need to 646 + * context save & restore so it can reuse the current thread 647 + * context. However, it still needs to bump `s_stack_depth` to 648 + * avoid kernel stack overflow from nested filesystems. 649 + */ 650 + if (erofs_is_fileio_mode(sbi)) { 651 + sb->s_stack_depth = 652 + file_inode(sbi->dif0.file)->i_sb->s_stack_depth + 1; 653 + if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { 654 + erofs_err(sb, "maximum fs stacking depth exceeded"); 655 + return -ENOTBLK; 656 + } 657 + } 642 658 sb->s_blocksize = PAGE_SIZE; 643 659 sb->s_blocksize_bits = PAGE_SHIFT; 644 660
+17 -4
fs/erofs/zdata.c
··· 1267 1267 struct erofs_sb_info *const sbi = EROFS_SB(be->sb); 1268 1268 struct z_erofs_pcluster *pcl = be->pcl; 1269 1269 unsigned int pclusterpages = z_erofs_pclusterpages(pcl); 1270 - const struct z_erofs_decompressor *decomp = 1270 + const struct z_erofs_decompressor *alg = 1271 1271 z_erofs_decomp[pcl->algorithmformat]; 1272 + bool try_free = true; 1272 1273 int i, j, jtop, err2; 1273 1274 struct page *page; 1274 1275 bool overlapped; 1275 - bool try_free = true; 1276 + const char *reason; 1276 1277 1277 1278 mutex_lock(&pcl->lock); 1278 1279 be->nr_pages = PAGE_ALIGN(pcl->length + pcl->pageofs_out) >> PAGE_SHIFT; ··· 1305 1304 err2 = z_erofs_parse_in_bvecs(be, &overlapped); 1306 1305 if (err2) 1307 1306 err = err2; 1308 - if (!err) 1309 - err = decomp->decompress(&(struct z_erofs_decompress_req) { 1307 + if (!err) { 1308 + reason = alg->decompress(&(struct z_erofs_decompress_req) { 1310 1309 .sb = be->sb, 1311 1310 .in = be->compressed_pages, 1312 1311 .out = be->decompressed_pages, ··· 1323 1322 .gfp = pcl->besteffort ? GFP_KERNEL : 1324 1323 GFP_NOWAIT | __GFP_NORETRY 1325 1324 }, be->pagepool); 1325 + if (IS_ERR(reason)) { 1326 + erofs_err(be->sb, "failed to decompress (%s) %ld @ pa %llu size %u => %u", 1327 + alg->name, PTR_ERR(reason), pcl->pos, 1328 + pcl->pclustersize, pcl->length); 1329 + err = PTR_ERR(reason); 1330 + } else if (unlikely(reason)) { 1331 + erofs_err(be->sb, "failed to decompress (%s) %s @ pa %llu size %u => %u", 1332 + alg->name, reason, pcl->pos, 1333 + pcl->pclustersize, pcl->length); 1334 + err = -EFSCORRUPTED; 1335 + } 1336 + } 1326 1337 1327 1338 /* must handle all compressed pages before actual file pages */ 1328 1339 if (pcl->from_meta) {