Commit b7fdef78 authored by Andrew Morton's avatar Andrew Morton Committed by Jaroslav Kysela

[PATCH] show_free_areas extensions

Ancient patch From Bill Irwin

The patch is intended to show improved information about where the
memory went during OOM-killing events.

- when the OOM killer fails and the system panics, calls
  show_free_areas()

- reorganize show_free_areas() to use for_each_zone()

- add per-cpu stats to show_free_areas()

- tags output from show_free_areas() with node and zone information
parent 3e9afe4c
...@@ -172,8 +172,10 @@ static void oom_kill(void) ...@@ -172,8 +172,10 @@ static void oom_kill(void)
p = select_bad_process(); p = select_bad_process();
/* Found nothing?!?! Either we hang forever, or we panic. */ /* Found nothing?!?! Either we hang forever, or we panic. */
if (p == NULL) if (!p) {
show_free_areas();
panic("Out of memory and no killable processes...\n"); panic("Out of memory and no killable processes...\n");
}
oom_kill_task(p); oom_kill_task(p);
/* /*
......
...@@ -694,6 +694,15 @@ unsigned int nr_free_highpages (void) ...@@ -694,6 +694,15 @@ unsigned int nr_free_highpages (void)
} }
#endif #endif
#ifdef CONFIG_NUMA
static void show_node(struct zone *zone)
{
printk("Node %d ", zone->zone_pgdat->node_id);
}
#else
#define show_node(zone) do { } while (0)
#endif
/* /*
* Accumulate the page_state information across all CPUs. * Accumulate the page_state information across all CPUs.
* The result is unavoidably approximate - it can change * The result is unavoidably approximate - it can change
...@@ -793,29 +802,57 @@ void si_meminfo_node(struct sysinfo *val, int nid) ...@@ -793,29 +802,57 @@ void si_meminfo_node(struct sysinfo *val, int nid)
*/ */
void show_free_areas(void) void show_free_areas(void)
{ {
pg_data_t *pgdat;
struct page_state ps; struct page_state ps;
int type; int cpu, temperature;
unsigned long active; unsigned long active;
unsigned long inactive; unsigned long inactive;
struct zone *zone;
for_each_zone(zone) {
show_node(zone);
printk("%s per-cpu:", zone->name);
if (!zone->present_pages) {
printk(" empty\n");
continue;
} else
printk("\n");
for (cpu = 0; cpu < NR_CPUS; ++cpu) {
struct per_cpu_pageset *pageset = zone->pageset + cpu;
for (temperature = 0; temperature < 2; temperature++)
printk("cpu %d %s: low %d, high %d, batch %d\n",
cpu,
temperature ? "cold" : "hot",
pageset->pcp[temperature].low,
pageset->pcp[temperature].high,
pageset->pcp[temperature].batch);
}
}
get_page_state(&ps); get_page_state(&ps);
get_zone_counts(&active, &inactive); get_zone_counts(&active, &inactive);
printk("Free pages: %6dkB (%6dkB HighMem)\n", printk("\nFree pages: %11ukB (%ukB HighMem)\n",
K(nr_free_pages()), K(nr_free_pages()),
K(nr_free_highpages())); K(nr_free_highpages()));
for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next) printk("Active:%lu inactive:%lu dirty:%lu writeback:%lu free:%u\n",
for (type = 0; type < MAX_NR_ZONES; ++type) { active,
struct zone *zone = &pgdat->node_zones[type]; inactive,
printk("Zone:%s" ps.nr_dirty,
" freepages:%6lukB" ps.nr_writeback,
" min:%6lukB" nr_free_pages());
" low:%6lukB"
" high:%6lukB" for_each_zone(zone) {
" active:%6lukB" show_node(zone);
" inactive:%6lukB" printk("%s"
" free:%lukB"
" min:%lukB"
" low:%lukB"
" high:%lukB"
" active:%lukB"
" inactive:%lukB"
"\n", "\n",
zone->name, zone->name,
K(zone->free_pages), K(zone->free_pages),
...@@ -827,21 +864,16 @@ void show_free_areas(void) ...@@ -827,21 +864,16 @@ void show_free_areas(void)
); );
} }
printk("( Active:%lu inactive:%lu dirty:%lu writeback:%lu free:%u )\n", for_each_zone(zone) {
active,
inactive,
ps.nr_dirty,
ps.nr_writeback,
nr_free_pages());
for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next)
for (type = 0; type < MAX_NR_ZONES; type++) {
struct list_head *elem; struct list_head *elem;
struct zone *zone = &pgdat->node_zones[type];
unsigned long nr, flags, order, total = 0; unsigned long nr, flags, order, total = 0;
if (!zone->present_pages) show_node(zone);
printk("%s: ", zone->name);
if (!zone->present_pages) {
printk("empty\n");
continue; continue;
}
spin_lock_irqsave(&zone->lock, flags); spin_lock_irqsave(&zone->lock, flags);
for (order = 0; order < MAX_ORDER; order++) { for (order = 0; order < MAX_ORDER; order++) {
...@@ -852,7 +884,7 @@ void show_free_areas(void) ...@@ -852,7 +884,7 @@ void show_free_areas(void)
printk("%lu*%lukB ", nr, K(1UL) << order); printk("%lu*%lukB ", nr, K(1UL) << order);
} }
spin_unlock_irqrestore(&zone->lock, flags); spin_unlock_irqrestore(&zone->lock, flags);
printk("= %lukB)\n", K(total)); printk("= %lukB\n", K(total));
} }
show_swap_cache_info(); show_swap_cache_info();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment