mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 00:21:59 +00:00
c78e93630d
It has been reported on very large machines that show_mem is taking almost 5 minutes to display information. This is a serious problem if there is an OOM storm. The bulk of the cost is in show_mem doing a very expensive PFN walk to give us the following information Total RAM: Also available as totalram_pages Highmem pages: Also available as totalhigh_pages Reserved pages: Can be inferred from the zone structure Shared pages: PFN walk required Unshared pages: PFN walk required Quick pages: Per-cpu walk required Only the shared/unshared pages requires a full PFN walk but that information is useless. It is also inaccurate as page pins of unshared pages would be accounted for as shared. Even if the information was accurate, I'm struggling to think how the shared/unshared information could be useful for debugging OOM conditions. Maybe it was useful before rmap existed when reclaiming shared pages was costly but it is less relevant today. The PFN walk could be optimised a bit but why bother as the information is useless. This patch deletes the PFN walker and infers the total RAM, highmem and reserved pages count from struct zone. It omits the shared/unshared page usage on the grounds that it is useless. It also corrects the reporting of HighMem as HighMem/MovableOnly as ZONE_MOVABLE has similar problems to HighMem with respect to lowmem/highmem exhaustion. Signed-off-by: Mel Gorman <mgorman@suse.de> Cc: David Rientjes <rientjes@google.com> Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
50 lines
1.1 KiB
C
50 lines
1.1 KiB
C
/*
|
|
* Generic show_mem() implementation
|
|
*
|
|
* Copyright (C) 2008 Johannes Weiner <hannes@saeurebad.de>
|
|
* All code subject to the GPL version 2.
|
|
*/
|
|
|
|
#include <linux/mm.h>
|
|
#include <linux/nmi.h>
|
|
#include <linux/quicklist.h>
|
|
|
|
void show_mem(unsigned int filter)
|
|
{
|
|
pg_data_t *pgdat;
|
|
unsigned long total = 0, reserved = 0, highmem = 0;
|
|
|
|
printk("Mem-Info:\n");
|
|
show_free_areas(filter);
|
|
|
|
if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
|
|
return;
|
|
|
|
for_each_online_pgdat(pgdat) {
|
|
unsigned long flags;
|
|
int zoneid;
|
|
|
|
pgdat_resize_lock(pgdat, &flags);
|
|
for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
|
|
struct zone *zone = &pgdat->node_zones[zoneid];
|
|
if (!populated_zone(zone))
|
|
continue;
|
|
|
|
total += zone->present_pages;
|
|
reserved = zone->present_pages - zone->managed_pages;
|
|
|
|
if (is_highmem_idx(zoneid))
|
|
highmem += zone->present_pages;
|
|
}
|
|
pgdat_resize_unlock(pgdat, &flags);
|
|
}
|
|
|
|
printk("%lu pages RAM\n", total);
|
|
printk("%lu pages HighMem/MovableOnly\n", highmem);
|
|
printk("%lu pages reserved\n", reserved);
|
|
#ifdef CONFIG_QUICKLIST
|
|
printk("%lu pages in pagetable cache\n",
|
|
quicklist_total_size());
|
|
#endif
|
|
}
|