|
@@ -1853,6 +1853,115 @@ struct seq_operations fragmentation_op = {
|
|
|
.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[] = {
|
|
|
"nr_dirty",
|
|
|
"nr_writeback",
|
|
@@ -2058,10 +2167,10 @@ static void setup_per_zone_pages_min(void)
|
|
|
min_pages = 128;
|
|
|
zone->pages_min = min_pages;
|
|
|
} 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.
|
|
|
*/
|
|
|
- zone->pages_min = (pages_min * zone->present_pages) /
|
|
|
+ zone->pages_min = (pages_min * zone->present_pages) /
|
|
|
lowmem_pages;
|
|
|
}
|
|
|
|