> On Jan 20, 2020, at 9:01 AM, David Hildenbrand <david@xxxxxxxxxx> wrote: > > On 20.01.20 14:56, Qian Cai wrote: >> >> >>> On Jan 20, 2020, at 8:38 AM, David Hildenbrand <david@xxxxxxxxxx> wrote: >>> >>> On 20.01.20 14:30, David Hildenbrand wrote: >>>> On 20.01.20 14:19, Qian Cai wrote: >>>>> It makes sense to call the WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE) >>>>> from start_isolate_page_range(), but should avoid triggering it from >>>>> userspace, i.e, from is_mem_section_removable() because it could be a >>>>> DoS if warn_on_panic is set. >>>>> >>>>> While at it, simplify the code a bit by removing an unnecessary jump >>>>> label and a local variable, so set_migratetype_isolate() could really >>>>> return a bool. >>>>> >>>>> Suggested-by: Michal Hocko <mhocko@xxxxxxxxxx> >>>>> Signed-off-by: Qian Cai <cai@xxxxxx> >>>>> --- >>>>> >>>>> v2: Improve the commit log. >>>>> Warn for all start_isolate_page_range() users not just offlining. >>>>> >>>>> mm/page_alloc.c | 11 ++++------- >>>>> mm/page_isolation.c | 30 +++++++++++++++++------------- >>>>> 2 files changed, 21 insertions(+), 20 deletions(-) >>>>> >>>>> diff --git a/mm/page_alloc.c b/mm/page_alloc.c >>>>> index 621716a25639..3c4eb750a199 100644 >>>>> --- a/mm/page_alloc.c >>>>> +++ b/mm/page_alloc.c >>>>> @@ -8231,7 +8231,7 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page, >>>>> if (is_migrate_cma(migratetype)) >>>>> return NULL; >>>>> >>>>> - goto unmovable; >>>>> + return page; >>>>> } >>>>> >>>>> for (; iter < pageblock_nr_pages; iter++) { >>>>> @@ -8241,7 +8241,7 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page, >>>>> page = pfn_to_page(pfn + iter); >>>>> >>>>> if (PageReserved(page)) >>>>> - goto unmovable; >>>>> + return page; >>>>> >>>>> /* >>>>> * If the zone is movable and we have ruled out all reserved >>>>> @@ -8261,7 +8261,7 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page, >>>>> unsigned int skip_pages; >>>>> >>>>> if (!hugepage_migration_supported(page_hstate(head))) >>>>> - goto unmovable; >>>>> + return page; >>>>> >>>>> skip_pages = compound_nr(head) - (page - head); >>>>> iter += skip_pages - 1; >>>>> @@ -8303,12 +8303,9 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page, >>>>> * is set to both of a memory hole page and a _used_ kernel >>>>> * page at boot. >>>>> */ >>>>> - goto unmovable; >>>>> + return page; >>>>> } >>>>> return NULL; >>>>> -unmovable: >>>>> - WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE); >>>>> - return pfn_to_page(pfn + iter); >>>>> } >>>>> >>>>> #ifdef CONFIG_CONTIG_ALLOC >>>>> diff --git a/mm/page_isolation.c b/mm/page_isolation.c >>>>> index e70586523ca3..31f5516f5d54 100644 >>>>> --- a/mm/page_isolation.c >>>>> +++ b/mm/page_isolation.c >>>>> @@ -15,12 +15,12 @@ >>>>> #define CREATE_TRACE_POINTS >>>>> #include <trace/events/page_isolation.h> >>>>> >>>>> -static int set_migratetype_isolate(struct page *page, int migratetype, int isol_flags) >>>>> +static bool set_migratetype_isolate(struct page *page, int migratetype, >>>>> + int isol_flags) >>>> >>>> Why this change? >>>> >>>>> { >>>>> - struct page *unmovable = NULL; >>>>> + struct page *unmovable = ERR_PTR(-EBUSY); >>>> >>>> Also, why this change? >>>> >>>>> struct zone *zone; >>>>> unsigned long flags; >>>>> - int ret = -EBUSY; >>>>> >>>>> zone = page_zone(page); >>>>> >>>>> @@ -49,21 +49,25 @@ static int set_migratetype_isolate(struct page *page, int migratetype, int isol_ >>>>> NULL); >>>>> >>>>> __mod_zone_freepage_state(zone, -nr_pages, mt); >>>>> - ret = 0; >>>>> } >>>>> >>>>> out: >>>>> spin_unlock_irqrestore(&zone->lock, flags); >>>>> - if (!ret) >>>>> + >>>>> + if (!unmovable) { >>>>> drain_all_pages(zone); >>>>> - else if ((isol_flags & REPORT_FAILURE) && unmovable) >>>>> - /* >>>>> - * printk() with zone->lock held will guarantee to trigger a >>>>> - * lockdep splat, so defer it here. >>>>> - */ >>>>> - dump_page(unmovable, "unmovable page"); >>>>> - >>>>> - return ret; >>>>> + } else { >>>>> + WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE); >>>>> + >>>>> + if ((isol_flags & REPORT_FAILURE) && !IS_ERR(unmovable)) >>>>> + /* >>>> >>>> Why this change? (!IS_ERR) >>>> >>>> >>>> Some things here look unrelated - or I am missing something :) >>>> >>> >>> FWIW, I'd prefer this change without any such cleanups (e.g., I don't >>> like returning a bool from this function and the IS_ERR handling, makes >>> the function harder to read than before) >> >> What is Michal or Andrew’s opinion? BTW, a bonus point to return a bool >> is that it helps the code robustness in general, as UBSAN will be able to >> catch any abuse. >> > > A return type of bool on a function that does not test a property > ("has_...", "is"...") is IMHO confusing. That is fine. It could be renamed to set_migratetype_is_isolate() or is_set_migratetype_isolate() which seems pretty minor because we have no consistency in the naming of this in linux kernel at all, i.e., many existing bool function names without those test of properties. > > If we have an int, it is clear that "0" means "success". With a bool > (true/false), it is not clear. > > -- > Thanks, > > David / dhildenb >