Re: [PATCH v4 12/12] mm: change the contract for free_pgtables(), update docs
From: Lance Yang
Date: Wed Sep 23 2026 - 23:26:45 EST
On Tue, Sep 22, 2026 at 04:35:43PM +0100, Lorenzo Stoakes (ARM) wrote:
>Now that page tables are freed after an RCU grace period, it is safe for
>read-only page table walkers to walk page table ranges that are being
>concurrently torn down, provided the mm is kept alive via mmgrab().
>
>It is however unsafe for writers to do so, as they must obtain an
>appropriate lock to do so safely.
>
>Update the pte_offset_map_lock()'s comment block to reflect this.
>
>Similarly update the process addresses documentation.
>
>Acked-by: Kiryl Shutsemau (Meta) <kas@xxxxxxxxxx>
>Signed-off-by: Lorenzo Stoakes (ARM) <ljs@xxxxxxxxxx>
>---
> Documentation/mm/process_addrs.rst | 6 ++++++
> mm/pgtable-generic.c | 15 +++++++++++----
> 2 files changed, 17 insertions(+), 4 deletions(-)
>
>diff --git a/Documentation/mm/process_addrs.rst b/Documentation/mm/process_addrs.rst
>index a7296f251799..b1f4f44d75eb 100644
>--- a/Documentation/mm/process_addrs.rst
>+++ b/Documentation/mm/process_addrs.rst
>@@ -537,6 +537,12 @@ We establish basic locking rules when interacting with page tables:
> * When changing a page table entry the page table lock for that page table
> **must** be held, except if you can safely assume nobody can access the page
> tables concurrently (such as on invocation of :c:func:`!free_pgtables`).
>+* Page tables may be *walked* under RCU alone, as page tables are freed only
>+ after an RCU grace period has elapsed. However, any entry found must be
>+ revalidated after the page table lock is taken (such as the
>+ :c:func:`!pmd_same` recheck performed by :c:func:`!pte_offset_map_lock`)
>+ before it is acted upon. Changing an entry requires the page table
>+ lock and one of the locks that excludes teardown (mmap or VMA lock).
What about rmap walkers? try_to_unmap() clears PTEs under the rmap lock
and PTL, without an mmap or VMA lock.
Cheers, Lance
> * Reads from and writes to page table entries must be *appropriately*
> atomic. See the section on atomicity below for details.
> * Populating previously empty entries requires that the mmap or VMA locks are
>diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
>index b91b1a98029c..a127e3e8f9b9 100644
>--- a/mm/pgtable-generic.c
>+++ b/mm/pgtable-generic.c
>@@ -385,10 +385,17 @@ pte_t *pte_offset_map_rw_nolock(struct mm_struct *mm, pmd_t *pmd,
> * Note: "RO" / "RW" expresses the intended semantics, not that the *kmap* will
> * be read-only/read-write protected.
> *
>- * Note that free_pgtables(), used after unmapping detached vmas, or when
>- * exiting the whole mm, does not take page table lock before freeing a page
>- * table, and may not use RCU at all: "outsiders" like khugepaged should avoid
>- * pte_offset_map() and co once the vma is detached from mm or mm_users is zero.
>+ * Note that free_pgtables(), used after unmapping detached vmas or when exiting
>+ * the whole mm, does not take a page table lock before freeing a page table.
>+ *
>+ * As page table freeing itself is RCU-safe, page table readers can safely run
>+ * concurrently with page table teardown.
>+ *
>+ * However, writers CANNOT as, without a lock being held, nothing prevents
>+ * concurrent teardown.
>+ *
>+ * Also note that the PGD itself is freed at mmdrop() time, not under RCU - so
>+ * the walker must keep the mm alive either by pinning the mm or the VMA.
> */
> pte_t *pte_offset_map_lock(struct mm_struct *mm, pmd_t *pmd,
> unsigned long addr, spinlock_t **ptlp)
>
>--
>2.55.0
>
>