diff options
| author | Konstantin Khlebnikov <khlebnikov@openvz.org> | 2011-12-08 17:33:54 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-12-09 10:50:27 -0500 |
| commit | 83aeeada7c69f35e5100b27ec354335597a7a488 (patch) | |
| tree | 44644e68f303368feba7c8ba3e0e0991d6238ada | |
| parent | 635697c663f38106063d5659f0cf2e45afcd4bb5 (diff) | |
vmscan: use atomic-long for shrinker batching
Use atomic-long operations instead of looping around cmpxchg().
[akpm@linux-foundation.org: massage atomic.h inclusions]
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>
| -rw-r--r-- | include/linux/fs.h | 2 | ||||
| -rw-r--r-- | include/linux/mm.h | 1 | ||||
| -rw-r--r-- | include/linux/shrinker.h | 2 | ||||
| -rw-r--r-- | mm/vmscan.c | 17 |
4 files changed, 10 insertions, 12 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index 019dc558df1..e0bc4ffb8e7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -393,8 +393,8 @@ struct inodes_stat_t { | |||
| 393 | #include <linux/semaphore.h> | 393 | #include <linux/semaphore.h> |
| 394 | #include <linux/fiemap.h> | 394 | #include <linux/fiemap.h> |
| 395 | #include <linux/rculist_bl.h> | 395 | #include <linux/rculist_bl.h> |
| 396 | #include <linux/shrinker.h> | ||
| 397 | #include <linux/atomic.h> | 396 | #include <linux/atomic.h> |
| 397 | #include <linux/shrinker.h> | ||
| 398 | 398 | ||
| 399 | #include <asm/byteorder.h> | 399 | #include <asm/byteorder.h> |
| 400 | 400 | ||
diff --git a/include/linux/mm.h b/include/linux/mm.h index 3dc3a8c2c48..4baadd18f4a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/mmzone.h> | 10 | #include <linux/mmzone.h> |
| 11 | #include <linux/rbtree.h> | 11 | #include <linux/rbtree.h> |
| 12 | #include <linux/prio_tree.h> | 12 | #include <linux/prio_tree.h> |
| 13 | #include <linux/atomic.h> | ||
| 13 | #include <linux/debug_locks.h> | 14 | #include <linux/debug_locks.h> |
| 14 | #include <linux/mm_types.h> | 15 | #include <linux/mm_types.h> |
| 15 | #include <linux/range.h> | 16 | #include <linux/range.h> |
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index a83833a1f7a..07ceb97d53f 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h | |||
| @@ -35,7 +35,7 @@ struct shrinker { | |||
| 35 | 35 | ||
| 36 | /* These are for internal use */ | 36 | /* These are for internal use */ |
| 37 | struct list_head list; | 37 | struct list_head list; |
| 38 | long nr; /* objs pending delete */ | 38 | atomic_long_t nr_in_batch; /* objs pending delete */ |
| 39 | }; | 39 | }; |
| 40 | #define DEFAULT_SEEKS 2 /* A good number if you don't know better. */ | 40 | #define DEFAULT_SEEKS 2 /* A good number if you don't know better. */ |
| 41 | extern void register_shrinker(struct shrinker *); | 41 | extern void register_shrinker(struct shrinker *); |
diff --git a/mm/vmscan.c b/mm/vmscan.c index f5255442ae2..f54a05b7a61 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -183,7 +183,7 @@ static unsigned long zone_nr_lru_pages(struct zone *zone, | |||
| 183 | */ | 183 | */ |
| 184 | void register_shrinker(struct shrinker *shrinker) | 184 | void register_shrinker(struct shrinker *shrinker) |
| 185 | { | 185 | { |
| 186 | shrinker->nr = 0; | 186 | atomic_long_set(&shrinker->nr_in_batch, 0); |
| 187 | down_write(&shrinker_rwsem); | 187 | down_write(&shrinker_rwsem); |
| 188 | list_add_tail(&shrinker->list, &shrinker_list); | 188 | list_add_tail(&shrinker->list, &shrinker_list); |
| 189 | up_write(&shrinker_rwsem); | 189 | up_write(&shrinker_rwsem); |
| @@ -264,9 +264,7 @@ unsigned long shrink_slab(struct shrink_control *shrink, | |||
| 264 | * and zero it so that other concurrent shrinker invocations | 264 | * and zero it so that other concurrent shrinker invocations |
| 265 | * don't also do this scanning work. | 265 | * don't also do this scanning work. |
| 266 | */ | 266 | */ |
| 267 | do { | 267 | nr = atomic_long_xchg(&shrinker->nr_in_batch, 0); |
| 268 | nr = shrinker->nr; | ||
| 269 | } while (cmpxchg(&shrinker->nr, nr, 0) != nr); | ||
| 270 | 268 | ||
| 271 | total_scan = nr; | 269 | total_scan = nr; |
| 272 | delta = (4 * nr_pages_scanned) / shrinker->seeks; | 270 | delta = (4 * nr_pages_scanned) / shrinker->seeks; |
| @@ -328,12 +326,11 @@ unsigned long shrink_slab(struct shrink_control *shrink, | |||
| 328 | * manner that handles concurrent updates. If we exhausted the | 326 | * manner that handles concurrent updates. If we exhausted the |
| 329 | * scan, there is no need to do an update. | 327 | * scan, there is no need to do an update. |
| 330 | */ | 328 | */ |
| 331 | do { | 329 | if (total_scan > 0) |
| 332 | nr = shrinker->nr; | 330 | new_nr = atomic_long_add_return(total_scan, |
| 333 | new_nr = total_scan + nr; | 331 | &shrinker->nr_in_batch); |
| 334 | if (total_scan <= 0) | 332 | else |
| 335 | break; | 333 | new_nr = atomic_long_read(&shrinker->nr_in_batch); |
| 336 | } while (cmpxchg(&shrinker->nr, nr, new_nr) != nr); | ||
| 337 | 334 | ||
| 338 | trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr); | 335 | trace_mm_shrink_slab_end(shrinker, shrink_ret, nr, new_nr); |
| 339 | } | 336 | } |
