Commit 295ab934 authored by Nikita Danilov's avatar Nikita Danilov Committed by Linus Torvalds

[PATCH] mm: add /proc/zoneinfo

Add /proc/zoneinfo file to display information about memory zones.  Useful
to analyze VM behaviour.
Signed-off-by: default avatarNikita Danilov <nikita@clusterfs.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 05b74384
...@@ -219,6 +219,19 @@ static struct file_operations fragmentation_file_operations = { ...@@ -219,6 +219,19 @@ static struct file_operations fragmentation_file_operations = {
.release = seq_release, .release = seq_release,
}; };
extern struct seq_operations zoneinfo_op;
static int zoneinfo_open(struct inode *inode, struct file *file)
{
return seq_open(file, &zoneinfo_op);
}
static struct file_operations proc_zoneinfo_file_operations = {
.open = zoneinfo_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static int version_read_proc(char *page, char **start, off_t off, static int version_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
...@@ -589,6 +602,7 @@ void __init proc_misc_init(void) ...@@ -589,6 +602,7 @@ void __init proc_misc_init(void)
create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
create_seq_entry("diskstats", 0, &proc_diskstats_operations); create_seq_entry("diskstats", 0, &proc_diskstats_operations);
#ifdef CONFIG_MODULES #ifdef CONFIG_MODULES
create_seq_entry("modules", 0, &proc_modules_operations); create_seq_entry("modules", 0, &proc_modules_operations);
......
...@@ -1853,6 +1853,115 @@ struct seq_operations fragmentation_op = { ...@@ -1853,6 +1853,115 @@ struct seq_operations fragmentation_op = {
.show = frag_show, .show = frag_show,
}; };
/*
* Output information about zones in @pgdat.
*/
static int zoneinfo_show(struct seq_file *m, void *arg)
{
pg_data_t *pgdat = arg;
struct zone *zone;
struct zone *node_zones = pgdat->node_zones;
unsigned long flags;
for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) {
int i;
if (!zone->present_pages)
continue;
spin_lock_irqsave(&zone->lock, flags);
seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name);
seq_printf(m,
"\n pages free %lu"
"\n min %lu"
"\n low %lu"
"\n high %lu"
"\n active %lu"
"\n inactive %lu"
"\n scanned %lu (a: %lu i: %lu)"
"\n spanned %lu"
"\n present %lu",
zone->free_pages,
zone->pages_min,
zone->pages_low,
zone->pages_high,
zone->nr_active,
zone->nr_inactive,
zone->pages_scanned,
zone->nr_scan_active, zone->nr_scan_inactive,
zone->spanned_pages,
zone->present_pages);
seq_printf(m,
"\n protection: (%lu",
zone->lowmem_reserve[0]);
for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
seq_printf(m, ", %lu", zone->lowmem_reserve[i]);
seq_printf(m,
")"
"\n pagesets");
for (i = 0; i < ARRAY_SIZE(zone->pageset); i++) {
struct per_cpu_pageset *pageset;
int j;
pageset = &zone->pageset[i];
for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
if (pageset->pcp[j].count)
break;
}
if (j == ARRAY_SIZE(pageset->pcp))
continue;
for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
seq_printf(m,
"\n cpu: %i pcp: %i"
"\n count: %i"
"\n low: %i"
"\n high: %i"
"\n batch: %i",
i, j,
pageset->pcp[j].count,
pageset->pcp[j].low,
pageset->pcp[j].high,
pageset->pcp[j].batch);
}
#ifdef CONFIG_NUMA
seq_printf(m,
"\n numa_hit: %lu"
"\n numa_miss: %lu"
"\n numa_foreign: %lu"
"\n interleave_hit: %lu"
"\n local_node: %lu"
"\n other_node: %lu",
pageset->numa_hit,
pageset->numa_miss,
pageset->numa_foreign,
pageset->interleave_hit,
pageset->local_node,
pageset->other_node);
#endif
}
seq_printf(m,
"\n all_unreclaimable: %u"
"\n prev_priority: %i"
"\n temp_priority: %i"
"\n start_pfn: %lu",
zone->all_unreclaimable,
zone->prev_priority,
zone->temp_priority,
zone->zone_start_pfn);
spin_unlock_irqrestore(&zone->lock, flags);
seq_putc(m, '\n');
}
return 0;
}
struct seq_operations zoneinfo_op = {
.start = frag_start, /* iterate over all zones. The same as in
* fragmentation. */
.next = frag_next,
.stop = frag_stop,
.show = zoneinfo_show,
};
static char *vmstat_text[] = { static char *vmstat_text[] = {
"nr_dirty", "nr_dirty",
"nr_writeback", "nr_writeback",
...@@ -2058,10 +2167,10 @@ static void setup_per_zone_pages_min(void) ...@@ -2058,10 +2167,10 @@ static void setup_per_zone_pages_min(void)
min_pages = 128; min_pages = 128;
zone->pages_min = min_pages; zone->pages_min = min_pages;
} else { } else {
/* if it's a lowmem zone, reserve a number of pages /* if it's a lowmem zone, reserve a number of pages
* proportionate to the zone's size. * proportionate to the zone's size.
*/ */
zone->pages_min = (pages_min * zone->present_pages) / zone->pages_min = (pages_min * zone->present_pages) /
lowmem_pages; lowmem_pages;
} }
......
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