Use the newly introduced zone_lock_irqsave lock guard in reserve_highatomic_pageblock() to replace the explicit lock/unlock and goto out_unlock pattern with automatic scope-based cleanup. Suggested-by: Steven Rostedt Signed-off-by: Dmitry Ilvokhin --- include/linux/mmzone_lock.h | 9 +++++++++ mm/page_alloc.c | 13 +++++-------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/linux/mmzone_lock.h b/include/linux/mmzone_lock.h index 6bd8b026029f..fe399a4505ba 100644 --- a/include/linux/mmzone_lock.h +++ b/include/linux/mmzone_lock.h @@ -97,4 +97,13 @@ static inline void zone_unlock_irq(struct zone *zone) spin_unlock_irq(&zone->_lock); } +DEFINE_LOCK_GUARD_1(zone_lock_irqsave, struct zone, + zone_lock_irqsave(_T->lock, _T->flags), + zone_unlock_irqrestore(_T->lock, _T->flags), + unsigned long flags) +DECLARE_LOCK_GUARD_1_ATTRS(zone_lock_irqsave, + __acquires(_T), __releases(*(struct zone **)_T)) +#define class_zone_lock_irqsave_constructor(_T) \ + WITH_LOCK_GUARD_1_ATTRS(zone_lock_irqsave, _T) + #endif /* _LINUX_MMZONE_LOCK_H */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 75ee81445640..260fb003822a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3407,7 +3407,7 @@ static void reserve_highatomic_pageblock(struct page *page, int order, struct zone *zone) { int mt; - unsigned long max_managed, flags; + unsigned long max_managed; /* * The number reserved as: minimum is 1 pageblock, maximum is @@ -3421,29 +3421,26 @@ static void reserve_highatomic_pageblock(struct page *page, int order, if (zone->nr_reserved_highatomic >= max_managed) return; - zone_lock_irqsave(zone, flags); + guard(zone_lock_irqsave)(zone); /* Recheck the nr_reserved_highatomic limit under the lock */ if (zone->nr_reserved_highatomic >= max_managed) - goto out_unlock; + return; /* Yoink! */ mt = get_pageblock_migratetype(page); /* Only reserve normal pageblocks (i.e., they can merge with others) */ if (!migratetype_is_mergeable(mt)) - goto out_unlock; + return; if (order < pageblock_order) { if (move_freepages_block(zone, page, mt, MIGRATE_HIGHATOMIC) == -1) - goto out_unlock; + return; zone->nr_reserved_highatomic += pageblock_nr_pages; } else { change_pageblock_range(page, order, MIGRATE_HIGHATOMIC); zone->nr_reserved_highatomic += 1 << order; } - -out_unlock: - zone_unlock_irqrestore(zone, flags); } /* -- 2.47.3 Use zone_lock_irqsave lock guard in unset_migratetype_isolate() to replace the explicit lock/unlock and goto pattern with automatic scope-based cleanup. Suggested-by: Steven Rostedt Signed-off-by: Dmitry Ilvokhin --- mm/page_isolation.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mm/page_isolation.c b/mm/page_isolation.c index e8414e9a718a..dc1e18124228 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -224,15 +224,14 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode, static void unset_migratetype_isolate(struct page *page) { struct zone *zone; - unsigned long flags; bool isolated_page = false; unsigned int order; struct page *buddy; zone = page_zone(page); - zone_lock_irqsave(zone, flags); + guard(zone_lock_irqsave)(zone); if (!is_migrate_isolate_page(page)) - goto out; + return; /* * Because freepage with more than pageblock_order on isolated @@ -280,8 +279,6 @@ static void unset_migratetype_isolate(struct page *page) __putback_isolated_page(page, order, get_pageblock_migratetype(page)); } zone->nr_isolate_pageblock--; -out: - zone_unlock_irqrestore(zone, flags); } static inline struct page * -- 2.47.3 Use zone_lock_irqsave lock guard in unreserve_highatomic_pageblock() to replace the explicit lock/unlock pattern with automatic scope-based cleanup. Suggested-by: Steven Rostedt Signed-off-by: Dmitry Ilvokhin --- mm/page_alloc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 260fb003822a..2857daf6ebfd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3456,7 +3456,6 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac, bool force) { struct zonelist *zonelist = ac->zonelist; - unsigned long flags; struct zoneref *z; struct zone *zone; struct page *page; @@ -3473,7 +3472,7 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac, pageblock_nr_pages) continue; - zone_lock_irqsave(zone, flags); + guard(zone_lock_irqsave)(zone); for (order = 0; order < NR_PAGE_ORDERS; order++) { struct free_area *area = &(zone->free_area[order]); unsigned long size; @@ -3521,11 +3520,9 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac, */ WARN_ON_ONCE(ret == -1); if (ret > 0) { - zone_unlock_irqrestore(zone, flags); return ret; } } - zone_unlock_irqrestore(zone, flags); } return false; -- 2.47.3 Use zone_lock_irqsave scoped lock guard in set_migratetype_isolate() to replace the explicit lock/unlock pattern with automatic scope-based cleanup. The scoped variant is used to keep dump_page() outside the locked section to avoid a lockdep splat. Suggested-by: Steven Rostedt Signed-off-by: Dmitry Ilvokhin --- mm/page_isolation.c | 60 ++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/mm/page_isolation.c b/mm/page_isolation.c index dc1e18124228..e7f006e8870c 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -168,48 +168,40 @@ static int set_migratetype_isolate(struct page *page, enum pb_isolate_mode mode, { struct zone *zone = page_zone(page); struct page *unmovable; - unsigned long flags; unsigned long check_unmovable_start, check_unmovable_end; if (PageUnaccepted(page)) accept_page(page); - zone_lock_irqsave(zone, flags); - - /* - * We assume the caller intended to SET migrate type to isolate. - * If it is already set, then someone else must have raced and - * set it before us. - */ - if (is_migrate_isolate_page(page)) { - zone_unlock_irqrestore(zone, flags); - return -EBUSY; - } - - /* - * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself. - * We just check MOVABLE pages. - * - * Pass the intersection of [start_pfn, end_pfn) and the page's pageblock - * to avoid redundant checks. - */ - check_unmovable_start = max(page_to_pfn(page), start_pfn); - check_unmovable_end = min(pageblock_end_pfn(page_to_pfn(page)), - end_pfn); - - unmovable = has_unmovable_pages(check_unmovable_start, check_unmovable_end, - mode); - if (!unmovable) { - if (!pageblock_isolate_and_move_free_pages(zone, page)) { - zone_unlock_irqrestore(zone, flags); + scoped_guard(zone_lock_irqsave, zone) { + /* + * We assume the caller intended to SET migrate type to + * isolate. If it is already set, then someone else must have + * raced and set it before us. + */ + if (is_migrate_isolate_page(page)) return -EBUSY; + + /* + * FIXME: Now, memory hotplug doesn't call shrink_slab() by + * itself. We just check MOVABLE pages. + * + * Pass the intersection of [start_pfn, end_pfn) and the page's + * pageblock to avoid redundant checks. + */ + check_unmovable_start = max(page_to_pfn(page), start_pfn); + check_unmovable_end = min(pageblock_end_pfn(page_to_pfn(page)), + end_pfn); + + unmovable = has_unmovable_pages(check_unmovable_start, + check_unmovable_end, mode); + if (!unmovable) { + if (!pageblock_isolate_and_move_free_pages(zone, page)) + return -EBUSY; + zone->nr_isolate_pageblock++; + return 0; } - zone->nr_isolate_pageblock++; - zone_unlock_irqrestore(zone, flags); - return 0; } - - zone_unlock_irqrestore(zone, flags); if (mode == PB_ISOLATE_MODE_MEM_OFFLINE) { /* * printk() with zone lock held will likely trigger a -- 2.47.3 Use zone_lock_irqsave lock guard in take_page_off_buddy() to replace the explicit lock/unlock pattern with automatic scope-based cleanup. This also allows to return directly from the loop, removing the 'ret' variable. Suggested-by: Steven Rostedt Signed-off-by: Dmitry Ilvokhin --- mm/page_alloc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2857daf6ebfd..92fa922911d5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -7493,11 +7493,9 @@ bool take_page_off_buddy(struct page *page) { struct zone *zone = page_zone(page); unsigned long pfn = page_to_pfn(page); - unsigned long flags; unsigned int order; - bool ret = false; - zone_lock_irqsave(zone, flags); + guard(zone_lock_irqsave)(zone); for (order = 0; order < NR_PAGE_ORDERS; order++) { struct page *page_head = page - (pfn & ((1 << order) - 1)); int page_order = buddy_order(page_head); @@ -7512,14 +7510,12 @@ bool take_page_off_buddy(struct page *page) break_down_buddy_pages(zone, page_head, page, 0, page_order, migratetype); SetPageHWPoisonTakenOff(page); - ret = true; - break; + return true; } if (page_count(page_head) > 0) break; } - zone_unlock_irqrestore(zone, flags); - return ret; + return false; } /* -- 2.47.3 Use zone_lock_irqsave lock guard in put_page_back_buddy() to replace the explicit lock/unlock pattern with automatic scope-based cleanup. Suggested-by: Steven Rostedt Signed-off-by: Dmitry Ilvokhin --- mm/page_alloc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 92fa922911d5..28b06baa4075 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -7524,23 +7524,19 @@ bool take_page_off_buddy(struct page *page) bool put_page_back_buddy(struct page *page) { struct zone *zone = page_zone(page); - unsigned long flags; - bool ret = false; - zone_lock_irqsave(zone, flags); + guard(zone_lock_irqsave)(zone); if (put_page_testzero(page)) { unsigned long pfn = page_to_pfn(page); int migratetype = get_pfnblock_migratetype(page, pfn); ClearPageHWPoisonTakenOff(page); __free_one_page(page, pfn, zone, 0, migratetype, FPI_NONE); - if (TestClearPageHWPoison(page)) { - ret = true; - } + if (TestClearPageHWPoison(page)) + return true; } - zone_unlock_irqrestore(zone, flags); - return ret; + return false; } #endif -- 2.47.3 Use zone_lock_irqsave lock guard in free_pcppages_bulk() to replace the explicit lock/unlock pattern with automatic scope-based cleanup. Suggested-by: Steven Rostedt Signed-off-by: Dmitry Ilvokhin --- mm/page_alloc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 28b06baa4075..2759e02340fa 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1455,7 +1455,6 @@ static void free_pcppages_bulk(struct zone *zone, int count, struct per_cpu_pages *pcp, int pindex) { - unsigned long flags; unsigned int order; struct page *page; @@ -1468,7 +1467,7 @@ static void free_pcppages_bulk(struct zone *zone, int count, /* Ensure requested pindex is drained first. */ pindex = pindex - 1; - zone_lock_irqsave(zone, flags); + guard(zone_lock_irqsave)(zone); while (count > 0) { struct list_head *list; @@ -1500,8 +1499,6 @@ static void free_pcppages_bulk(struct zone *zone, int count, trace_mm_page_pcpu_drain(page, order, mt); } while (count > 0 && !list_empty(list)); } - - zone_unlock_irqrestore(zone, flags); } /* Split a multi-block free page into its individual pageblocks. */ -- 2.47.3 Use zone_lock_irqsave lock guard in __offline_isolated_pages() to replace the explicit lock/unlock pattern with automatic scope-based cleanup. Suggested-by: Steven Rostedt Signed-off-by: Dmitry Ilvokhin --- mm/page_alloc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2759e02340fa..6f7420e4431f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -7380,7 +7380,7 @@ void zone_pcp_reset(struct zone *zone) unsigned long __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) { - unsigned long already_offline = 0, flags; + unsigned long already_offline = 0; unsigned long pfn = start_pfn; struct page *page; struct zone *zone; @@ -7388,7 +7388,7 @@ unsigned long __offline_isolated_pages(unsigned long start_pfn, offline_mem_sections(pfn, end_pfn); zone = page_zone(pfn_to_page(pfn)); - zone_lock_irqsave(zone, flags); + guard(zone_lock_irqsave)(zone); while (pfn < end_pfn) { page = pfn_to_page(pfn); /* @@ -7418,7 +7418,6 @@ unsigned long __offline_isolated_pages(unsigned long start_pfn, del_page_from_free_list(page, zone, order, MIGRATE_ISOLATE); pfn += (1 << order); } - zone_unlock_irqrestore(zone, flags); return end_pfn - start_pfn - already_offline; } -- 2.47.3