Re: [PATCH 02/13] mm: extract ensure_on_mmlist() helper

From: Dev Jain

Date: Fri May 29 2026 - 03:46:53 EST




On 27/04/26 3:31 pm, Usama Arif wrote:
> When a swap entry is installed in a page table, the mm must be added
> to init_mm.mmlist so that swapoff can find and unuse its swap entries.
> This double-checked locking pattern is currently open-coded in
> try_to_unmap_one() and copy_nonpresent_pte().
>
> Move it into ensure_on_mmlist() in mm/internal.h and convert both
> callers so it can be reused by upcoming PMD-level swap entry code
> paths that also need to register the mm with swapoff.
>
> copy_nonpresent_pte() previously inserted into &src_mm->mmlist rather
> than &init_mm.mmlist, but the insertion point is irrelevant, mmlist
> is a circular list and swapoff walks it entirely from init_mm.mmlist,
> so only membership matters, not position.
>
> Signed-off-by: Usama Arif <usama.arif@xxxxxxxxx>
> ---

Agree with David on the name.

The unlikely hint is dropped from the fork path. I don't think we care.

Reviewed-by: Dev Jain <dev.jain@xxxxxxx>


> mm/internal.h | 13 +++++++++++++
> mm/memory.c | 9 +--------
> mm/rmap.c | 7 +------
> 3 files changed, 15 insertions(+), 14 deletions(-)
>
> diff --git a/mm/internal.h b/mm/internal.h
> index 5a2ddcf68e0b..7de489689f54 100644
> --- a/mm/internal.h
> +++ b/mm/internal.h
> @@ -1952,4 +1952,17 @@ static inline int get_sysctl_max_map_count(void)
> bool may_expand_vm(struct mm_struct *mm, const vma_flags_t *vma_flags,
> unsigned long npages);
>
> +/*
> + * Ensure @mm is on the init_mm.mmlist so swapoff can find it.
> + */
> +static inline void ensure_on_mmlist(struct mm_struct *mm)
> +{
> + if (list_empty(&mm->mmlist)) {
> + spin_lock(&mmlist_lock);
> + if (list_empty(&mm->mmlist))
> + list_add(&mm->mmlist, &init_mm.mmlist);
> + spin_unlock(&mmlist_lock);
> + }
> +}
> +
> #endif /* __MM_INTERNAL_H */
> diff --git a/mm/memory.c b/mm/memory.c
> index ea6568571131..33d7cc274e23 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -937,14 +937,7 @@ copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
> if (swap_dup_entry_direct(entry) < 0)
> return -EIO;
>
> - /* make sure dst_mm is on swapoff's mmlist. */
> - if (unlikely(list_empty(&dst_mm->mmlist))) {
> - spin_lock(&mmlist_lock);
> - if (list_empty(&dst_mm->mmlist))
> - list_add(&dst_mm->mmlist,
> - &src_mm->mmlist);
> - spin_unlock(&mmlist_lock);
> - }
> + ensure_on_mmlist(dst_mm);
> /* Mark the swap entry as shared. */
> if (pte_swp_exclusive(orig_pte)) {
> pte = pte_swp_clear_exclusive(orig_pte);
> diff --git a/mm/rmap.c b/mm/rmap.c
> index 78b7fb5f367c..057e18cb80b0 100644
> --- a/mm/rmap.c
> +++ b/mm/rmap.c
> @@ -2302,12 +2302,7 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,
> set_pte_at(mm, address, pvmw.pte, pteval);
> goto walk_abort;
> }
> - if (list_empty(&mm->mmlist)) {
> - spin_lock(&mmlist_lock);
> - if (list_empty(&mm->mmlist))
> - list_add(&mm->mmlist, &init_mm.mmlist);
> - spin_unlock(&mmlist_lock);
> - }
> + ensure_on_mmlist(mm);
> dec_mm_counter(mm, MM_ANONPAGES);
> inc_mm_counter(mm, MM_SWAPENTS);
> swp_pte = swp_entry_to_pte(entry);