Add hwpoison handling to filemap_read() such that .read_iter() could make best effort copying data out of clean pages without risking MCE in case page cache contains HWpoison. [1] https://lore.kernel.org/linux-mm/aeZwAz6PcdlqSnJ2@casper.infradead.org/ Suggested-by: Matthew Wilcox Signed-off-by: Jane Chu --- mm/filemap.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index a27ce4ad6247..df8543573570 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2475,6 +2475,8 @@ static void filemap_get_read_batch(struct address_space *mapping, if (!folio_batch_add(fbatch, folio)) break; + if (folio_contain_hwpoisoned_page(folio)) + break; if (!folio_test_uptodate(folio)) break; if (folio_test_readahead(folio)) @@ -2871,6 +2873,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, size_t offset = iocb->ki_pos & (fsize - 1); size_t bytes = min_t(loff_t, end_offset - iocb->ki_pos, fsize - offset); + size_t adjusted; size_t copied; if (end_offset < folio_pos(folio)) @@ -2885,13 +2888,22 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter, if (writably_mapped) flush_dcache_folio(folio); - copied = copy_folio_to_iter(folio, offset, bytes, iter); + adjusted = bytes; + if (folio_contain_hwpoisoned_page(folio)) { + adjusted = adjust_range_hwpoison(folio, offset, bytes); + if (adjusted == 0) { + error = -EIO; + break; + } + } + + copied = copy_folio_to_iter(folio, offset, adjusted, iter); already_read += copied; iocb->ki_pos += copied; last_pos = iocb->ki_pos; - if (copied < bytes) { + if (copied < adjusted) { error = -EFAULT; break; } -- 2.43.5