diff options
-rw-r--r-- | fs/super.c | 3 | ||||
-rw-r--r-- | include/linux/shrinker.h | 7 | ||||
-rw-r--r-- | mm/vmscan.c | 12 | ||||
-rw-r--r-- | mm/workingset.c | 3 |
4 files changed, 20 insertions, 5 deletions
diff --git a/fs/super.c b/fs/super.c index f5f96e52e0cd..7429588d6b49 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -144,6 +144,9 @@ static unsigned long super_cache_count(struct shrinker *shrink, | |||
144 | total_objects += list_lru_shrink_count(&sb->s_dentry_lru, sc); | 144 | total_objects += list_lru_shrink_count(&sb->s_dentry_lru, sc); |
145 | total_objects += list_lru_shrink_count(&sb->s_inode_lru, sc); | 145 | total_objects += list_lru_shrink_count(&sb->s_inode_lru, sc); |
146 | 146 | ||
147 | if (!total_objects) | ||
148 | return SHRINK_EMPTY; | ||
149 | |||
147 | total_objects = vfs_pressure_ratio(total_objects); | 150 | total_objects = vfs_pressure_ratio(total_objects); |
148 | return total_objects; | 151 | return total_objects; |
149 | } | 152 | } |
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index 7ca9c18cf130..b154fd2b084c 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h | |||
@@ -34,12 +34,15 @@ struct shrink_control { | |||
34 | }; | 34 | }; |
35 | 35 | ||
36 | #define SHRINK_STOP (~0UL) | 36 | #define SHRINK_STOP (~0UL) |
37 | #define SHRINK_EMPTY (~0UL - 1) | ||
37 | /* | 38 | /* |
38 | * A callback you can register to apply pressure to ageable caches. | 39 | * A callback you can register to apply pressure to ageable caches. |
39 | * | 40 | * |
40 | * @count_objects should return the number of freeable items in the cache. If | 41 | * @count_objects should return the number of freeable items in the cache. If |
41 | * there are no objects to free or the number of freeable items cannot be | 42 | * there are no objects to free, it should return SHRINK_EMPTY, while 0 is |
42 | * determined, it should return 0. No deadlock checks should be done during the | 43 | * returned in cases of the number of freeable items cannot be determined |
44 | * or shrinker should skip this cache for this time (e.g., their number | ||
45 | * is below shrinkable limit). No deadlock checks should be done during the | ||
43 | * count callback - the shrinker relies on aggregating scan counts that couldn't | 46 | * count callback - the shrinker relies on aggregating scan counts that couldn't |
44 | * be executed due to potential deadlocks to be run at a later call when the | 47 | * be executed due to potential deadlocks to be run at a later call when the |
45 | * deadlock condition is no longer pending. | 48 | * deadlock condition is no longer pending. |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 2aa3cb760189..8199e1b9a204 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -456,8 +456,8 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl, | |||
456 | long scanned = 0, next_deferred; | 456 | long scanned = 0, next_deferred; |
457 | 457 | ||
458 | freeable = shrinker->count_objects(shrinker, shrinkctl); | 458 | freeable = shrinker->count_objects(shrinker, shrinkctl); |
459 | if (freeable == 0) | 459 | if (freeable == 0 || freeable == SHRINK_EMPTY) |
460 | return 0; | 460 | return freeable; |
461 | 461 | ||
462 | /* | 462 | /* |
463 | * copy the current shrinker scan count into a local variable | 463 | * copy the current shrinker scan count into a local variable |
@@ -596,6 +596,8 @@ static unsigned long shrink_slab_memcg(gfp_t gfp_mask, int nid, | |||
596 | continue; | 596 | continue; |
597 | 597 | ||
598 | ret = do_shrink_slab(&sc, shrinker, priority); | 598 | ret = do_shrink_slab(&sc, shrinker, priority); |
599 | if (ret == SHRINK_EMPTY) | ||
600 | ret = 0; | ||
599 | freed += ret; | 601 | freed += ret; |
600 | 602 | ||
601 | if (rwsem_is_contended(&shrinker_rwsem)) { | 603 | if (rwsem_is_contended(&shrinker_rwsem)) { |
@@ -641,6 +643,7 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid, | |||
641 | { | 643 | { |
642 | struct shrinker *shrinker; | 644 | struct shrinker *shrinker; |
643 | unsigned long freed = 0; | 645 | unsigned long freed = 0; |
646 | int ret; | ||
644 | 647 | ||
645 | if (!mem_cgroup_is_root(memcg)) | 648 | if (!mem_cgroup_is_root(memcg)) |
646 | return shrink_slab_memcg(gfp_mask, nid, memcg, priority); | 649 | return shrink_slab_memcg(gfp_mask, nid, memcg, priority); |
@@ -658,7 +661,10 @@ static unsigned long shrink_slab(gfp_t gfp_mask, int nid, | |||
658 | if (!(shrinker->flags & SHRINKER_NUMA_AWARE)) | 661 | if (!(shrinker->flags & SHRINKER_NUMA_AWARE)) |
659 | sc.nid = 0; | 662 | sc.nid = 0; |
660 | 663 | ||
661 | freed += do_shrink_slab(&sc, shrinker, priority); | 664 | ret = do_shrink_slab(&sc, shrinker, priority); |
665 | if (ret == SHRINK_EMPTY) | ||
666 | ret = 0; | ||
667 | freed += ret; | ||
662 | /* | 668 | /* |
663 | * Bail out if someone want to register a new shrinker to | 669 | * Bail out if someone want to register a new shrinker to |
664 | * prevent the regsitration from being stalled for long periods | 670 | * prevent the regsitration from being stalled for long periods |
diff --git a/mm/workingset.c b/mm/workingset.c index cd0b2ae615e4..bc72ad029b3e 100644 --- a/mm/workingset.c +++ b/mm/workingset.c | |||
@@ -399,6 +399,9 @@ static unsigned long count_shadow_nodes(struct shrinker *shrinker, | |||
399 | } | 399 | } |
400 | max_nodes = cache >> (RADIX_TREE_MAP_SHIFT - 3); | 400 | max_nodes = cache >> (RADIX_TREE_MAP_SHIFT - 3); |
401 | 401 | ||
402 | if (!nodes) | ||
403 | return SHRINK_EMPTY; | ||
404 | |||
402 | if (nodes <= max_nodes) | 405 | if (nodes <= max_nodes) |
403 | return 0; | 406 | return 0; |
404 | return nodes - max_nodes; | 407 | return nodes - max_nodes; |