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) { | ||||
| 		unsigned long long delta; | ||||
| 		unsigned long total_scan; | ||||
| 		unsigned long max_pass; | ||||
| 		long total_scan; | ||||
| 		long max_pass; | ||||
| 		int shrink_ret = 0; | ||||
| 		long nr; | ||||
| 		long new_nr; | ||||
| 		long batch_size = shrinker->batch ? shrinker->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 | ||||
| 		 * 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); | ||||
| 
 | ||||
| 		total_scan = nr; | ||||
| 		max_pass = do_shrinker_shrink(shrinker, shrink, 0); | ||||
| 		delta = (4 * nr_pages_scanned) / shrinker->seeks; | ||||
| 		delta *= max_pass; | ||||
| 		do_div(delta, lru_pages + 1); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Konstantin Khlebnikov
						Konstantin Khlebnikov