Skip to content

Commit dbe2d4e

Browse files
gormanmtorvalds
authored andcommitted
mm, compaction: round-robin the order while searching the free lists for a target
As compaction proceeds and creates high-order blocks, the free list search gets less efficient as the larger blocks are used as compaction targets. Eventually, the larger blocks will be behind the migration scanner for partially migrated pageblocks and the search fails. This patch round-robins what orders are searched so that larger blocks can be ignored and find smaller blocks that can be used as migration targets. The overall impact was small on 1-socket but it avoids corner cases where the migration/free scanners meet prematurely or situations where many of the pageblocks encountered by the free scanner are almost full instead of being properly packed. Previous testing had indicated that without this patch there were occasional large spikes in the free scanner without this patch. [dan.carpenter@oracle.com: fix static checker warning] Link: http://lkml.kernel.org/r/20190118175136.31341-20-mgorman@techsingularity.net Signed-off-by: Mel Gorman <mgorman@techsingularity.net> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: David Rientjes <rientjes@google.com> Cc: YueHaibing <yuehaibing@huawei.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent d097a6f commit dbe2d4e

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

mm/compaction.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,24 @@ fast_isolate_around(struct compact_control *cc, unsigned long pfn, unsigned long
11471147
set_pageblock_skip(page);
11481148
}
11491149

1150+
/* Search orders in round-robin fashion */
1151+
static int next_search_order(struct compact_control *cc, int order)
1152+
{
1153+
order--;
1154+
if (order < 0)
1155+
order = cc->order - 1;
1156+
1157+
/* Search wrapped around? */
1158+
if (order == cc->search_order) {
1159+
cc->search_order--;
1160+
if (cc->search_order < 0)
1161+
cc->search_order = cc->order - 1;
1162+
return -1;
1163+
}
1164+
1165+
return order;
1166+
}
1167+
11501168
static unsigned long
11511169
fast_isolate_freepages(struct compact_control *cc)
11521170
{
@@ -1183,9 +1201,15 @@ fast_isolate_freepages(struct compact_control *cc)
11831201
if (WARN_ON_ONCE(min_pfn > low_pfn))
11841202
low_pfn = min_pfn;
11851203

1186-
for (order = cc->order - 1;
1187-
order >= 0 && !page;
1188-
order--) {
1204+
/*
1205+
* Search starts from the last successful isolation order or the next
1206+
* order to search after a previous failure
1207+
*/
1208+
cc->search_order = min_t(unsigned int, cc->order - 1, cc->search_order);
1209+
1210+
for (order = cc->search_order;
1211+
!page && order >= 0;
1212+
order = next_search_order(cc, order)) {
11891213
struct free_area *area = &cc->zone->free_area[order];
11901214
struct list_head *freelist;
11911215
struct page *freepage;
@@ -1209,6 +1233,7 @@ fast_isolate_freepages(struct compact_control *cc)
12091233

12101234
if (pfn >= low_pfn) {
12111235
cc->fast_search_fail = 0;
1236+
cc->search_order = order;
12121237
page = freepage;
12131238
break;
12141239
}
@@ -2138,6 +2163,7 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,
21382163
.total_migrate_scanned = 0,
21392164
.total_free_scanned = 0,
21402165
.order = order,
2166+
.search_order = order,
21412167
.gfp_mask = gfp_mask,
21422168
.zone = zone,
21432169
.mode = (prio == COMPACT_PRIO_ASYNC) ?
@@ -2369,6 +2395,7 @@ static void kcompactd_do_work(pg_data_t *pgdat)
23692395
struct zone *zone;
23702396
struct compact_control cc = {
23712397
.order = pgdat->kcompactd_max_order,
2398+
.search_order = pgdat->kcompactd_max_order,
23722399
.total_migrate_scanned = 0,
23732400
.total_free_scanned = 0,
23742401
.classzone_idx = pgdat->kcompactd_classzone_idx,

mm/internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ struct compact_control {
192192
struct zone *zone;
193193
unsigned long total_migrate_scanned;
194194
unsigned long total_free_scanned;
195-
unsigned int fast_search_fail; /* failures to use free list searches */
195+
unsigned short fast_search_fail;/* failures to use free list searches */
196+
short search_order; /* order to start a fast search at */
196197
const gfp_t gfp_mask; /* gfp mask of a direct compactor */
197198
int order; /* order a direct compactor needs */
198199
int migratetype; /* migratetype of direct compactor */

0 commit comments

Comments
 (0)