[PATCH 12/25] mm/fbatch: remove percpu_pvec_drained and folios_put()
From: Hugh Dickins
Date: Mon Aug 24 2026 - 10:25:44 EST
Remove the percpu_pvec_drained field from folio_batch, and its only use
in __folio_batch_release(): remove that now pointless lru_add_drain().
Which leaves __folio_batch_release() as an exported name for folios_put()
which is itself just a wrapper for folios_put_refs(): mm/mlock.c and
mm/folio.c don't need such a wrapper, just say folios_put_refs(,NULL).
Or should folios_put() be the export? But __folio_batch_release() is what
drivers/gpu and net/sunrpc are using: don't change them in this series.
Signed-off-by: Hugh Dickins <hughd@xxxxxxxxxx>
---
include/linux/folio_batch.h | 2 --
include/linux/mm.h | 18 ------------------
mm/folio.c | 17 +++--------------
mm/mlock.c | 2 +-
4 files changed, 4 insertions(+), 35 deletions(-)
diff --git a/include/linux/folio_batch.h b/include/linux/folio_batch.h
index e1cc8ae023f1..a3337f70e109 100644
--- a/include/linux/folio_batch.h
+++ b/include/linux/folio_batch.h
@@ -27,7 +27,6 @@ struct folio;
struct folio_batch {
unsigned char nr;
unsigned char i;
- bool percpu_pvec_drained;
struct folio *folios[FOLIO_BATCH_SIZE];
};
@@ -41,7 +40,6 @@ static inline void folio_batch_init(struct folio_batch *fbatch)
{
fbatch->nr = 0;
fbatch->i = 0;
- fbatch->percpu_pvec_drained = false;
}
static inline void folio_batch_reinit(struct folio_batch *fbatch)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 87feaa5a2b78..a426f7351787 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2201,24 +2201,6 @@ typedef union {
void release_pages(release_pages_arg, int nr);
-/**
- * folios_put - Decrement the reference count on an array of folios.
- * @folios: The folios.
- *
- * Like folio_put(), but for a batch of folios. This is more efficient
- * than writing the loop yourself as it will optimise the locks which need
- * to be taken if the folios are freed. The folios batch is returned
- * empty and ready to be reused for another batch; there is no need to
- * reinitialise it.
- *
- * Context: May be called in process or interrupt context, but not in NMI
- * context. May be called while holding a spinlock.
- */
-static inline void folios_put(struct folio_batch *folios)
-{
- folios_put_refs(folios, NULL);
-}
-
static inline void put_page(struct page *page)
{
struct folio *folio = page_folio(page);
diff --git a/mm/folio.c b/mm/folio.c
index fa4cf9d7d51b..782b8245d213 100644
--- a/mm/folio.c
+++ b/mm/folio.c
@@ -159,7 +159,7 @@ static void folio_batch_move_lru(struct folio_batch *fbatch, move_fn_t move_fn)
if (lruvec)
lruvec_unlock_irqrestore(lruvec, flags);
- folios_put(fbatch);
+ folios_put_refs(fbatch, NULL);
}
static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch,
@@ -1062,22 +1062,11 @@ void release_pages(release_pages_arg arg, int nr)
EXPORT_SYMBOL(release_pages);
/*
- * The folios which we're about to release may be in the deferred lru-addition
- * queues. That would prevent them from really being freed right now. That's
- * OK from a correctness point of view but is inefficient - those folios may be
- * cache-warm and we want to give them back to the page allocator ASAP.
- *
- * So __folio_batch_release() will drain those queues here.
- * folio_batch_move_lru() calls folios_put() directly to avoid
- * mutual recursion.
+ * This used to optimize with a drain before putting: no longer helpful.
*/
void __folio_batch_release(struct folio_batch *fbatch)
{
- if (!fbatch->percpu_pvec_drained) {
- lru_add_drain();
- fbatch->percpu_pvec_drained = true;
- }
- folios_put(fbatch);
+ folios_put_refs(fbatch, NULL);
}
EXPORT_SYMBOL(__folio_batch_release);
diff --git a/mm/mlock.c b/mm/mlock.c
index 1050010bbe0b..97134eff6b56 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -191,7 +191,7 @@ static void mlock_folio_batch(struct folio_batch *fbatch)
if (lruvec)
lruvec_unlock_irq(lruvec);
- folios_put(fbatch);
+ folios_put_refs(fbatch, NULL);
}
void mlock_drain_local(void)
--
2.51.0