In cases where we know that the VMA is file-backed, use
vma_filebacked_address() rather than vma_address().

This lays the foundation for using the virtual page offset for anonymous
VMAs via vma_anon_address().

Also add an assert to ensure that the VMA whose address is required is not
anonymous.

No functional change intended.

Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]>
---
 mm/internal.h        | 18 ++++++++++++++++++
 mm/memory-failure.c  |  4 ++--
 mm/page_vma_mapped.c |  6 +++++-
 mm/rmap.c            | 10 ++++++----
 4 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/mm/internal.h b/mm/internal.h
index 04acfeffa066..73f90aaa979d 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1025,6 +1025,24 @@ static inline unsigned long __vma_address(const struct 
vm_area_struct *vma,
        return address;
 }
 
+/**
+ * vma_filebacked_address - Find the virtual address a file-backed page range 
is
+ * mapped at.
+ * @vma: The vma which maps this object.
+ * @pgoff: The page offset within its object.
+ * @nr_pages: The number of pages to consider.
+ *
+ * Returns: If any page in this range is mapped by this VMA, return the first
+ * address where any of these pages appear.  Otherwise, return -EFAULT.
+ */
+static inline unsigned long vma_filebacked_address(const struct vm_area_struct 
*vma,
+               pgoff_t pgoff, unsigned long nr_pages)
+{
+       VM_WARN_ON_ONCE(vma_is_anonymous(vma));
+
+       return __vma_address(vma, pgoff, vma_start_pgoff(vma), nr_pages);
+}
+
 /**
  * vma_address - Find the virtual address a page range is mapped at.
  * @vma: The vma which maps this object.
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index aaf14608b30e..a8b03e2920ba 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -620,7 +620,7 @@ static void add_to_kill_fsdax(struct task_struct *tsk, 
const struct page *p,
                              struct vm_area_struct *vma,
                              struct list_head *to_kill, pgoff_t pgoff)
 {
-       unsigned long addr = vma_address(vma, pgoff, 1);
+       unsigned long addr = vma_filebacked_address(vma, pgoff, 1);
        __add_to_kill(tsk, p, vma, to_kill, addr);
 }
 
@@ -2265,7 +2265,7 @@ static void add_to_kill_pgoff(struct task_struct *tsk,
        }
 
        /* Check for pgoff not backed by struct page */
-       tk->addr = vma_address(vma, pgoff, 1);
+       tk->addr = vma_filebacked_address(vma, pgoff, 1);
        tk->size_shift = PAGE_SHIFT;
 
        if (tk->addr == -EFAULT)
diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c
index d7670ba4147b..081e483cc7bf 100644
--- a/mm/page_vma_mapped.c
+++ b/mm/page_vma_mapped.c
@@ -356,6 +356,7 @@ unsigned long page_mapped_in_vma(const struct page *page,
                struct vm_area_struct *vma)
 {
        const struct folio *folio = page_folio(page);
+       const pgoff_t pgoff = page_pgoff(folio, page);
        struct page_vma_mapped_walk pvmw = {
                .pfn = page_to_pfn(page),
                .nr_pages = 1,
@@ -363,7 +364,10 @@ unsigned long page_mapped_in_vma(const struct page *page,
                .flags = PVMW_SYNC,
        };
 
-       pvmw.address = vma_address(vma, page_pgoff(folio, page), 1);
+       if (folio_test_anon(folio))
+               pvmw.address = vma_address(vma, pgoff, 1);
+       else
+               pvmw.address = vma_filebacked_address(vma, pgoff, 1);
        if (pvmw.address == -EFAULT)
                goto out;
        if (!page_vma_mapped_walk(&pvmw))
diff --git a/mm/rmap.c b/mm/rmap.c
index ad820fe86f7d..5798427d007f 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -865,14 +865,15 @@ unsigned long page_address_in_vma(const struct folio 
*folio,
                if (!vma->anon_vma || !anon_vma ||
                    vma->anon_vma->root != anon_vma->root)
                        return -EFAULT;
+               /* KSM folios don't reach here because of the !anon_vma check */
+               return vma_address(vma, page_pgoff(folio, page), 1);
        } else if (!vma->vm_file) {
                return -EFAULT;
        } else if (vma->vm_file->f_mapping != folio->mapping) {
                return -EFAULT;
        }
 
-       /* KSM folios don't reach here because of the !anon_vma check */
-       return vma_address(vma, page_pgoff(folio, page), 1);
+       return vma_filebacked_address(vma, page_pgoff(folio, page), 1);
 }
 
 /*
@@ -1321,7 +1322,7 @@ int pfn_mkclean_range(unsigned long pfn, unsigned long 
nr_pages, pgoff_t pgoff,
        if (invalid_mkclean_vma(vma, NULL))
                return 0;
 
-       pvmw.address = vma_address(vma, pgoff, nr_pages);
+       pvmw.address = vma_filebacked_address(vma, pgoff, nr_pages);
        VM_BUG_ON_VMA(pvmw.address == -EFAULT, vma);
 
        return page_vma_mkclean_one(&pvmw);
@@ -3100,7 +3101,8 @@ static void __rmap_walk_file(struct folio *folio, struct 
address_space *mapping,
        }
 lookup:
        mapping_rmap_tree_foreach(vma, mapping, pgoff_start, pgoff_end) {
-               unsigned long address = vma_address(vma, pgoff_start, nr_pages);
+               unsigned long address = vma_filebacked_address(vma, pgoff_start,
+                                                              nr_pages);
 
                VM_BUG_ON_VMA(address == -EFAULT, vma);
                cond_resched();

-- 
2.55.0


Reply via email to