FAILED: patch "[PATCH] mm: call ->free_folio() directly in folio_unmap_invalidate()" failed to apply to 6.18-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 615d9bb2ccad42f9e21d837431e401db2e471195
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026042002-idealness-evade-7213@gregkh' --subject-prefix 'PATCH 6.18.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 615d9bb2ccad42f9e21d837431e401db2e471195 Mon Sep 17 00:00:00 2001
From: "Matthew Wilcox (Oracle)" <[email protected]>
Date: Mon, 13 Apr 2026 19:43:11 +0100
Subject: [PATCH] mm: call ->free_folio() directly in folio_unmap_invalidate()
We can only call filemap_free_folio() if we have a reference to (or hold a lock on) the mapping. Otherwise, we've already removed the folio from the mapping so it no longer pins the mapping and the mapping can be removed, causing a use-after-free when accessing mapping->a_ops.
Follow the same pattern as __remove_mapping() and load the free_folio function pointer before dropping the lock on the mapping. That lets us make filemap_free_folio() static as this was the only caller outside filemap.c.
mm/filemap.c +2 -1
@@ -228,7 +228,8 @@ void __filemap_remove_folio(struct folio *folio, void *shadow)page_cache_delete (mapping, folio, shadow); } -void filemap_free_folio (struct address_space *mapping,struct folio *folio) +static void filemap_free_folio (const struct address_space *mapping, +struct folio *folio) {void (*free_folio)(struct folio *);
mm/internal.h +0 -1
@@ -540,7 +540,6 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t *start, pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices);unsigned find_get_entries (struct address_space *mapping,pgoff_t *start,pgoff_t end,struct folio_batch *fbatch,pgoff_t *indices); -void filemap_free_folio (struct address_space *mapping,struct folio *folio);int truncate_inode_folio (struct address_space *mapping,struct folio *folio);bool truncate_inode_partial_folio (struct folio *folio,loff_t start,loff_t end);
mm/truncate.c +5 -1
@@ -622,6 +622,7 @@ static int folio_launder(struct address_space *mapping, struct folio *folio)int folio_unmap_invalidate (struct address_space *mapping,struct folio *folio,gfp_t gfp) { +void (*free_folio)(struct folio *);int ret;VM_BUG_ON_FOLIO (!folio_test_locked (folio), folio);
@@ -648,9 +649,12 @@ int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio,xa_unlock_irq (&mapping->i_pages);if (mapping_shrinkable (mapping))inode_lru_list_add (mapping->host); + free_folio = mapping->a_ops->free_folio;spin_unlock (&mapping->host->i_lock); -filemap_free_folio (mapping, folio); +if (free_folio) +free_folio (folio); +folio_put_refs (folio,folio_nr_pages (folio));return 1 ; failed:xa_unlock_irq (&mapping->i_pages);
Matthew Wilcox (Oracle)
maintainerPATCH 1/1 mm: call ->free_folio() directly in folio_unmap_invalidate()
We can only call filemap_free_folio() if we have a reference to (or hold a lock on) the mapping. Otherwise, we've already removed the folio from the mapping so it no longer pins the mapping and the mapping can be removed, causing a use-after-free when accessing mapping->a_ops.
Follow the same pattern as __remove_mapping() and load the free_folio function pointer before dropping the lock on the mapping. That lets us make filemap_free_folio() static as this was the only caller outside filemap.c.
--- mm/filemap.c | 3 ++- mm/internal.h | 1 - mm/truncate.c | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-)
mm/filemap.c +2 -1
@@ -233,7 +233,8 @@ void __filemap_remove_folio(struct folio *folio, void *shadow)page_cache_delete (mapping, folio, shadow); } -void filemap_free_folio (struct address_space *mapping,struct folio *folio) +static void filemap_free_folio (const struct address_space *mapping, +struct folio *folio) {void (*free_folio)(struct folio *);int refs =1 ;
mm/internal.h +0 -1
@@ -401,7 +401,6 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t *start, pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices);unsigned find_get_entries (struct address_space *mapping,pgoff_t *start,pgoff_t end,struct folio_batch *fbatch,pgoff_t *indices); -void filemap_free_folio (struct address_space *mapping,struct folio *folio);int truncate_inode_folio (struct address_space *mapping,struct folio *folio);bool truncate_inode_partial_folio (struct folio *folio,loff_t start,loff_t end);
mm/truncate.c +5 -1
@@ -574,6 +574,7 @@ EXPORT_SYMBOL(invalidate_mapping_pages);static int invalidate_complete_folio2 (struct address_space *mapping,struct folio *folio) { +void (*free_folio)(struct folio *);if (folio->mapping != mapping)return 0 ;
@@ -590,9 +591,12 @@ static int invalidate_complete_folio2(struct address_space *mapping,xa_unlock_irq (&mapping->i_pages);if (mapping_shrinkable (mapping))inode_add_lru (mapping->host); + free_folio = mapping->a_ops->free_folio;spin_unlock (&mapping->host->i_lock); -filemap_free_folio (mapping, folio); +if (free_folio) +free_folio (folio); +folio_put_refs (folio,folio_nr_pages (folio));return 1 ; failed:xa_unlock_irq (&mapping->i_pages);
Signature · 1 line
2.47.3
Greg KH
maintainerRe: [PATCH 6.18.y] mm: call ->free_folio() directly in folio_unmap_invalidate()
Quoted 20 lines · Matthew Wilcox (Oracle)
We can only call
filemap_free_folio()if we have a reference to (or hold a lock on) the mapping. Otherwise, we've already removed the folio from the mapping so it no longer pins the mapping and the mapping can be removed, causing a use-after-free when accessingmapping->a_ops.Follow the same pattern as
__remove_mapping()and load thefree_foliofunction pointer before dropping the lock on the mapping. That lets us makefilemap_free_folio()static as this was the only caller outsidefilemap.c.Fixes fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes")Signed-off-by Matthew Wilcox (Oracle) <[email protected]>Reported-by Google Big Sleep <[email protected]>Cc Jens Axboe <[email protected]>Cc Jan Kara <[email protected]>Cc <[email protected]>Signed-off-by Andrew Morton <[email protected]>(cherry picked from commit 615d9bb2ccad42f9e21d837431e401db2e471195)Signed-off-by Matthew Wilcox (Oracle) <[email protected]>
Quoted 5 lines
--- mm/filemap.c | 3 ++- mm/internal.h | 1 - mm/truncate.c | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-)
This is odd, it's applying with a ton of fuzz, which puts things in the wrong functions and breaks the build. Let me go fix it up by hand...
thanks,
greg k-h
Greg KH
maintainerRe: [PATCH 6.18.y] mm: call ->free_folio() directly in folio_unmap_invalidate()
In reply to Matthew Wilcox (Oracle)Quoted 65 lines · Matthew Wilcox (Oracle)
We can only call
filemap_free_folio()if we have a reference to (or hold a lock on) the mapping. Otherwise, we've already removed the folio from the mapping so it no longer pins the mapping and the mapping can be removed, causing a use-after-free when accessingmapping->a_ops.Follow the same pattern as
__remove_mapping()and load thefree_foliofunction pointer before dropping the lock on the mapping. That lets us makefilemap_free_folio()static as this was the only caller outsidefilemap.c.Fixes fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes")Signed-off-by Matthew Wilcox (Oracle) <[email protected]>Reported-by Google Big Sleep <[email protected]>Cc Jens Axboe <[email protected]>Cc Jan Kara <[email protected]>Cc <[email protected]>Signed-off-by Andrew Morton <[email protected]>(cherry picked from commit 615d9bb2ccad42f9e21d837431e401db2e471195)Signed-off-by Matthew Wilcox (Oracle) <[email protected]>--- mm/filemap.c | 3 ++- mm/internal.h | 1 - mm/truncate.c | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-)mm/filemap.c +2
-1@@ -233,7 +233,8 @@ void __filemap_remove_folio(struct folio *folio, void *shadow)page_cache_delete (mapping, folio, shadow); } -void filemap_free_folio (struct address_space *mapping,struct folio *folio) +static void filemap_free_folio (const struct address_space *mapping, +struct folio *folio) {void (*free_folio)(struct folio *);int refs =1 ;mm/internal.h +0
-1@@ -401,7 +401,6 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t *start, pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices);unsigned find_get_entries (struct address_space *mapping,pgoff_t *start,pgoff_t end,struct folio_batch *fbatch,pgoff_t *indices); -void filemap_free_folio (struct address_space *mapping,struct folio *folio);int truncate_inode_folio (struct address_space *mapping,struct folio *folio);bool truncate_inode_partial_folio (struct folio *folio,loff_t start,loff_t end);mm/truncate.c +1
-0@@ -574,6 +574,7 @@ EXPORT_SYMBOL(invalidate_mapping_pages);static int invalidate_complete_folio2 (struct address_space *mapping,struct folio *folio) { +void (*free_folio)(struct folio *);if (folio->mapping != mapping)return 0 ;
mm/truncate.c static int invalidate_complete_folio2(struct address_space *mapping, · line 594
Quoted 4 lines
mm/truncate.c +1
-0@@ -590,9 +591,12 @@ static int invalidate_complete_folio2(struct address_space *mapping,xa_unlock_irq (&mapping->i_pages);if (mapping_shrinkable (mapping))inode_add_lru (mapping->host); + free_folio = mapping->a_ops->free_folio;
Wait, I see what's wrong, this function isn't even in 6.18.y, which is why when I apply this it has fuzz and blows up.
So this isn't going to work at all here, did you send the wrong backport?
thanks,
greg k-h
Matthew Wilcox
maintainerRe: [PATCH 6.18.y] mm: call ->free_folio() directly in folio_unmap_invalidate()
Quoted 15 lines · Greg KH
Quoted 5 lines · Matthew Wilcox (Oracle)
We can only call
filemap_free_folio()if we have a reference to (or hold a lock on) the mapping. Otherwise, we've already removed the folio from the mapping so it no longer pins the mapping and the mapping can be removed, causing a use-after-free when accessingmapping->a_ops.Quoted 8 lines
Follow the same pattern as
__remove_mapping()and load thefree_foliofunction pointer before dropping the lock on the mapping. That lets us makefilemap_free_folio()static as this was the only caller outsidefilemap.c.Fixes fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes")Signed-off-by Matthew Wilcox (Oracle) <[email protected]>
Quoted 5 lines
Wait, I see what's wrong, this function isn't even in 6.18.y, which is why when I apply this it has fuzz and blows up.
So this isn't going to work at all here, did you send the wrong backport?
Oh blimey. Somehow I did the backport to 6.12.y. Sorry about that; I'll do 6.18 now.
Matthew Wilcox (Oracle)
maintainerPATCH 1/1 mm: call ->free_folio() directly in folio_unmap_invalidate()
In reply to [email protected]We can only call filemap_free_folio() if we have a reference to (or hold a lock on) the mapping. Otherwise, we've already removed the folio from the mapping so it no longer pins the mapping and the mapping can be removed, causing a use-after-free when accessing mapping->a_ops.
Follow the same pattern as __remove_mapping() and load the free_folio function pointer before dropping the lock on the mapping. That lets us make filemap_free_folio() static as this was the only caller outside filemap.c.
--- mm/filemap.c | 3 ++- mm/internal.h | 1 - mm/truncate.c | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-)
mm/filemap.c +2 -1
@@ -227,7 +227,8 @@ void __filemap_remove_folio(struct folio *folio, void *shadow)page_cache_delete (mapping, folio, shadow); } -void filemap_free_folio (struct address_space *mapping,struct folio *folio) +static void filemap_free_folio (const struct address_space *mapping, +struct folio *folio) {void (*free_folio)(struct folio *);
mm/internal.h +0 -1
@@ -471,7 +471,6 @@ unsigned find_lock_entries(struct address_space *mapping, pgoff_t *start, pgoff_t end, struct folio_batch *fbatch, pgoff_t *indices);unsigned find_get_entries (struct address_space *mapping,pgoff_t *start,pgoff_t end,struct folio_batch *fbatch,pgoff_t *indices); -void filemap_free_folio (struct address_space *mapping,struct folio *folio);int truncate_inode_folio (struct address_space *mapping,struct folio *folio);bool truncate_inode_partial_folio (struct folio *folio,loff_t start,loff_t end);
mm/truncate.c +5 -1
@@ -622,6 +622,7 @@ static int folio_launder(struct address_space *mapping, struct folio *folio)int folio_unmap_invalidate (struct address_space *mapping,struct folio *folio,gfp_t gfp) { +void (*free_folio)(struct folio *);int ret;VM_BUG_ON_FOLIO (!folio_test_locked (folio), folio);
@@ -648,9 +649,12 @@ int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio,xa_unlock_irq (&mapping->i_pages);if (mapping_shrinkable (mapping))inode_add_lru (mapping->host); + free_folio = mapping->a_ops->free_folio;spin_unlock (&mapping->host->i_lock); -filemap_free_folio (mapping, folio); +if (free_folio) +free_folio (folio); +folio_put_refs (folio,folio_nr_pages (folio));return 1 ; failed:xa_unlock_irq (&mapping->i_pages);
Signature · 1 line
2.47.3
Sasha Levin
maintainerRe: [PATCH 6.18.y] mm: call ->free_folio() directly in folio_unmap_invalidate()
Quoted 9 lines · Matthew Wilcox (Oracle)
We can only call
filemap_free_folio()if we have a reference to (or hold a lock on) the mapping. Otherwise, we've already removed the folio from the mapping so it no longer pins the mapping and the mapping can be removed, causing a use-after-free when accessingmapping->a_ops.Follow the same pattern as
__remove_mapping()and load thefree_foliofunction pointer before dropping the lock on the mapping. That lets us makefilemap_free_folio()static as this was the only caller outsidefilemap.c.
Thanks, queued for 6.18.y.
--
Thanks,
Sasha