Re: [PATCH resend v6 28/30] mm: add put_page_zeroed and folio_put_zeroed
From: Gregory Price
Date: Tue May 12 2026 - 12:11:27 EST
On Mon, May 11, 2026 at 05:04:19AM -0400, Michael S. Tsirkin wrote:
> Add put_page_zeroed() / folio_put_zeroed() for callers that hold
> a reference to a page known to be zeroed.
>
> If this drops the last reference, the page goes through
> __folio_put_zeroed() which calls free_frozen_pages_zeroed() so
> the zeroed hint is preserved. If someone else still holds a
> reference, the hint is simply lost - this is best-effort.
>
> This is useful for balloon drivers during deflation: the host
> has already zeroed the pages, and the balloon is typically the
> sole owner. But if the page happens to be shared, silently
> dropping the hint is safe and avoids the need for callers to
> check the refcount.
>
I see this gets used in mm/balloon.c not the driver itself,
should these be in include/linux/mm.h or mm/internal.h ?
Just wondering the utility of this being exported for drivers.
> Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx>
> Assisted-by: Claude:claude-opus-4-6
> ---
> include/linux/mm.h | 12 ++++++++++++
> mm/swap.c | 18 ++++++++++++++++--
> 2 files changed, 28 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 3b1ca90fd435..4c51b7bd7576 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -1913,6 +1913,7 @@ static inline struct folio *virt_to_folio(const void *x)
> }
>
> void __folio_put(struct folio *folio);
> +void __folio_put_zeroed(struct folio *folio);
>
> void split_page(struct page *page, unsigned int order);
> void folio_copy(struct folio *dst, struct folio *src);
> @@ -2090,6 +2091,17 @@ static inline void folio_put(struct folio *folio)
> __folio_put(folio);
> }
>
> +static inline void folio_put_zeroed(struct folio *folio)
> +{
> + if (folio_put_testzero(folio))
> + __folio_put_zeroed(folio);
> +}
> +
> +static inline void put_page_zeroed(struct page *page)
> +{
> + folio_put_zeroed(page_folio(page));
> +}
> +
> /**
> * folio_put_refs - Reduce the reference count on a folio.
> * @folio: The folio.
> diff --git a/mm/swap.c b/mm/swap.c
> index 5cc44f0de987..8d57223dfe34 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -94,7 +94,7 @@ static void page_cache_release(struct folio *folio)
> lruvec_unlock_irqrestore(lruvec, flags);
> }
>
> -void __folio_put(struct folio *folio)
> +static void ___folio_put(struct folio *folio, bool zeroed)
> {
> if (unlikely(folio_is_zone_device(folio))) {
> free_zone_device_folio(folio);
> @@ -109,10 +109,24 @@ void __folio_put(struct folio *folio)
> page_cache_release(folio);
> folio_unqueue_deferred_split(folio);
> mem_cgroup_uncharge(folio);
> - free_frozen_pages(&folio->page, folio_order(folio));
> + if (zeroed)
> + free_frozen_pages_zeroed(&folio->page, folio_order(folio));
> + else
> + free_frozen_pages(&folio->page, folio_order(folio));
> +}
> +
> +void __folio_put(struct folio *folio)
> +{
> + ___folio_put(folio, false);
> }
> EXPORT_SYMBOL(__folio_put);
>
> +void __folio_put_zeroed(struct folio *folio)
> +{
> + ___folio_put(folio, true);
> +}
> +EXPORT_SYMBOL(__folio_put_zeroed);
> +
> typedef void (*move_fn_t)(struct lruvec *lruvec, struct folio *folio);
>
> static void lru_add(struct lruvec *lruvec, struct folio *folio)
> --
> MST
>