Skip to content

Commit 727c080

Browse files
Vinayak Menontorvalds
authored andcommitted
mm: avoid taking zone lock in pagetypeinfo_showmixed()
pagetypeinfo_showmixedcount_print is found to take a lot of time to complete and it does this holding the zone lock and disabling interrupts. In some cases it is found to take more than a second (On a 2.4GHz,8Gb RAM,arm64 cpu). Avoid taking the zone lock similar to what is done by read_page_owner, which means possibility of inaccurate results. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Vinayak Menon <[email protected]> Acked-by: Vlastimil Babka <[email protected]> Cc: Joonsoo Kim <[email protected]> Cc: zhongjiang <[email protected]> Cc: Sergey Senozhatsky <[email protected]> Cc: Sudip Mukherjee <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Mel Gorman <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Sebastian Andrzej Siewior <[email protected]> Cc: David Rientjes <[email protected]> Cc: Minchan Kim <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent ef77ba5 commit 727c080

File tree

2 files changed

+19
-11
lines changed

2 files changed

+19
-11
lines changed

mm/page_owner.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,11 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,
281281
continue;
282282

283283
if (PageBuddy(page)) {
284-
pfn += (1UL << page_order(page)) - 1;
284+
unsigned long freepage_order;
285+
286+
freepage_order = page_order_unsafe(page);
287+
if (freepage_order < MAX_ORDER)
288+
pfn += (1UL << freepage_order) - 1;
285289
continue;
286290
}
287291

mm/vmstat.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,7 @@ static void frag_stop(struct seq_file *m, void *arg)
11301130
* If @assert_populated is true, only use callback for zones that are populated.
11311131
*/
11321132
static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
1133-
bool assert_populated,
1133+
bool assert_populated, bool nolock,
11341134
void (*print)(struct seq_file *m, pg_data_t *, struct zone *))
11351135
{
11361136
struct zone *zone;
@@ -1141,9 +1141,11 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
11411141
if (assert_populated && !populated_zone(zone))
11421142
continue;
11431143

1144-
spin_lock_irqsave(&zone->lock, flags);
1144+
if (!nolock)
1145+
spin_lock_irqsave(&zone->lock, flags);
11451146
print(m, pgdat, zone);
1146-
spin_unlock_irqrestore(&zone->lock, flags);
1147+
if (!nolock)
1148+
spin_unlock_irqrestore(&zone->lock, flags);
11471149
}
11481150
}
11491151
#endif
@@ -1166,7 +1168,7 @@ static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
11661168
static int frag_show(struct seq_file *m, void *arg)
11671169
{
11681170
pg_data_t *pgdat = (pg_data_t *)arg;
1169-
walk_zones_in_node(m, pgdat, true, frag_show_print);
1171+
walk_zones_in_node(m, pgdat, true, false, frag_show_print);
11701172
return 0;
11711173
}
11721174

@@ -1207,7 +1209,7 @@ static int pagetypeinfo_showfree(struct seq_file *m, void *arg)
12071209
seq_printf(m, "%6d ", order);
12081210
seq_putc(m, '\n');
12091211

1210-
walk_zones_in_node(m, pgdat, true, pagetypeinfo_showfree_print);
1212+
walk_zones_in_node(m, pgdat, true, false, pagetypeinfo_showfree_print);
12111213

12121214
return 0;
12131215
}
@@ -1258,7 +1260,8 @@ static int pagetypeinfo_showblockcount(struct seq_file *m, void *arg)
12581260
for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
12591261
seq_printf(m, "%12s ", migratetype_names[mtype]);
12601262
seq_putc(m, '\n');
1261-
walk_zones_in_node(m, pgdat, true, pagetypeinfo_showblockcount_print);
1263+
walk_zones_in_node(m, pgdat, true, false,
1264+
pagetypeinfo_showblockcount_print);
12621265

12631266
return 0;
12641267
}
@@ -1284,7 +1287,8 @@ static void pagetypeinfo_showmixedcount(struct seq_file *m, pg_data_t *pgdat)
12841287
seq_printf(m, "%12s ", migratetype_names[mtype]);
12851288
seq_putc(m, '\n');
12861289

1287-
walk_zones_in_node(m, pgdat, true, pagetypeinfo_showmixedcount_print);
1290+
walk_zones_in_node(m, pgdat, true, true,
1291+
pagetypeinfo_showmixedcount_print);
12881292
#endif /* CONFIG_PAGE_OWNER */
12891293
}
12901294

@@ -1446,7 +1450,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
14461450
static int zoneinfo_show(struct seq_file *m, void *arg)
14471451
{
14481452
pg_data_t *pgdat = (pg_data_t *)arg;
1449-
walk_zones_in_node(m, pgdat, false, zoneinfo_show_print);
1453+
walk_zones_in_node(m, pgdat, false, false, zoneinfo_show_print);
14501454
return 0;
14511455
}
14521456

@@ -1852,7 +1856,7 @@ static int unusable_show(struct seq_file *m, void *arg)
18521856
if (!node_state(pgdat->node_id, N_MEMORY))
18531857
return 0;
18541858

1855-
walk_zones_in_node(m, pgdat, true, unusable_show_print);
1859+
walk_zones_in_node(m, pgdat, true, false, unusable_show_print);
18561860

18571861
return 0;
18581862
}
@@ -1904,7 +1908,7 @@ static int extfrag_show(struct seq_file *m, void *arg)
19041908
{
19051909
pg_data_t *pgdat = (pg_data_t *)arg;
19061910

1907-
walk_zones_in_node(m, pgdat, true, extfrag_show_print);
1911+
walk_zones_in_node(m, pgdat, true, false, extfrag_show_print);
19081912

19091913
return 0;
19101914
}

0 commit comments

Comments
 (0)