On Mon, Oct 26, 2020 at 06:33:56PM +0100, Vlastimil Babka wrote: > Enabling page_poison=1 together with init_on_alloc=1 or init_on_free=1 produces > a warning in dmesg that page_poison takes precendence. However, as these ^ precedence > warnings are printed in early_param handlers for init_on_alloc/free, they are > not printed if page_poison is enabled later on the command line (handlers are > called in the order of their parameters), or when init_on_alloc/free is always > enabled by the respective config option - before the page_poison early param > handler is called, it is not considered to be enabled. This is inconsistent. > > We can remove the dependency on order by making the init_on_* parameters only > set a boolean variable, and postponing the evaluation after all early params > have been processed. Introduce a new init_mem_debugging() function for that, > and move the related debug_pagealloc processing there as well. > > As a result init_mem_debugging() knows always accurately if init_on_* and/or > page_poison options were enabled. Thus we can also optimize want_init_on_alloc() > and want_init_on_free(). We don't need to check page_poisoning_enabled() there, > we can instead not enable the init_on_* tracepoint at all, if page poisoning is > enabled. This results in a simpler and more effective code. > > Signed-off-by: Vlastimil Babka <vbabka@xxxxxxx> With two more nits below fixed Reviewed-by: Mike Rapoport <rppt@xxxxxxxxxxxxx> > --- > include/linux/mm.h | 20 ++-------- > init/main.c | 2 +- > mm/page_alloc.c | 94 +++++++++++++++++++++++----------------------- > 3 files changed, 50 insertions(+), 66 deletions(-) > ... > @@ -792,6 +752,44 @@ static inline void clear_page_guard(struct zone *zone, struct page *page, > unsigned int order, int migratetype) {} > #endif > > +/* > + * Enable static keys related to various memory debugging and hardening options. > + * Some override others, and depend on early params that are evaluated in the > + * order of appearance. So we need to first gather the full picture of what was > + * enabled, and then make decisions. > + */ > +void init_mem_debugging() Shouldn't it be init_mem_debug(void)? Or whatever a new name would be :) > +{ > + if (_init_on_alloc_enabled_early) { > + if (page_poisoning_enabled()) { > + pr_info("mem auto-init: CONFIG_PAGE_POISONING is on, " > + "will take precedence over init_on_alloc\n"); > + } else { > + static_branch_enable(&init_on_alloc); > + } > + } > + if (_init_on_free_enabled_early) { > + if (page_poisoning_enabled()) { > + pr_info("mem auto-init: CONFIG_PAGE_POISONING is on, " > + "will take precedence over init_on_free\n"); > + } else { > + static_branch_enable(&init_on_free); > + } > + } I think the braces for the inner ifs are not required. > + > +#ifdef CONFIG_DEBUG_PAGEALLOC > + if (!debug_pagealloc_enabled()) > + return; > + > + static_branch_enable(&_debug_pagealloc_enabled); > + > + if (!debug_guardpage_minorder()) > + return; > + > + static_branch_enable(&_debug_guardpage_enabled); > +#endif > +} > + > static inline void set_buddy_order(struct page *page, unsigned int order) > { > set_page_private(page, order); > -- > 2.29.0 > > -- Sincerely yours, Mike.