dax_associate_entry(), dax_disassociate_entry() and dax_busy_page() each
compute dax_to_folio(entry) in the declaration, one statement before the
test that returns early when the entry is a zero entry or an empty entry.
An empty entry holds no pfn, so dax_to_folio() reads vmemmap[0].

Where the memory map starts at pfn 0 this reads a struct page that exists,
the value is discarded, and nothing shows. Where the lowest present section
is above pfn 0 there is no struct page for pfn 0 and the read faults.
grab_mapping_entry() gives the first fault on a file an empty entry, so on
such a machine every first DAX fault on a file ends in:

  BUG: unable to handle page fault for address: ffffea0000000008
  RIP: 0010:dax_to_folio+0x14/0x60
   dax_insert_entry+0xb2/0x3c0
   dax_fault_iter+0x200/0x600
   dax_iomap_pte_fault+0x193/0x3d0

Found on a kernel that boots on one high region of system RAM, which has
no struct page for the memory below it.

Move each call after the early return. The other callers of dax_to_folio()
in this file already only run for an entry that holds a pfn.

Fixes: 38607c62b34b ("fs/dax: properly refcount fs dax pages")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Kiara Grouwstra <[email protected]>
---
 fs/dax.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/dax.c b/fs/dax.c
index 6ba50142eeb2..90305996b106 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -480,11 +480,12 @@ static void dax_associate_entry(void *entry, struct 
address_space *mapping,
                                unsigned long address, bool shared)
 {
        unsigned long size = dax_entry_size(entry), index;
-       struct folio *folio = dax_to_folio(entry);
+       struct folio *folio;
 
        if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry))
                return;
 
+       folio = dax_to_folio(entry);
        index = linear_page_index(vma, address & ~(size - 1));
        if (shared && (folio->mapping || dax_folio_is_shared(folio))) {
                if (folio->mapping)
@@ -505,21 +506,20 @@ static void dax_associate_entry(void *entry, struct 
address_space *mapping,
 static void dax_disassociate_entry(void *entry, struct address_space *mapping,
                                bool trunc)
 {
-       struct folio *folio = dax_to_folio(entry);
-
        if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry))
                return;
 
-       dax_folio_put(folio);
+       dax_folio_put(dax_to_folio(entry));
 }
 
 static struct page *dax_busy_page(void *entry)
 {
-       struct folio *folio = dax_to_folio(entry);
+       struct folio *folio;
 
        if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry))
                return NULL;
 
+       folio = dax_to_folio(entry);
        if (folio_ref_count(folio) - folio_mapcount(folio))
                return &folio->page;
        else
-- 
2.55.0


Reply via email to