| From: Hugh Dickins <hughd@google.com> |
| Subject: shmem: minor fixes to splice-read implementation |
| Date: Sun, 23 Jul 2023 14:05:54 -0700 (PDT) |
| |
| HWPoison: my reading of folio_test_hwpoison() is that it only tests the |
| head page of a large folio, whereas splice_folio_into_pipe() will splice |
| as much of the folio as it can: so for safety we should also check the |
| has_hwpoisoned flag, set if any of the folio's pages are hwpoisoned. |
| (Perhaps that ugliness can be improved at the mm end later.) |
| |
| The call to splice_zeropage_into_pipe() risked overrunning past EOF: ask |
| it for "part" not "len". |
| |
| Link: https://lkml.kernel.org/r/32c72c9c-72a8-115f-407d-f0148f368@google.com |
| Fixes: bd194b187115 ("shmem: Implement splice-read") |
| Signed-off-by: Hugh Dickins <hughd@google.com> |
| Reviewed-by: David Howells <dhowells@redhat.com> |
| Cc: David Hildenbrand <david@redhat.com> |
| Cc: Jens Axboe <axboe@kernel.dk> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| mm/shmem.c | 9 ++++++--- |
| 1 file changed, 6 insertions(+), 3 deletions(-) |
| |
| --- a/mm/shmem.c~shmem-minor-fixes-to-splice-read-implementation |
| +++ a/mm/shmem.c |
| @@ -2796,7 +2796,8 @@ static ssize_t shmem_file_splice_read(st |
| if (*ppos >= i_size_read(inode)) |
| break; |
| |
| - error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio, SGP_READ); |
| + error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio, |
| + SGP_READ); |
| if (error) { |
| if (error == -EINVAL) |
| error = 0; |
| @@ -2805,7 +2806,9 @@ static ssize_t shmem_file_splice_read(st |
| if (folio) { |
| folio_unlock(folio); |
| |
| - if (folio_test_hwpoison(folio)) { |
| + if (folio_test_hwpoison(folio) || |
| + (folio_test_large(folio) && |
| + folio_test_has_hwpoisoned(folio))) { |
| error = -EIO; |
| break; |
| } |
| @@ -2841,7 +2844,7 @@ static ssize_t shmem_file_splice_read(st |
| folio_put(folio); |
| folio = NULL; |
| } else { |
| - n = splice_zeropage_into_pipe(pipe, *ppos, len); |
| + n = splice_zeropage_into_pipe(pipe, *ppos, part); |
| } |
| |
| if (!n) |
| _ |