| From: Kairui Song <kasong@tencent.com> |
| Subject: mm, swap: fix swap cache index error when retrying reclaim |
| Date: Wed, 17 Sep 2025 00:00:48 +0800 |
| |
| The allocator will reclaim cached slots while scanning. Currently, it |
| will try again if reclaim found a folio that is already removed from the |
| swap cache due to a race. But the following lookup will be using the |
| wrong index. It won't cause any OOB issue since the swap cache index is |
| truncated upon lookup, but it may lead to reclaiming of an irrelevant |
| folio. |
| |
| This should not cause a measurable issue, but we should fix it. |
| |
| Link: https://lkml.kernel.org/r/20250916160100.31545-4-ryncsn@gmail.com |
| Fixes: fae859550531 ("mm, swap: avoid reclaiming irrelevant swap cache") |
| Signed-off-by: Kairui Song <kasong@tencent.com> |
| Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com> |
| Acked-by: Nhat Pham <nphamcs@gmail.com> |
| Acked-by: Chris Li <chrisl@kernel.org> |
| Acked-by: David Hildenbrand <david@redhat.com> |
| Suggested-by: Chris Li <chrisl@kernel.org> |
| Cc: Baoquan He <bhe@redhat.com> |
| Cc: Barry Song <baohua@kernel.org> |
| Cc: "Huang, Ying" <ying.huang@linux.alibaba.com> |
| Cc: Hugh Dickins <hughd@google.com> |
| Cc: Johannes Weiner <hannes@cmpxchg.org> |
| Cc: Kemeng Shi <shikemeng@huaweicloud.com> |
| Cc: kernel test robot <oliver.sang@intel.com> |
| Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> |
| Cc: Matthew Wilcox (Oracle) <willy@infradead.org> |
| Cc: Yosry Ahmed <yosryahmed@google.com> |
| Cc: Zi Yan <ziy@nvidia.com> |
| Cc: SeongJae Park <sj@kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| mm/swapfile.c | 8 ++++---- |
| 1 file changed, 4 insertions(+), 4 deletions(-) |
| |
| --- a/mm/swapfile.c~mm-swap-fix-swap-cache-index-error-when-retrying-reclaim |
| +++ a/mm/swapfile.c |
| @@ -212,7 +212,7 @@ static bool swap_is_last_map(struct swap |
| static int __try_to_reclaim_swap(struct swap_info_struct *si, |
| unsigned long offset, unsigned long flags) |
| { |
| - swp_entry_t entry = swp_entry(si->type, offset); |
| + const swp_entry_t entry = swp_entry(si->type, offset); |
| struct swap_cluster_info *ci; |
| struct folio *folio; |
| int ret, nr_pages; |
| @@ -240,13 +240,13 @@ again: |
| * Offset could point to the middle of a large folio, or folio |
| * may no longer point to the expected offset before it's locked. |
| */ |
| - entry = folio->swap; |
| - if (offset < swp_offset(entry) || offset >= swp_offset(entry) + nr_pages) { |
| + if (offset < swp_offset(folio->swap) || |
| + offset >= swp_offset(folio->swap) + nr_pages) { |
| folio_unlock(folio); |
| folio_put(folio); |
| goto again; |
| } |
| - offset = swp_offset(entry); |
| + offset = swp_offset(folio->swap); |
| |
| need_reclaim = ((flags & TTRS_ANYWAY) || |
| ((flags & TTRS_UNMAPPED) && !folio_mapped(folio)) || |
| _ |