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 <[email protected]>
> 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
> 

Reply via email to