| From: Sidhartha Kumar <sidhartha.kumar@oracle.com> |
| Subject: fs/hugetlbfs/inode.c: mm/memory-failure.c: fix hugetlbfs hwpoison handling |
| Date: Fri, 12 Jan 2024 10:08:40 -0800 |
| |
| has_extra_refcount() makes the assumption that the page cache adds a ref |
| count of 1 and subtracts this in the extra_pins case. Commit a08c7193e4f1 |
| (mm/filemap: remove hugetlb special casing in filemap.c) modifies |
| __filemap_add_folio() by calling folio_ref_add(folio, nr); for all cases |
| (including hugtetlb) where nr is the number of pages in the folio. We |
| should adjust the number of references coming from the page cache by |
| subtracing the number of pages rather than 1. |
| |
| In hugetlbfs_read_iter(), folio_test_has_hwpoisoned() is testing the wrong |
| flag as, in the hugetlb case, memory-failure code calls |
| folio_test_set_hwpoison() to indicate poison. folio_test_hwpoison() is |
| the correct function to test for that flag. |
| |
| After these fixes, the hugetlb hwpoison read selftest passes all cases. |
| |
| Link: https://lkml.kernel.org/r/20240112180840.367006-1-sidhartha.kumar@oracle.com |
| Fixes: a08c7193e4f1 ("mm/filemap: remove hugetlb special casing in filemap.c") |
| Signed-off-by: Sidhartha Kumar <sidhartha.kumar@oracle.com> |
| Closes: https://lore.kernel.org/linux-mm/20230713001833.3778937-1-jiaqiyan@google.com/T/#m8e1469119e5b831bbd05d495f96b842e4a1c5519 |
| Reported-by: Muhammad Usama Anjum <usama.anjum@collabora.com> |
| Tested-by: Muhammad Usama Anjum <usama.anjum@collabora.com> |
| Acked-by: Miaohe Lin <linmiaohe@huawei.com> |
| Acked-by: Muchun Song <muchun.song@linux.dev> |
| Cc: James Houghton <jthoughton@google.com> |
| Cc: Jiaqi Yan <jiaqiyan@google.com> |
| Cc: Matthew Wilcox (Oracle) <willy@infradead.org> |
| Cc: Naoya Horiguchi <naoya.horiguchi@nec.com> |
| Cc: <stable@vger.kernel.org> [6.7+] |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| fs/hugetlbfs/inode.c | 2 +- |
| mm/memory-failure.c | 2 +- |
| 2 files changed, 2 insertions(+), 2 deletions(-) |
| |
| --- a/fs/hugetlbfs/inode.c~fs-hugetlbfs-inodec-mm-memory-failurec-fix-hugetlbfs-hwpoison-handling |
| +++ a/fs/hugetlbfs/inode.c |
| @@ -340,7 +340,7 @@ static ssize_t hugetlbfs_read_iter(struc |
| } else { |
| folio_unlock(folio); |
| |
| - if (!folio_test_has_hwpoisoned(folio)) |
| + if (!folio_test_hwpoison(folio)) |
| want = nr; |
| else { |
| /* |
| --- a/mm/memory-failure.c~fs-hugetlbfs-inodec-mm-memory-failurec-fix-hugetlbfs-hwpoison-handling |
| +++ a/mm/memory-failure.c |
| @@ -982,7 +982,7 @@ static bool has_extra_refcount(struct pa |
| int count = page_count(p) - 1; |
| |
| if (extra_pins) |
| - count -= 1; |
| + count -= folio_nr_pages(page_folio(p)); |
| |
| if (count > 0) { |
| pr_err("%#lx: %s still referenced by %d users\n", |
| _ |