aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/shrinker.h38
-rw-r--r--mm/vmscan.c60
2 files changed, 69 insertions, 29 deletions
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h
index ac6b8ee07825..884e76222e1b 100644
--- a/include/linux/shrinker.h
+++ b/include/linux/shrinker.h
@@ -4,6 +4,12 @@
4/* 4/*
5 * This struct is used to pass information from page reclaim to the shrinkers. 5 * This struct is used to pass information from page reclaim to the shrinkers.
6 * We consolidate the values for easier extention later. 6 * We consolidate the values for easier extention later.
7 *
8 * The 'gfpmask' refers to the allocation we are currently trying to
9 * fulfil.
10 *
11 * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is
12 * querying the cache size, so a fastpath for that case is appropriate.
7 */ 13 */
8struct shrink_control { 14struct shrink_control {
9 gfp_t gfp_mask; 15 gfp_t gfp_mask;
@@ -12,23 +18,37 @@ struct shrink_control {
12 unsigned long nr_to_scan; 18 unsigned long nr_to_scan;
13}; 19};
14 20
21#define SHRINK_STOP (~0UL)
15/* 22/*
16 * A callback you can register to apply pressure to ageable caches. 23 * A callback you can register to apply pressure to ageable caches.
17 * 24 *
18 * 'sc' is passed shrink_control which includes a count 'nr_to_scan' 25 * @shrink() should look through the least-recently-used 'nr_to_scan' entries
19 * and a 'gfpmask'. It should look through the least-recently-used 26 * and attempt to free them up. It should return the number of objects which
20 * 'nr_to_scan' entries and attempt to free them up. It should return 27 * remain in the cache. If it returns -1, it means it cannot do any scanning at
21 * the number of objects which remain in the cache. If it returns -1, it means 28 * this time (eg. there is a risk of deadlock).
22 * it cannot do any scanning at this time (eg. there is a risk of deadlock).
23 * 29 *
24 * The 'gfpmask' refers to the allocation we are currently trying to 30 * @count_objects should return the number of freeable items in the cache. If
25 * fulfil. 31 * there are no objects to free or the number of freeable items cannot be
32 * determined, it should return 0. No deadlock checks should be done during the
33 * count callback - the shrinker relies on aggregating scan counts that couldn't
34 * be executed due to potential deadlocks to be run at a later call when the
35 * deadlock condition is no longer pending.
26 * 36 *
27 * Note that 'shrink' will be passed nr_to_scan == 0 when the VM is 37 * @scan_objects will only be called if @count_objects returned a non-zero
28 * querying the cache size, so a fastpath for that case is appropriate. 38 * value for the number of freeable objects. The callout should scan the cache
39 * and attempt to free items from the cache. It should then return the number
40 * of objects freed during the scan, or SHRINK_STOP if progress cannot be made
41 * due to potential deadlocks. If SHRINK_STOP is returned, then no further
42 * attempts to call the @scan_objects will be made from the current reclaim
43 * context.
29 */ 44 */
30struct shrinker { 45struct shrinker {
31 int (*shrink)(struct shrinker *, struct shrink_control *sc); 46 int (*shrink)(struct shrinker *, struct shrink_control *sc);
47 unsigned long (*count_objects)(struct shrinker *,
48 struct shrink_control *sc);
49 unsigned long (*scan_objects)(struct shrinker *,
50 struct shrink_control *sc);
51
32 int seeks; /* seeks to recreate an obj */ 52 int seeks; /* seeks to recreate an obj */
33 long batch; /* reclaim batch size, 0 = default */ 53 long batch; /* reclaim batch size, 0 = default */
34 54
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 2cff0d491c6d..4d4e859b4b9c 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -205,19 +205,24 @@ static inline int do_shrinker_shrink(struct shrinker *shrinker,
205 * 205 *
206 * Returns the number of slab objects which we shrunk. 206 * Returns the number of slab objects which we shrunk.
207 */ 207 */
208unsigned long shrink_slab(struct shrink_control *shrink, 208unsigned long shrink_slab(struct shrink_control *shrinkctl,
209 unsigned long nr_pages_scanned, 209 unsigned long nr_pages_scanned,
210 unsigned long lru_pages) 210 unsigned long lru_pages)
211{ 211{
212 struct shrinker *shrinker; 212 struct shrinker *shrinker;
213 unsigned long ret = 0; 213 unsigned long freed = 0;
214 214
215 if (nr_pages_scanned == 0) 215 if (nr_pages_scanned == 0)
216 nr_pages_scanned = SWAP_CLUSTER_MAX; 216 nr_pages_scanned = SWAP_CLUSTER_MAX;
217 217
218 if (!down_read_trylock(&shrinker_rwsem)) { 218 if (!down_read_trylock(&shrinker_rwsem)) {
219 /* Assume we'll be able to shrink next time */ 219 /*
220 ret = 1; 220 * If we would return 0, our callers would understand that we
221 * have nothing else to shrink and give up trying. By returning
222 * 1 we keep it going and assume we'll be able to shrink next
223 * time.
224 */
225 freed = 1;
221 goto out; 226 goto out;
222 } 227 }
223 228
@@ -225,14 +230,16 @@ unsigned long shrink_slab(struct shrink_control *shrink,
225 unsigned long long delta; 230 unsigned long long delta;
226 long total_scan; 231 long total_scan;
227 long max_pass; 232 long max_pass;
228 int shrink_ret = 0;
229 long nr; 233 long nr;
230 long new_nr; 234 long new_nr;
231 long batch_size = shrinker->batch ? shrinker->batch 235 long batch_size = shrinker->batch ? shrinker->batch
232 : SHRINK_BATCH; 236 : SHRINK_BATCH;
233 237
234 max_pass = do_shrinker_shrink(shrinker, shrink, 0); 238 if (shrinker->count_objects)
235 if (max_pass <= 0) 239 max_pass = shrinker->count_objects(shrinker, shrinkctl);
240 else
241 max_pass = do_shrinker_shrink(shrinker, shrinkctl, 0);
242 if (max_pass == 0)
236 continue; 243 continue;
237 244
238 /* 245 /*
@@ -248,8 +255,8 @@ unsigned long shrink_slab(struct shrink_control *shrink,
248 do_div(delta, lru_pages + 1); 255 do_div(delta, lru_pages + 1);
249 total_scan += delta; 256 total_scan += delta;
250 if (total_scan < 0) { 257 if (total_scan < 0) {
251 printk(KERN_ERR "shrink_slab: %pF negative objects to " 258 printk(KERN_ERR
252 "delete nr=%ld\n", 259 "shrink_slab: %pF negative objects to delete nr=%ld\n",
253 shrinker->shrink, total_scan); 260 shrinker->shrink, total_scan);
254 total_scan = max_pass; 261 total_scan = max_pass;
255 } 262 }
@@ -277,20 +284,33 @@ unsigned long shrink_slab(struct shrink_control *shrink,
277 if (total_scan > max_pass * 2) 284 if (total_scan > max_pass * 2)
278 total_scan = max_pass * 2; 285 total_scan = max_pass * 2;
279 286
280 trace_mm_shrink_slab_start(shrinker, shrink, nr, 287 trace_mm_shrink_slab_start(shrinker, shrinkctl, nr,
281 nr_pages_scanned, lru_pages, 288 nr_pages_scanned, lru_pages,
282 max_pass, delta, total_scan); 289 max_pass, delta, total_scan);
283 290
284 while (total_scan >= batch_size) { 291 while (total_scan >= batch_size) {
285 int nr_before;
286 292
287 nr_before = do_shrinker_shrink(shrinker, shrink, 0); 293 if (shrinker->scan_objects) {
288 shrink_ret = do_shrinker_shrink(shrinker, shrink, 294 unsigned long ret;
289 batch_size); 295 shrinkctl->nr_to_scan = batch_size;
290 if (shrink_ret == -1) 296 ret = shrinker->scan_objects(shrinker, shrinkctl);
291 break; 297
292 if (shrink_ret < nr_before) 298 if (ret == SHRINK_STOP)
293 ret += nr_before - shrink_ret; 299 break;
300 freed += ret;
301 } else {
302 int nr_before;
303 long ret;
304
305 nr_before = do_shrinker_shrink(shrinker, shrinkctl, 0);
306 ret = do_shrinker_shrink(shrinker, shrinkctl,
307 batch_size);
308 if (ret == -1)
309 break;
310 if (ret < nr_before)
311 freed += nr_before - ret;
312 }
313
294 count_vm_events(SLABS_SCANNED, batch_size); 314 count_vm_events(SLABS_SCANNED, batch_size);
295 total_scan -= batch_size; 315 total_scan -= batch_size;
296 316
@@ -308,12 +328,12 @@ unsigned long shrink_slab(struct shrink_control *shrink,
308 else 328 else
309 new_nr = atomic_long_read(&shrinker->nr_in_batch); 329 new_nr = atomic_long_read(&shrinker->nr_in_batch);
310 330
311 trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr); 331 trace_mm_shrink_slab_end(shrinker, freed, nr, new_nr);
312 } 332 }
313 up_read(&shrinker_rwsem); 333 up_read(&shrinker_rwsem);
314out: 334out:
315 cond_resched(); 335 cond_resched();
316 return ret; 336 return freed;
317} 337}
318 338
319static inline int is_page_cache_freeable(struct page *page) 339static inline int is_page_cache_freeable(struct page *page)