The patch titled Subject: mm: clarify swap_count_continued and improve readability for __swap_duplicate has been added to the -mm mm-unstable branch. Its filename is mm-swap-add-nr-argument-in-swapcache_prepare-and-swapcache_clear-to-support-large-folios-fix.patch This patch will shortly appear at https://git.kernel.org/pub/scm/linux/kernel/git/akpm/25-new.git/tree/patches/mm-swap-add-nr-argument-in-swapcache_prepare-and-swapcache_clear-to-support-large-folios-fix.patch This patch will later appear in the mm-unstable branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/process/submit-checklist.rst when testing your code *** The -mm tree is included into linux-next via the mm-everything branch at git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm and is updated there every 2-3 working days ------------------------------------------------------ From: Barry Song <v-songbaohua@xxxxxxxx> Subject: mm: clarify swap_count_continued and improve readability for __swap_duplicate Date: Fri, 2 Aug 2024 17:52:43 +1200 When usage=1 and swapcount is very large, the situation can become quite complex. The first entry might succeed with swap_count_continued(), but the second entry may require extending to an additional continued page. Rolling back these changes can be extremely challenging. Therefore, anyone using usage==1 for batched __swap_duplicate() operations should proceed with caution. Additionally, we have moved swap_count_continued() to the second iteration to enhance readability, as this function may modify data. Link: https://lkml.kernel.org/r/20240802071817.47081-1-21cnbao@xxxxxxxxx Signed-off-by: Barry Song <v-songbaohua@xxxxxxxx> Suggested-by: "Huang, Ying" <ying.huang@xxxxxxxxx> Cc: Baolin Wang <baolin.wang@xxxxxxxxxxxxxxxxx> Cc: Chris Li <chrisl@xxxxxxxxxx> Cc: David Hildenbrand <david@xxxxxxxxxx> Cc: Gao Xiang <xiang@xxxxxxxxxx> Cc: Hugh Dickins <hughd@xxxxxxxxxx> Cc: Johannes Weiner <hannes@xxxxxxxxxxx> Cc: Kairui Song <kasong@xxxxxxxxxxx> Cc: Kalesh Singh <kaleshsingh@xxxxxxxxxx> Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> Cc: Michal Hocko <mhocko@xxxxxxxx> Cc: Minchan Kim <minchan@xxxxxxxxxx> Cc: Nhat Pham <nphamcs@xxxxxxxxx> Cc: Ryan Roberts <ryan.roberts@xxxxxxx> Cc: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx> Cc: Shakeel Butt <shakeel.butt@xxxxxxxxx> Cc: Suren Baghdasaryan <surenb@xxxxxxxxxx> Cc: Yang Shi <shy828301@xxxxxxxxx> Cc: Yosry Ahmed <yosryahmed@xxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/swapfile.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) --- a/mm/swapfile.c~mm-swap-add-nr-argument-in-swapcache_prepare-and-swapcache_clear-to-support-large-folios-fix +++ a/mm/swapfile.c @@ -3386,6 +3386,7 @@ static int __swap_duplicate(swp_entry_t offset = swp_offset(entry); VM_WARN_ON(nr > SWAPFILE_CLUSTER - offset % SWAPFILE_CLUSTER); + VM_WARN_ON(usage == 1 && nr > 1); ci = lock_cluster_or_swap_info(p, offset); err = 0; @@ -3404,27 +3405,14 @@ static int __swap_duplicate(swp_entry_t has_cache = count & SWAP_HAS_CACHE; count &= ~SWAP_HAS_CACHE; - if (usage == SWAP_HAS_CACHE) { - /* set SWAP_HAS_CACHE if there is no cache and entry is used */ - if (!has_cache && count) - continue; - else if (has_cache) /* someone else added cache */ + if (!count && !has_cache) { + err = -ENOENT; + } else if (usage == SWAP_HAS_CACHE) { + if (has_cache) err = -EEXIST; - else /* no users remaining */ - err = -ENOENT; - - } else if (count || has_cache) { - - if ((count & ~COUNT_CONTINUED) < SWAP_MAP_MAX) - continue; - else if ((count & ~COUNT_CONTINUED) > SWAP_MAP_MAX) - err = -EINVAL; - else if (swap_count_continued(p, offset + i, count)) - continue; - else - err = -ENOMEM; - } else - err = -ENOENT; /* unused swap entry */ + } else if ((count & ~COUNT_CONTINUED) > SWAP_MAP_MAX) { + err = -EINVAL; + } if (err) goto unlock_out; @@ -3439,8 +3427,16 @@ static int __swap_duplicate(swp_entry_t has_cache = SWAP_HAS_CACHE; else if ((count & ~COUNT_CONTINUED) < SWAP_MAP_MAX) count += usage; - else + else if (swap_count_continued(p, offset + i, count)) count = COUNT_CONTINUED; + else { + /* + * Don't need to rollback changes, because if + * usage == 1, there must be nr == 1. + */ + err = -ENOMEM; + goto unlock_out; + } WRITE_ONCE(p->swap_map[offset + i], count | has_cache); } _ Patches currently in -mm which might be from v-songbaohua@xxxxxxxx are mm-extend-usage-parameter-so-that-cluster_swap_free_nr-can-be-reused.patch mm-swap-add-nr-argument-in-swapcache_prepare-and-swapcache_clear-to-support-large-folios.patch mm-swap-add-nr-argument-in-swapcache_prepare-and-swapcache_clear-to-support-large-folios-fix.patch vpda-try-to-fix-the-potential-crash-due-to-misusing-__gfp_nofail.patch mm-document-__gfp_nofail-must-be-blockable.patch mm-bug_on-to-avoid-null-deference-while-__gfp_nofail-fails.patch mm-prohibit-null-deference-exposed-for-unsupported-non-blockable-__gfp_nofail.patch mm-add-nr-argument-in-mem_cgroup_swapin_uncharge_swap-helper-to-support-large-folios.patch