forked from mirrors/linux
		
	vmscan: fix initial shrinker size handling
A shrinker function can return -1, means that it cannot do anything without a risk of deadlock. For example prune_super() does this if it cannot grab a superblock refrence, even if nr_to_scan=0. Currently we interpret this -1 as a ULONG_MAX size shrinker and evaluate `total_scan' according to this. So the next time around this shrinker can cause really big pressure. Let's skip such shrinkers instead. Also make total_scan signed, otherwise the check (total_scan < 0) below never works. Signed-off-by: Konstantin Khlebnikov <khlebnikov@openvz.org> Cc: Dave Chinner <david@fromorbit.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
							
								
									09d9673d53
								
							
						
					
					
						commit
						635697c663
					
				
					 1 changed files with 6 additions and 3 deletions
				
			
		| 
						 | 
					@ -247,14 +247,18 @@ unsigned long shrink_slab(struct shrink_control *shrink,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(shrinker, &shrinker_list, list) {
 | 
						list_for_each_entry(shrinker, &shrinker_list, list) {
 | 
				
			||||||
		unsigned long long delta;
 | 
							unsigned long long delta;
 | 
				
			||||||
		unsigned long total_scan;
 | 
							long total_scan;
 | 
				
			||||||
		unsigned long max_pass;
 | 
							long max_pass;
 | 
				
			||||||
		int shrink_ret = 0;
 | 
							int shrink_ret = 0;
 | 
				
			||||||
		long nr;
 | 
							long nr;
 | 
				
			||||||
		long new_nr;
 | 
							long new_nr;
 | 
				
			||||||
		long batch_size = shrinker->batch ? shrinker->batch
 | 
							long batch_size = shrinker->batch ? shrinker->batch
 | 
				
			||||||
						  : SHRINK_BATCH;
 | 
											  : SHRINK_BATCH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							max_pass = do_shrinker_shrink(shrinker, shrink, 0);
 | 
				
			||||||
 | 
							if (max_pass <= 0)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * copy the current shrinker scan count into a local variable
 | 
							 * copy the current shrinker scan count into a local variable
 | 
				
			||||||
		 * and zero it so that other concurrent shrinker invocations
 | 
							 * and zero it so that other concurrent shrinker invocations
 | 
				
			||||||
| 
						 | 
					@ -265,7 +269,6 @@ unsigned long shrink_slab(struct shrink_control *shrink,
 | 
				
			||||||
		} while (cmpxchg(&shrinker->nr, nr, 0) != nr);
 | 
							} while (cmpxchg(&shrinker->nr, nr, 0) != nr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		total_scan = nr;
 | 
							total_scan = nr;
 | 
				
			||||||
		max_pass = do_shrinker_shrink(shrinker, shrink, 0);
 | 
					 | 
				
			||||||
		delta = (4 * nr_pages_scanned) / shrinker->seeks;
 | 
							delta = (4 * nr_pages_scanned) / shrinker->seeks;
 | 
				
			||||||
		delta *= max_pass;
 | 
							delta *= max_pass;
 | 
				
			||||||
		do_div(delta, lru_pages + 1);
 | 
							do_div(delta, lru_pages + 1);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue