if (!uptodate(page3)) goto do_read readahead(FileA, 4K, 8K) // Here create PCL-chain like below: // [null, page1] [page2, null] // [PCL0:RA]-----[PCL1:RA] ... do read(page3) // found [PCL1:RA] and add page3 into it, // and then, change PCL1 from RA to R ... // Now, PCL-chain is as below: // [null, page1] [page2, page3] // [PCL0:RA]-----[PCL1:R] // try to decompress PCL-chain... z_erofs_decompress_queue err = 0; // failed with ENOMEM, so page 1 // only for RA will not be uptodated. // it's okay. err = decompress([PCL0:RA], err) // However, ENOMEM propagated to next // PCL, even though PCL is not only // for RA but also for R. As a result, // it just failed with ENOMEM without // trying any decompression, so page2 // and page3 will not be uptodated. ** BUG HERE ** --> err = decompress([PCL1:R], err) return err as ENOMEM ... wait_lock(page3) if (!uptodate(page3)) return EIO <-- Return an unexpected EIO! ... Fixes: 2349d2fa02db ("erofs: sunset unneeded NOFAILs") Cc: stable@vger.kernel.org Reviewed-by: Jaewook Kim Reviewed-by: Sungjong Seo Signed-off-by: Junbeom Yeom --- fs/erofs/zdata.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c index 27b1f44d10ce..86bf6e087d34 100644 --- a/fs/erofs/zdata.c +++ b/fs/erofs/zdata.c @@ -1414,11 +1414,15 @@ static int z_erofs_decompress_queue(const struct z_erofs_decompressqueue *io, }; struct z_erofs_pcluster *next; int err = io->eio ? -EIO : 0; + int io_err = err; for (; be.pcl != Z_EROFS_PCLUSTER_TAIL; be.pcl = next) { + int propagate_err; + DBG_BUGON(!be.pcl); next = READ_ONCE(be.pcl->next); - err = z_erofs_decompress_pcluster(&be, err) ?: err; + propagate_err = READ_ONCE(be.pcl->besteffort) ? io_err : err; + err = z_erofs_decompress_pcluster(&be, propagate_err) ?: err; } return err; } -- 2.34.1[PATCH] erofs: fix unexpected EIO under memory pressureJunbeom Yeom undefinedxiang@kernel.org, chao@kernel.org undefined undefined undefined undefined undefined undefined undefined‚