On 7/29/26 18:48, Lorenzo Stoakes (ARM) wrote:
> This function is, for now, a placeholder; it will be used in future to
> determine whether to use the anonymous page index or not, based on whether
> the folio is anonymous or not.
> 
> Currently it simply wraps linear_page_index(), so this does not change
> behaviour.
> 
> We update callers that will, once the change is introduced to track
> anonymous folios by anonymous page offset if MAP_PRIVATE file-backed, need
> to determine which index to use based on folio type.
> 
> No functional change intended.
> 
> Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]>
> ---
>  include/linux/pagemap.h | 18 ++++++++++++++++++
>  mm/huge_memory.c        |  3 ++-
>  mm/migrate.c            |  6 ++++--
>  mm/userfaultfd.c        |  6 ++++--
>  4 files changed, 28 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
> index 259177544b03..6eb8d811ba4c 100644
> --- a/include/linux/pagemap.h
> +++ b/include/linux/pagemap.h
> @@ -1143,6 +1143,24 @@ static inline pgoff_t linear_anon_page_index(const 
> struct vm_area_struct *vma,
>       return pgoff;
>  }
>  
> +/**
> + * linear_folio_page_index() - Determine the absolute page offset of
> + * @address within @vma from @folio.
> + * @folio: The folio whose linear page index is sought.
> + * @vma: The VMA in which @address resides.
> + * @address: The address whose absolute page offset is required.
> + *
> + * For compatibility, currently identical to linear_page_index().
> + *
> + * Returns: The absolute page offset of @address within @vma.
> + */
> +static inline pgoff_t linear_folio_page_index(const struct folio *folio,
> +                                           const struct vm_area_struct *vma,
> +                                           const unsigned long address)
> +{
> +     return linear_page_index(vma, address);
> +}


I found this to be rather confusing, given that we now have a "folio" helper 
that
receives a folio and a "page" helper that doesn't receive a page ...

I guess the problem is the "page" in "linear_page_index", as it
reminds of legacy page->index.


I wonder if it would be better to have a linear_folio_index() and
force that address points at the start of the folio.

Looking below, this is exactly what we want for all except one case:


>               /* pgoff is invalid for ksm pages, but they are never large */
> -             if (folio_test_large(folio) && !folio_test_hugetlb(folio))
> -                     idx = linear_page_index(vma, pvmw.address) - pvmw.pgoff;
> +             if (folio_test_large(folio) && !folio_test_hugetlb(folio)) {
> +                     idx += linear_folio_page_index(folio, vma, 
> pvmw.address);
> +                     idx -= pvmw.pgoff;
> +             }
>               new = folio_page(folio, idx);

I think we could avoid this index work entirely by using the pfn, which is much
clearer to me, and similar to how we handle it during other rmap operations.

diff --git a/mm/migrate.c b/mm/migrate.c
index 222c8c15f782f..686351d353203 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -362,17 +362,12 @@ static bool remove_migration_pte(struct folio *folio,
                struct page *new;
                unsigned long idx = 0;

-               /* pgoff is invalid for ksm pages, but they are never large */
-               if (folio_test_large(folio) && !folio_test_hugetlb(folio))
-                       idx = linear_page_index(vma, pvmw.address) - pvmw.pgoff;
-               new = folio_page(folio, idx);
-
 #ifdef CONFIG_ARCH_HAS_PMD_SOFTLEAVES
                /* PMD-mapped THP migration entry */
                if (!pvmw.pte) {
                        VM_BUG_ON_FOLIO(folio_test_hugetlb(folio) ||
                                        !folio_test_pmd_mappable(folio), folio);
-                       remove_migration_pmd(&pvmw, new);
+                       remove_migration_pmd(&pvmw, folio_page(folio, idx));
                        continue;
                }
 #endif
@@ -385,10 +380,14 @@ static bool remove_migration_pte(struct folio *folio,
                    try_to_map_unused_to_zeropage(&pvmw, folio, old_pte, idx))
                        continue;

+               entry = softleaf_from_pte(old_pte);
+               if (folio_test_large(folio) && !folio_test_hugetlb(folio))
+                       idx = softleaf_to_pfn(entry) - 
folio_pfn(rmap_walk_arg->folio);
+               new = folio_page(folio, idx);
+
                folio_get(folio);
                pte = mk_pte(new, READ_ONCE(vma->vm_page_prot));

-               entry = softleaf_from_pte(old_pte);
                if (!softleaf_is_migration_young(entry))
                        pte = pte_mkold(pte);
                if (folio_test_dirty(folio) && softleaf_is_migration_dirty(entr


remove_migration_pmd() will work for now. Later it should just receive the folio
and do the same thing through softleaf_from_pmd() -> softleaf_to_pfn().

-- 
Cheers,

David

Reply via email to