mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Print out statistics in relation to fragmentation avoidance to /proc/pagetypeinfo
This patch provides fragmentation avoidance statistics via /proc/pagetypeinfo. The information is collected only on request so there is no runtime overhead. The statistics are in three parts: The first part prints information on the size of blocks that pages are being grouped on and looks like Page block order: 10 Pages per block: 1024 The second part is a more detailed version of /proc/buddyinfo and looks like Free pages count per migrate type at order 0 1 2 3 4 5 6 7 8 9 10 Node 0, zone DMA, type Unmovable 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA, type Reclaimable 1 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA, type Movable 0 0 0 0 0 0 0 0 0 0 0 Node 0, zone DMA, type Reserve 0 4 4 0 0 0 0 1 0 1 0 Node 0, zone Normal, type Unmovable 111 8 4 4 2 3 1 0 0 0 0 Node 0, zone Normal, type Reclaimable 293 89 8 0 0 0 0 0 0 0 0 Node 0, zone Normal, type Movable 1 6 13 9 7 6 3 0 0 0 0 Node 0, zone Normal, type Reserve 0 0 0 0 0 0 0 0 0 0 4 The third part looks like Number of blocks type Unmovable Reclaimable Movable Reserve Node 0, zone DMA 0 1 2 1 Node 0, zone Normal 3 17 94 4 To walk the zones within a node with interrupts disabled, walk_zones_in_node() is introduced and shared between /proc/buddyinfo, /proc/zoneinfo and /proc/pagetypeinfo to reduce code duplication. It seems specific to what vmstat.c requires but could be broken out as a general utility function in mmzone.c if there were other other potential users. Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Andy Whitcroft <apw@shadowen.org> Acked-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									d9c2340052
								
							
						
					
					
						commit
						467c996c1e
					
				
					 5 changed files with 242 additions and 102 deletions
				
			
		| 
						 | 
				
			
			@ -229,6 +229,19 @@ static const struct file_operations fragmentation_file_operations = {
 | 
			
		|||
	.release	= seq_release,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern struct seq_operations pagetypeinfo_op;
 | 
			
		||||
static int pagetypeinfo_open(struct inode *inode, struct file *file)
 | 
			
		||||
{
 | 
			
		||||
	return seq_open(file, &pagetypeinfo_op);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct file_operations pagetypeinfo_file_ops = {
 | 
			
		||||
	.open		= pagetypeinfo_open,
 | 
			
		||||
	.read		= seq_read,
 | 
			
		||||
	.llseek		= seq_lseek,
 | 
			
		||||
	.release	= seq_release,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern struct seq_operations zoneinfo_op;
 | 
			
		||||
static int zoneinfo_open(struct inode *inode, struct file *file)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -724,6 +737,7 @@ void __init proc_misc_init(void)
 | 
			
		|||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
	create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
 | 
			
		||||
	create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops);
 | 
			
		||||
	create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
 | 
			
		||||
	create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
 | 
			
		||||
#ifdef CONFIG_BLOCK
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,6 +104,18 @@ struct vm_area_struct;
 | 
			
		|||
/* 4GB DMA on some platforms */
 | 
			
		||||
#define GFP_DMA32	__GFP_DMA32
 | 
			
		||||
 | 
			
		||||
/* Convert GFP flags to their corresponding migrate type */
 | 
			
		||||
static inline int allocflags_to_migratetype(gfp_t gfp_flags)
 | 
			
		||||
{
 | 
			
		||||
	WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
 | 
			
		||||
 | 
			
		||||
	if (unlikely(page_group_by_mobility_disabled))
 | 
			
		||||
		return MIGRATE_UNMOVABLE;
 | 
			
		||||
 | 
			
		||||
	/* Group based on mobility */
 | 
			
		||||
	return (((gfp_flags & __GFP_MOVABLE) != 0) << 1) |
 | 
			
		||||
		((gfp_flags & __GFP_RECLAIMABLE) != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline enum zone_type gfp_zone(gfp_t flags)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,16 @@
 | 
			
		|||
	for (order = 0; order < MAX_ORDER; order++) \
 | 
			
		||||
		for (type = 0; type < MIGRATE_TYPES; type++)
 | 
			
		||||
 | 
			
		||||
extern int page_group_by_mobility_disabled;
 | 
			
		||||
 | 
			
		||||
static inline int get_pageblock_migratetype(struct page *page)
 | 
			
		||||
{
 | 
			
		||||
	if (unlikely(page_group_by_mobility_disabled))
 | 
			
		||||
		return MIGRATE_UNMOVABLE;
 | 
			
		||||
 | 
			
		||||
	return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct free_area {
 | 
			
		||||
	struct list_head	free_list[MIGRATE_TYPES];
 | 
			
		||||
	unsigned long		nr_free;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -164,32 +164,12 @@ EXPORT_SYMBOL(nr_node_ids);
 | 
			
		|||
 | 
			
		||||
int page_group_by_mobility_disabled __read_mostly;
 | 
			
		||||
 | 
			
		||||
static inline int get_pageblock_migratetype(struct page *page)
 | 
			
		||||
{
 | 
			
		||||
	if (unlikely(page_group_by_mobility_disabled))
 | 
			
		||||
		return MIGRATE_UNMOVABLE;
 | 
			
		||||
 | 
			
		||||
	return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_pageblock_migratetype(struct page *page, int migratetype)
 | 
			
		||||
{
 | 
			
		||||
	set_pageblock_flags_group(page, (unsigned long)migratetype,
 | 
			
		||||
					PB_migrate, PB_migrate_end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int allocflags_to_migratetype(gfp_t gfp_flags)
 | 
			
		||||
{
 | 
			
		||||
	WARN_ON((gfp_flags & GFP_MOVABLE_MASK) == GFP_MOVABLE_MASK);
 | 
			
		||||
 | 
			
		||||
	if (unlikely(page_group_by_mobility_disabled))
 | 
			
		||||
		return MIGRATE_UNMOVABLE;
 | 
			
		||||
 | 
			
		||||
	/* Cluster based on mobility */
 | 
			
		||||
	return (((gfp_flags & __GFP_MOVABLE) != 0) << 1) |
 | 
			
		||||
		((gfp_flags & __GFP_RECLAIMABLE) != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DEBUG_VM
 | 
			
		||||
static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										288
									
								
								mm/vmstat.c
									
									
									
									
									
								
							
							
						
						
									
										288
									
								
								mm/vmstat.c
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -398,6 +398,13 @@ void zone_statistics(struct zonelist *zonelist, struct zone *z)
 | 
			
		|||
 | 
			
		||||
#include <linux/seq_file.h>
 | 
			
		||||
 | 
			
		||||
static char * const migratetype_names[MIGRATE_TYPES] = {
 | 
			
		||||
	"Unmovable",
 | 
			
		||||
	"Reclaimable",
 | 
			
		||||
	"Movable",
 | 
			
		||||
	"Reserve",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void *frag_start(struct seq_file *m, loff_t *pos)
 | 
			
		||||
{
 | 
			
		||||
	pg_data_t *pgdat;
 | 
			
		||||
| 
						 | 
				
			
			@ -422,28 +429,144 @@ static void frag_stop(struct seq_file *m, void *arg)
 | 
			
		|||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This walks the free areas for each zone.
 | 
			
		||||
 */
 | 
			
		||||
static int frag_show(struct seq_file *m, void *arg)
 | 
			
		||||
/* Walk all the zones in a node and print using a callback */
 | 
			
		||||
static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
 | 
			
		||||
		void (*print)(struct seq_file *m, pg_data_t *, struct zone *))
 | 
			
		||||
{
 | 
			
		||||
	pg_data_t *pgdat = (pg_data_t *)arg;
 | 
			
		||||
	struct zone *zone;
 | 
			
		||||
	struct zone *node_zones = pgdat->node_zones;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	int order;
 | 
			
		||||
 | 
			
		||||
	for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
 | 
			
		||||
		if (!populated_zone(zone))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		spin_lock_irqsave(&zone->lock, flags);
 | 
			
		||||
		seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
 | 
			
		||||
		for (order = 0; order < MAX_ORDER; ++order)
 | 
			
		||||
			seq_printf(m, "%6lu ", zone->free_area[order].nr_free);
 | 
			
		||||
		print(m, pgdat, zone);
 | 
			
		||||
		spin_unlock_irqrestore(&zone->lock, flags);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void frag_show_print(struct seq_file *m, pg_data_t *pgdat,
 | 
			
		||||
						struct zone *zone)
 | 
			
		||||
{
 | 
			
		||||
	int order;
 | 
			
		||||
 | 
			
		||||
	seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
 | 
			
		||||
	for (order = 0; order < MAX_ORDER; ++order)
 | 
			
		||||
		seq_printf(m, "%6lu ", zone->free_area[order].nr_free);
 | 
			
		||||
	seq_putc(m, '\n');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This walks the free areas for each zone.
 | 
			
		||||
 */
 | 
			
		||||
static int frag_show(struct seq_file *m, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	pg_data_t *pgdat = (pg_data_t *)arg;
 | 
			
		||||
	walk_zones_in_node(m, pgdat, frag_show_print);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pagetypeinfo_showfree_print(struct seq_file *m,
 | 
			
		||||
					pg_data_t *pgdat, struct zone *zone)
 | 
			
		||||
{
 | 
			
		||||
	int order, mtype;
 | 
			
		||||
 | 
			
		||||
	for (mtype = 0; mtype < MIGRATE_TYPES; mtype++) {
 | 
			
		||||
		seq_printf(m, "Node %4d, zone %8s, type %12s ",
 | 
			
		||||
					pgdat->node_id,
 | 
			
		||||
					zone->name,
 | 
			
		||||
					migratetype_names[mtype]);
 | 
			
		||||
		for (order = 0; order < MAX_ORDER; ++order) {
 | 
			
		||||
			unsigned long freecount = 0;
 | 
			
		||||
			struct free_area *area;
 | 
			
		||||
			struct list_head *curr;
 | 
			
		||||
 | 
			
		||||
			area = &(zone->free_area[order]);
 | 
			
		||||
 | 
			
		||||
			list_for_each(curr, &area->free_list[mtype])
 | 
			
		||||
				freecount++;
 | 
			
		||||
			seq_printf(m, "%6lu ", freecount);
 | 
			
		||||
		}
 | 
			
		||||
		seq_putc(m, '\n');
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Print out the free pages at each order for each migatetype */
 | 
			
		||||
static int pagetypeinfo_showfree(struct seq_file *m, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	int order;
 | 
			
		||||
	pg_data_t *pgdat = (pg_data_t *)arg;
 | 
			
		||||
 | 
			
		||||
	/* Print header */
 | 
			
		||||
	seq_printf(m, "%-43s ", "Free pages count per migrate type at order");
 | 
			
		||||
	for (order = 0; order < MAX_ORDER; ++order)
 | 
			
		||||
		seq_printf(m, "%6d ", order);
 | 
			
		||||
	seq_putc(m, '\n');
 | 
			
		||||
 | 
			
		||||
	walk_zones_in_node(m, pgdat, pagetypeinfo_showfree_print);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pagetypeinfo_showblockcount_print(struct seq_file *m,
 | 
			
		||||
					pg_data_t *pgdat, struct zone *zone)
 | 
			
		||||
{
 | 
			
		||||
	int mtype;
 | 
			
		||||
	unsigned long pfn;
 | 
			
		||||
	unsigned long start_pfn = zone->zone_start_pfn;
 | 
			
		||||
	unsigned long end_pfn = start_pfn + zone->spanned_pages;
 | 
			
		||||
	unsigned long count[MIGRATE_TYPES] = { 0, };
 | 
			
		||||
 | 
			
		||||
	for (pfn = start_pfn; pfn < end_pfn; pfn += pageblock_nr_pages) {
 | 
			
		||||
		struct page *page;
 | 
			
		||||
 | 
			
		||||
		if (!pfn_valid(pfn))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		page = pfn_to_page(pfn);
 | 
			
		||||
		mtype = get_pageblock_migratetype(page);
 | 
			
		||||
 | 
			
		||||
		count[mtype]++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Print counts */
 | 
			
		||||
	seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name);
 | 
			
		||||
	for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
 | 
			
		||||
		seq_printf(m, "%12lu ", count[mtype]);
 | 
			
		||||
	seq_putc(m, '\n');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Print out the free pages at each order for each migratetype */
 | 
			
		||||
static int pagetypeinfo_showblockcount(struct seq_file *m, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	int mtype;
 | 
			
		||||
	pg_data_t *pgdat = (pg_data_t *)arg;
 | 
			
		||||
 | 
			
		||||
	seq_printf(m, "\n%-23s", "Number of blocks type ");
 | 
			
		||||
	for (mtype = 0; mtype < MIGRATE_TYPES; mtype++)
 | 
			
		||||
		seq_printf(m, "%12s ", migratetype_names[mtype]);
 | 
			
		||||
	seq_putc(m, '\n');
 | 
			
		||||
	walk_zones_in_node(m, pgdat, pagetypeinfo_showblockcount_print);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This prints out statistics in relation to grouping pages by mobility.
 | 
			
		||||
 * It is expensive to collect so do not constantly read the file.
 | 
			
		||||
 */
 | 
			
		||||
static int pagetypeinfo_show(struct seq_file *m, void *arg)
 | 
			
		||||
{
 | 
			
		||||
	pg_data_t *pgdat = (pg_data_t *)arg;
 | 
			
		||||
 | 
			
		||||
	seq_printf(m, "Page block order: %d\n", pageblock_order);
 | 
			
		||||
	seq_printf(m, "Pages per block:  %lu\n", pageblock_nr_pages);
 | 
			
		||||
	seq_putc(m, '\n');
 | 
			
		||||
	pagetypeinfo_showfree(m, pgdat);
 | 
			
		||||
	pagetypeinfo_showblockcount(m, pgdat);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -454,6 +577,13 @@ const struct seq_operations fragmentation_op = {
 | 
			
		|||
	.show	= frag_show,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct seq_operations pagetypeinfo_op = {
 | 
			
		||||
	.start	= frag_start,
 | 
			
		||||
	.next	= frag_next,
 | 
			
		||||
	.stop	= frag_stop,
 | 
			
		||||
	.show	= pagetypeinfo_show,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_ZONE_DMA
 | 
			
		||||
#define TEXT_FOR_DMA(xx) xx "_dma",
 | 
			
		||||
#else
 | 
			
		||||
| 
						 | 
				
			
			@ -532,84 +662,78 @@ static const char * const vmstat_text[] = {
 | 
			
		|||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
 | 
			
		||||
							struct zone *zone)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	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        scanned  %lu (a: %lu i: %lu)"
 | 
			
		||||
		   "\n        spanned  %lu"
 | 
			
		||||
		   "\n        present  %lu",
 | 
			
		||||
		   zone_page_state(zone, NR_FREE_PAGES),
 | 
			
		||||
		   zone->pages_min,
 | 
			
		||||
		   zone->pages_low,
 | 
			
		||||
		   zone->pages_high,
 | 
			
		||||
		   zone->pages_scanned,
 | 
			
		||||
		   zone->nr_scan_active, zone->nr_scan_inactive,
 | 
			
		||||
		   zone->spanned_pages,
 | 
			
		||||
		   zone->present_pages);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
 | 
			
		||||
		seq_printf(m, "\n    %-12s %lu", vmstat_text[i],
 | 
			
		||||
				zone_page_state(zone, i));
 | 
			
		||||
 | 
			
		||||
	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_each_online_cpu(i) {
 | 
			
		||||
		struct per_cpu_pageset *pageset;
 | 
			
		||||
		int j;
 | 
			
		||||
 | 
			
		||||
		pageset = zone_pcp(zone, i);
 | 
			
		||||
		for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
 | 
			
		||||
			seq_printf(m,
 | 
			
		||||
				   "\n    cpu: %i pcp: %i"
 | 
			
		||||
				   "\n              count: %i"
 | 
			
		||||
				   "\n              high:  %i"
 | 
			
		||||
				   "\n              batch: %i",
 | 
			
		||||
				   i, j,
 | 
			
		||||
				   pageset->pcp[j].count,
 | 
			
		||||
				   pageset->pcp[j].high,
 | 
			
		||||
				   pageset->pcp[j].batch);
 | 
			
		||||
			}
 | 
			
		||||
#ifdef CONFIG_SMP
 | 
			
		||||
		seq_printf(m, "\n  vm stats threshold: %d",
 | 
			
		||||
				pageset->stat_threshold);
 | 
			
		||||
#endif
 | 
			
		||||
	}
 | 
			
		||||
	seq_printf(m,
 | 
			
		||||
		   "\n  all_unreclaimable: %u"
 | 
			
		||||
		   "\n  prev_priority:     %i"
 | 
			
		||||
		   "\n  start_pfn:         %lu",
 | 
			
		||||
		   zone->all_unreclaimable,
 | 
			
		||||
		   zone->prev_priority,
 | 
			
		||||
		   zone->zone_start_pfn);
 | 
			
		||||
	seq_putc(m, '\n');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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 (!populated_zone(zone))
 | 
			
		||||
			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        scanned  %lu (a: %lu i: %lu)"
 | 
			
		||||
			   "\n        spanned  %lu"
 | 
			
		||||
			   "\n        present  %lu",
 | 
			
		||||
			   zone_page_state(zone, NR_FREE_PAGES),
 | 
			
		||||
			   zone->pages_min,
 | 
			
		||||
			   zone->pages_low,
 | 
			
		||||
			   zone->pages_high,
 | 
			
		||||
			   zone->pages_scanned,
 | 
			
		||||
			   zone->nr_scan_active, zone->nr_scan_inactive,
 | 
			
		||||
			   zone->spanned_pages,
 | 
			
		||||
			   zone->present_pages);
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
 | 
			
		||||
			seq_printf(m, "\n    %-12s %lu", vmstat_text[i],
 | 
			
		||||
					zone_page_state(zone, i));
 | 
			
		||||
 | 
			
		||||
		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_each_online_cpu(i) {
 | 
			
		||||
			struct per_cpu_pageset *pageset;
 | 
			
		||||
			int j;
 | 
			
		||||
 | 
			
		||||
			pageset = zone_pcp(zone, i);
 | 
			
		||||
			for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
 | 
			
		||||
				seq_printf(m,
 | 
			
		||||
					   "\n    cpu: %i pcp: %i"
 | 
			
		||||
					   "\n              count: %i"
 | 
			
		||||
					   "\n              high:  %i"
 | 
			
		||||
					   "\n              batch: %i",
 | 
			
		||||
					   i, j,
 | 
			
		||||
					   pageset->pcp[j].count,
 | 
			
		||||
					   pageset->pcp[j].high,
 | 
			
		||||
					   pageset->pcp[j].batch);
 | 
			
		||||
			}
 | 
			
		||||
#ifdef CONFIG_SMP
 | 
			
		||||
			seq_printf(m, "\n  vm stats threshold: %d",
 | 
			
		||||
					pageset->stat_threshold);
 | 
			
		||||
#endif
 | 
			
		||||
		}
 | 
			
		||||
		seq_printf(m,
 | 
			
		||||
			   "\n  all_unreclaimable: %u"
 | 
			
		||||
			   "\n  prev_priority:     %i"
 | 
			
		||||
			   "\n  start_pfn:         %lu",
 | 
			
		||||
			   zone->all_unreclaimable,
 | 
			
		||||
			   zone->prev_priority,
 | 
			
		||||
			   zone->zone_start_pfn);
 | 
			
		||||
		spin_unlock_irqrestore(&zone->lock, flags);
 | 
			
		||||
		seq_putc(m, '\n');
 | 
			
		||||
	}
 | 
			
		||||
	pg_data_t *pgdat = (pg_data_t *)arg;
 | 
			
		||||
	walk_zones_in_node(m, pgdat, zoneinfo_show_print);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue