Skip to content

Commit a676a20

Browse files
Vinayak MenonBrian Maly
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]> Orabug: 29905302 (cherry picked from commit 727c080) Reviewed-by: Joe Jin <[email protected]> Reviewed-by: Khalid Aziz <[email protected]> Signed-off-by: Tong Chen <[email protected]> Conflicts: mm/page_owner.c mm/vmstat.c Signed-off-by: Brian Maly <[email protected]>
1 parent f1fe879 commit a676a20

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

mm/vmstat.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,7 @@ static void frag_stop(struct seq_file *m, void *arg)
883883

884884
/* Walk all the zones in a node and print using a callback */
885885
static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
886+
bool nolock,
886887
void (*print)(struct seq_file *m, pg_data_t *, struct zone *))
887888
{
888889
struct zone *zone;
@@ -893,9 +894,11 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
893894
if (!populated_zone(zone))
894895
continue;
895896

896-
spin_lock_irqsave(&zone->lock, flags);
897+
if (!nolock)
898+
spin_lock_irqsave(&zone->lock, flags);
897899
print(m, pgdat, zone);
898-
spin_unlock_irqrestore(&zone->lock, flags);
900+
if (!nolock)
901+
spin_unlock_irqrestore(&zone->lock, flags);
899902
}
900903
}
901904
#endif
@@ -931,7 +934,7 @@ static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
931934
static int frag_show(struct seq_file *m, void *arg)
932935
{
933936
pg_data_t *pgdat = (pg_data_t *)arg;
934-
walk_zones_in_node(m, pgdat, frag_show_print);
937+
walk_zones_in_node(m, pgdat, false, frag_show_print);
935938
return 0;
936939
}
937940

@@ -972,7 +975,7 @@ static int pagetypeinfo_showfree(struct seq_file *m, void *arg)
972975
seq_printf(m, "%6d ", order);
973976
seq_putc(m, '\n');
974977

975-
walk_zones_in_node(m, pgdat, pagetypeinfo_showfree_print);
978+
walk_zones_in_node(m, pgdat, false, pagetypeinfo_showfree_print);
976979

977980
return 0;
978981
}
@@ -1021,7 +1024,7 @@ static int pagetypeinfo_showblockcount(struct seq_file *m, void *arg)
10211024
for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
10221025
seq_printf(m, "%12s ", migratetype_names[mtype]);
10231026
seq_putc(m, '\n');
1024-
walk_zones_in_node(m, pgdat, pagetypeinfo_showblockcount_print);
1027+
walk_zones_in_node(m, pgdat, false, pagetypeinfo_showblockcount_print);
10251028

10261029
return 0;
10271030
}
@@ -1065,7 +1068,11 @@ static void pagetypeinfo_showmixedcount_print(struct seq_file *m,
10651068

10661069
page = pfn_to_page(pfn);
10671070
if (PageBuddy(page)) {
1068-
pfn += (1UL << page_order(page)) - 1;
1071+
unsigned long freepage_order;
1072+
1073+
freepage_order = page_order_unsafe(page);
1074+
if (freepage_order < MAX_ORDER)
1075+
pfn += (1UL << freepage_order) - 1;
10691076
continue;
10701077
}
10711078

@@ -1120,7 +1127,7 @@ static void pagetypeinfo_showmixedcount(struct seq_file *m, pg_data_t *pgdat)
11201127
seq_printf(m, "%12s ", migratetype_names[mtype]);
11211128
seq_putc(m, '\n');
11221129

1123-
walk_zones_in_node(m, pgdat, pagetypeinfo_showmixedcount_print);
1130+
walk_zones_in_node(m, pgdat, true, pagetypeinfo_showmixedcount_print);
11241131
#endif /* CONFIG_PAGE_OWNER */
11251132
}
11261133

@@ -1253,7 +1260,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
12531260
static int zoneinfo_show(struct seq_file *m, void *arg)
12541261
{
12551262
pg_data_t *pgdat = (pg_data_t *)arg;
1256-
walk_zones_in_node(m, pgdat, zoneinfo_show_print);
1263+
walk_zones_in_node(m, pgdat, false, zoneinfo_show_print);
12571264
return 0;
12581265
}
12591266

@@ -1601,7 +1608,7 @@ static int unusable_show(struct seq_file *m, void *arg)
16011608
if (!node_state(pgdat->node_id, N_MEMORY))
16021609
return 0;
16031610

1604-
walk_zones_in_node(m, pgdat, unusable_show_print);
1611+
walk_zones_in_node(m, pgdat, false, unusable_show_print);
16051612

16061613
return 0;
16071614
}
@@ -1653,7 +1660,7 @@ static int extfrag_show(struct seq_file *m, void *arg)
16531660
{
16541661
pg_data_t *pgdat = (pg_data_t *)arg;
16551662

1656-
walk_zones_in_node(m, pgdat, extfrag_show_print);
1663+
walk_zones_in_node(m, pgdat, false, extfrag_show_print);
16571664

16581665
return 0;
16591666
}

0 commit comments

Comments
 (0)