All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dmitry Ilvokhin <d@ilvokhin.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: dan.j.williams@intel.com, Vlastimil Babka <vbabka@kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	David Hildenbrand <david@kernel.org>,
	Lorenzo Stoakes <ljs@kernel.org>,
	"Liam R. Howlett" <Liam.Howlett@oracle.com>,
	Mike Rapoport <rppt@kernel.org>,
	Suren Baghdasaryan <surenb@google.com>,
	Michal Hocko <mhocko@suse.com>,
	Brendan Jackman <jackmanb@google.com>,
	Johannes Weiner <hannes@cmpxchg.org>, Zi Yan <ziy@nvidia.com>,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	kernel-team@meta.com
Subject: Re: [PATCH 1/8] mm: use zone lock guard in reserve_highatomic_pageblock()
Date: Tue, 28 Apr 2026 10:58:41 +0000	[thread overview]
Message-ID: <afCS4d4YccQFtvpi@shell.ilvokhin.com> (raw)
In-Reply-To: <20260309164516.GE606826@noisy.programming.kicks-ass.net>

On Mon, Mar 09, 2026 at 05:45:16PM +0100, Peter Zijlstra wrote:
> On Sat, Mar 07, 2026 at 02:09:41PM +0000, Dmitry Ilvokhin wrote:
> > On Sat, Mar 07, 2026 at 02:16:41PM +0100, Peter Zijlstra wrote:
> > > On Fri, Mar 06, 2026 at 07:24:56PM +0100, Vlastimil Babka wrote:
> > > 
> > > > Yeah I don't think the guard construct in this case should be doing anything
> > > > here that wouldn't allow the compiler to compile to the exactly same result
> > > > as before? Either there's some problem with the infra, or we're just victim
> > > > of compiler heuristics. In both cases imho worth looking into rather than
> > > > rejecting the construct.
> > > 
> > > I'd love to look into it, but I can't seem to apply these patches to
> > > anything.
> > > 
> > > By virtue of not actually having the patches, I had to resort to b4, and
> > > I think the incantation is something like:
> > > 
> > >   b4 shazam cover.1772811429.git.d@ilvokhin.com
> > > 
> > > but it doesn't want to apply to anything I have at hand. Specifically, I
> > > tried Linus' tree and tip, which is most of what I have at hand.
> > 
> > Thanks for taking a look, Peter.
> > 
> > This series is based on mm-new and depends on my earlier patchset:
> > 
> > https://lore.kernel.org/all/cover.1772206930.git.d@ilvokhin.com/
> > 
> > Those patches are currently only in Andrew's mm-new tree, so this series
> > won't apply cleanly on Linus' tree or tip.
> > 
> > It should apply on top of mm-new from:
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
> 
> OK, so the big problem is __GUARD_IS_ERR(), and that came up before, but
> while Linus told me how to fix it, he didn't actually like it very much:
> 
>   https://lore.kernel.org/all/20250513085001.GC25891@noisy.programming.kicks-ass.net/
> 
> However it does help with this:
> 
> $ ./scripts/bloat-o-meter defconfig-build/mm/page_alloc-pre-gcc-16.o defconfig-build/mm/page_alloc-post-gcc-16.o | grep -v __UNIQUE
> add/remove: 24/24 grow/shrink: 3/2 up/down: 296/-224 (72)
> Function                                     old     new   delta
> get_page_from_freelist                      6158    6198     +40
> free_pcppages_bulk                           678     714     +36
> unreserve_highatomic_pageblock               708     736     +28
> make_alloc_exact                             280     264     -16
> alloc_pages_bulk_noprof                     1415    1399     -16
> Total: Before=45299, After=45371, chg +0.16%
> 
> $ ./scripts/bloat-o-meter defconfig-build/mm/page_alloc-pre-gcc-16.o defconfig-build/mm/page_alloc.o | grep -v __UNIQUE
> add/remove: 24/24 grow/shrink: 3/15 up/down: 277/-363 (-86)
> Function                                     old     new   delta
> unreserve_highatomic_pageblock               708     757     +49
> free_pcppages_bulk                           678     707     +29
> get_page_from_freelist                      6158    6165      +7
> try_to_claim_block                          1729    1726      -3
> setup_per_zone_wmarks                        656     653      -3
> free_pages_prepare                           924     921      -3
> calculate_totalreserve_pages                 282     279      -3
> alloc_frozen_pages_nolock_noprof             622     619      -3
> __free_pages_prepare                         924     921      -3
> __free_pages_ok                             1197    1194      -3
> __free_one_page                             1330    1327      -3
> __free_frozen_pages                         1303    1300      -3
> __rmqueue_pcplist                           2786    2777      -9
> free_unref_folios                           1905    1894     -11
> setup_per_zone_lowmem_reserve                388     374     -14
> make_alloc_exact                             280     264     -16
> __alloc_frozen_pages_noprof                 5411    5368     -43
> nr_free_zone_pages                           189     138     -51
> Total: Before=45299, After=45213, chg -0.19%
> 
> 
> 
> However, looking at things again, I think we can get rid of that
> unconditional __GUARD_IS_ERR(), something like the below, Dan?
> 
> This then gives:
> 
> $ ./scripts/bloat-o-meter defconfig-build/mm/page_alloc-pre-gcc-16.o defconfig-build/mm/page_alloc.o | grep -v __UNIQUE
> add/remove: 24/24 grow/shrink: 1/16 up/down: 213/-486 (-273)
> Function                                     old     new   delta
> free_pcppages_bulk                           678     699     +21
> try_to_claim_block                          1729    1723      -6
> setup_per_zone_wmarks                        656     650      -6
> free_pages_prepare                           924     918      -6
> calculate_totalreserve_pages                 282     276      -6
> alloc_frozen_pages_nolock_noprof             622     616      -6
> __free_pages_prepare                         924     918      -6
> __free_pages_ok                             1197    1191      -6
> __free_one_page                             1330    1324      -6
> __free_frozen_pages                         1303    1297      -6
> free_pages_exact                             199     183     -16
> setup_per_zone_lowmem_reserve                388     371     -17
> free_unref_folios                           1905    1888     -17
> __rmqueue_pcplist                           2786    2768     -18
> nr_free_zone_pages                           189     138     -51
> __alloc_frozen_pages_noprof                 5411    5359     -52
> get_page_from_freelist                      6158    6089     -69
> Total: Before=45299, After=45026, chg -0.60%
> 
> 
> Anyway, if you all care about the size of things -- those tracepoints
> consume *WAAY* more bytes than any of this.
> 
> 
> ---
> --- a/include/linux/cleanup.h
> +++ b/include/linux/cleanup.h
> @@ -286,15 +286,18 @@ static __always_inline _type class_##_na
>  	__no_context_analysis						\
>  { _type t = _init; return t; }
>  
> -#define EXTEND_CLASS(_name, ext, _init, _init_args...)			\
> -typedef lock_##_name##_t lock_##_name##ext##_t;			\
> +#define EXTEND_CLASS_COND(_name, ext, _cond, _init, _init_args...)	\
> +typedef lock_##_name##_t lock_##_name##ext##_t;				\
>  typedef class_##_name##_t class_##_name##ext##_t;			\
> -static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *p) \
> -{ class_##_name##_destructor(p); }					\
> +static __always_inline void class_##_name##ext##_destructor(class_##_name##_t *_T) \
> +{ if (_cond) return; class_##_name##_destructor(_T); }			\
>  static __always_inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
>  	__no_context_analysis \
>  { class_##_name##_t t = _init; return t; }
>  
> +#define EXTEND_CLASS(_name, ext, _init, _init_args...)			\
> +	EXTEND_CLASS_COND(_name, ext, 0, _init, _init_args)
> +
>  #define CLASS(_name, var)						\
>  	class_##_name##_t var __cleanup(class_##_name##_destructor) =	\
>  		class_##_name##_constructor
> @@ -394,12 +397,12 @@ static __maybe_unused const bool class_#
>  	__DEFINE_GUARD_LOCK_PTR(_name, _T)
>  
>  #define DEFINE_GUARD(_name, _type, _lock, _unlock) \
> -	DEFINE_CLASS(_name, _type, if (!__GUARD_IS_ERR(_T)) { _unlock; }, ({ _lock; _T; }), _type _T); \
> +	DEFINE_CLASS(_name, _type, if (_T) { _unlock; }, ({ _lock; _T; }), _type _T); \
>  	DEFINE_CLASS_IS_GUARD(_name)
>  
>  #define DEFINE_GUARD_COND_4(_name, _ext, _lock, _cond) \
>  	__DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true); \
> -	EXTEND_CLASS(_name, _ext, \
> +	EXTEND_CLASS_COND(_name, _ext, __GUARD_IS_ERR(*_T), \
>  		     ({ void *_t = _T; int _RET = (_lock); if (_T && !(_cond)) _t = ERR_PTR(_RET); _t; }), \
>  		     class_##_name##_t _T) \
>  	static __always_inline void * class_##_name##_ext##_lock_ptr(class_##_name##_t *_T) \
> @@ -488,7 +491,7 @@ typedef struct {							\
>  static __always_inline void class_##_name##_destructor(class_##_name##_t *_T) \
>  	__no_context_analysis						\
>  {									\
> -	if (!__GUARD_IS_ERR(_T->lock)) { _unlock; }			\
> +	if (_T->lock) { _unlock; }					\
>  }									\
>  									\
>  __DEFINE_GUARD_LOCK_PTR(_name, &_T->lock)
> @@ -565,7 +568,7 @@ __DEFINE_LOCK_GUARD_0(_name, _lock)
>  
>  #define DEFINE_LOCK_GUARD_1_COND_4(_name, _ext, _lock, _cond)		\
>  	__DEFINE_CLASS_IS_CONDITIONAL(_name##_ext, true);		\
> -	EXTEND_CLASS(_name, _ext,					\
> +	EXTEND_CLASS_COND(_name, _ext, __GUARD_IS_ERR(_T->lock),	\
>  		     ({ class_##_name##_t _t = { .lock = l }, *_T = &_t;\
>  		        int _RET = (_lock);                             \
>  		        if (_T->lock && !(_cond)) _T->lock = ERR_PTR(_RET);\

I re-tested my original patchset after rebasing and can still reproduce
the regression (though smaller). It appears to depend on compiler
inlining decisions: in some cases the compiler is able to deduplicate
the cleanup path across multiple return sites, while in others it is
not.

Given that, I think we can go further than just removing
__GUARD_IS_ERR(). It should be possible to eliminate this branch
entirely and simplify the cleanup flow.

    https://lore.kernel.org/all/20260427165037.205337-1-d@ilvokhin.com/

Reposting here to increase visibility, as several people involved in
this code have participated in this thread already.

Any feedback would be appreciated.


  parent reply	other threads:[~2026-04-28 10:58 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-06 16:05 [PATCH 0/8] mm: introduce zone lock guards Dmitry Ilvokhin
2026-03-06 16:05 ` [PATCH 1/8] mm: use zone lock guard in reserve_highatomic_pageblock() Dmitry Ilvokhin
2026-03-06 17:53   ` Andrew Morton
2026-03-06 18:00     ` Steven Rostedt
2026-03-06 18:24       ` Vlastimil Babka
2026-03-06 18:33         ` Andrew Morton
2026-03-06 18:46           ` Steven Rostedt
2026-03-07 13:16         ` Peter Zijlstra
2026-03-07 14:09           ` Dmitry Ilvokhin
2026-03-09 16:45             ` Peter Zijlstra
2026-03-10 12:57               ` Dmitry Ilvokhin
2026-03-12 23:40               ` Dan Williams
2026-03-13  8:36                 ` Peter Zijlstra
2026-03-18  8:02               ` [tip: locking/core] cleanup: Optimize guards tip-bot2 for Peter Zijlstra
2026-04-28 10:58               ` Dmitry Ilvokhin [this message]
2026-04-28 11:47                 ` [PATCH 1/8] mm: use zone lock guard in reserve_highatomic_pageblock() Peter Zijlstra
2026-04-28 13:41                   ` Dmitry Ilvokhin
2026-04-29 18:01                   ` Dmitry Ilvokhin
2026-03-26 18:04     ` Dmitry Ilvokhin
2026-03-26 18:51       ` Andrew Morton
2026-03-06 16:05 ` [PATCH 2/8] mm: use zone lock guard in unset_migratetype_isolate() Dmitry Ilvokhin
2026-03-06 16:05 ` [PATCH 3/8] mm: use zone lock guard in unreserve_highatomic_pageblock() Dmitry Ilvokhin
2026-03-06 16:10   ` Steven Rostedt
2026-03-06 16:05 ` [PATCH 4/8] mm: use zone lock guard in set_migratetype_isolate() Dmitry Ilvokhin
2026-03-06 16:05 ` [PATCH 5/8] mm: use zone lock guard in take_page_off_buddy() Dmitry Ilvokhin
2026-03-06 16:05 ` [PATCH 6/8] mm: use zone lock guard in put_page_back_buddy() Dmitry Ilvokhin
2026-03-06 16:05 ` [PATCH 7/8] mm: use zone lock guard in free_pcppages_bulk() Dmitry Ilvokhin
2026-03-06 16:05 ` [PATCH 8/8] mm: use zone lock guard in __offline_isolated_pages() Dmitry Ilvokhin
2026-03-06 16:15 ` [PATCH 0/8] mm: introduce zone lock guards Steven Rostedt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=afCS4d4YccQFtvpi@shell.ilvokhin.com \
    --to=d@ilvokhin.com \
    --cc=Liam.Howlett@oracle.com \
    --cc=akpm@linux-foundation.org \
    --cc=dan.j.williams@intel.com \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=jackmanb@google.com \
    --cc=kernel-team@meta.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=mhocko@suse.com \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=rppt@kernel.org \
    --cc=surenb@google.com \
    --cc=vbabka@kernel.org \
    --cc=ziy@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.