Linux filesystem development
 help / color / mirror / Atom feed
* [PATCH] fs/dax: get the folio of an entry only after the entry has one
@ 2026-09-01 19:56 Kiara Grouwstra
  2026-09-01 20:51 ` Andrew Morton
  0 siblings, 1 reply; 2+ messages in thread
From: Kiara Grouwstra @ 2026-09-01 19:56 UTC (permalink / raw)
  To: Dan Williams, Christian Brauner, Alexander Viro
  Cc: Alistair Popple, David Hildenbrand, Andrew Morton, Jan Kara,
	Matthew Wilcox, linux-fsdevel, nvdimm, linux-kernel,
	Kiara Grouwstra

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 <cinereal@riseup.net>
---
 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


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] fs/dax: get the folio of an entry only after the entry has one
  2026-09-01 19:56 [PATCH] fs/dax: get the folio of an entry only after the entry has one Kiara Grouwstra
@ 2026-09-01 20:51 ` Andrew Morton
  0 siblings, 0 replies; 2+ messages in thread
From: Andrew Morton @ 2026-09-01 20:51 UTC (permalink / raw)
  To: Kiara Grouwstra
  Cc: Dan Williams, Christian Brauner, Alexander Viro, Alistair Popple,
	David Hildenbrand, Jan Kara, Matthew Wilcox, linux-fsdevel,
	nvdimm, linux-kernel, Seunguk Shin

On Tue,  1 Sep 2026 21:56:58 +0200 Kiara Grouwstra <cinereal@riseup.net> wrote:

> 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.
> 

Thanks.  This is near-identical to
https://lore.kernel.org/all/m2y0enxtzk.fsf@arm.com/, which I have
queued for 7.3-rcX, with cc:stable.

Seunguk's fix was set a month ago, but balls were dropped :(


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-01 20:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01 19:56 [PATCH] fs/dax: get the folio of an entry only after the entry has one Kiara Grouwstra
2026-09-01 20:51 ` Andrew Morton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox