[RFC PATCH 00/12] remove is_swap_[pte, pmd]() + non-swap confusion

Lorenzo Stoakes
2025-10-24T07:42:57Z

There's an established convention in the kernel that we treat leaf page
tables (so far at the PTE, PMD level) as containing 'swap entries' should
they be neither empty (i.e. p**_none() evaluating true) nor present
(i.e. p**_present() evaluating true).

However, at the same time we also have helper predicates - is_swap_pte(),
is_swap_pmd() - which are inconsistently used.

This is problematic, as it is logical to assume that should somebody wish
to operate upon a page table swap entry they should first check to see if
it is in fact one.

It also implies that perhaps, in future, we might introduce a non-present,
none page table entry that is not a swap entry.

This series resolves this issue by systematically eliminating all use of
the is_swap_pte() and is swap_pmd() predicates so we retain only the
convention that should a leaf page table entry be neither none nor present
it is a swap entry.

We also have the further issue that 'swap entry' is unfortunately a really
rather overloaded term and in fact refers to both entries for swap and for
other information such as migration entries, page table markers, and device
private entries.

We therefore have the rather 'unique' concept of a 'non-swap' swap entry.

This is deeply confusing, so this series goes further and eliminates the
non_swap_entry() predicate, replacing it with is_non_present_entry() - with
an eye to a new convention of referring to these non-swap 'swap entries' as
non-present.

It also introduces the is_swap_entry() predicate to explicitly and
logically refer to actual 'true' swap entries, improving code readibility,
avoiding the hideous convention of:

if (!non_swap_entry(entry)) {
...
}

As part of these changes we also introduce a few other new predicates:

* pte_to_swp_entry_or_zero() - allows for convenient conversion from a PTE
to a swap entry if present, or an empty swap entry if none. This is
useful as many swap entry conversions are simply checking for flags for
which this suffices.

* get_pte_swap_entry() - Retrieves a PTE swap entry if it truly is a swap
entry (i.e. not a non-present entry), returning true if so, otherwise
returns false. This simplifies a lot of logic that previously open-coded
this.

* is_huge_pmd() - Determines if a PMD contains either a present transparent
huge page entry or a huge non-present entry. This again simplifies a lot
of logic that simply open-coded this.

REVIEWERS NOTE:

This series applies against mm-unstable as there are currently conflicts
with mm-new. Should the series receive community assent I will resolve
these at the point the RFC tag is removed.

I also intend to use this as a foundation for further work to add higher
order page table markers.

Lorenzo Stoakes (12):
mm: introduce and use pte_to_swp_entry_or_zero()
mm: avoid unnecessary uses of is_swap_pte()
mm: introduce get_pte_swap_entry() and use it
mm: use get_pte_swap_entry() in debug pgtable + remove is_swap_pte()
fs/proc/task_mmu: refactor pagemap_pmd_range()
mm: avoid unnecessary use of is_swap_pmd()
mm: introduce is_huge_pmd() and use where appropriate
mm/huge_memory: refactor copy_huge_pmd() non-present logic
mm/huge_memory: refactor change_huge_pmd() non-present logic
mm: remove remaining is_swap_pmd() users and is_swap_pmd()
mm: rename non_swap_entry() to is_non_present_entry()
mm: provide is_swap_entry() and use it

arch/s390/mm/gmap_helpers.c | 2 +-
arch/s390/mm/pgtable.c | 2 +-
fs/proc/task_mmu.c | 214 ++++++++++++++++++++--------------
include/linux/huge_mm.h | 49 +++++---
include/linux/swapops.h | 99 ++++++++++++++--
include/linux/userfaultfd_k.h | 16 +--
mm/debug_vm_pgtable.c | 43 ++++---
mm/filemap.c | 2 +-
mm/hmm.c | 2 +-
mm/huge_memory.c | 189 ++++++++++++++++--------------
mm/hugetlb.c | 6 +-
mm/internal.h | 12 +-
mm/khugepaged.c | 29 ++---
mm/madvise.c | 14 +--
mm/memory.c | 62 +++++-----
mm/migrate.c | 2 +-
mm/mincore.c | 2 +-
mm/mprotect.c | 45 ++++---
mm/mremap.c | 9 +-
mm/page_table_check.c | 25 ++--
mm/page_vma_mapped.c | 30 +++--
mm/swap_state.c | 5 +-
mm/swapfile.c | 3 +-
mm/userfaultfd.c | 2 +-
24 files changed, 511 insertions(+), 353 deletions(-)

--
2.51.0