diff options
Diffstat (limited to 'mm/vmstat.c')
| -rw-r--r-- | mm/vmstat.c | 25 | 
1 files changed, 21 insertions, 4 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c index 6afc892a148a..a8222041bd44 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1383,12 +1383,29 @@ static void pagetypeinfo_showfree_print(struct seq_file *m,  			unsigned long freecount = 0;  			struct free_area *area;  			struct list_head *curr; +			bool overflow = false;  			area = &(zone->free_area[order]); -			list_for_each(curr, &area->free_list[mtype]) -				freecount++; -			seq_printf(m, "%6lu ", freecount); +			list_for_each(curr, &area->free_list[mtype]) { +				/* +				 * Cap the free_list iteration because it might +				 * be really large and we are under a spinlock +				 * so a long time spent here could trigger a +				 * hard lockup detector. Anyway this is a +				 * debugging tool so knowing there is a handful +				 * of pages of this order should be more than +				 * sufficient. +				 */ +				if (++freecount >= 100000) { +					overflow = true; +					break; +				} +			} +			seq_printf(m, "%s%6lu ", overflow ? ">" : "", freecount); +			spin_unlock_irq(&zone->lock); +			cond_resched(); +			spin_lock_irq(&zone->lock);  		}  		seq_putc(m, '\n');  	} @@ -1972,7 +1989,7 @@ void __init init_mm_internals(void)  #endif  #ifdef CONFIG_PROC_FS  	proc_create_seq("buddyinfo", 0444, NULL, &fragmentation_op); -	proc_create_seq("pagetypeinfo", 0444, NULL, &pagetypeinfo_op); +	proc_create_seq("pagetypeinfo", 0400, NULL, &pagetypeinfo_op);  	proc_create_seq("vmstat", 0444, NULL, &vmstat_op);  	proc_create_seq("zoneinfo", 0444, NULL, &zoneinfo_op);  #endif  | 
