diff options
author | Matthew Wilcox <willy@linux.intel.com> | 2016-03-17 17:22:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-17 18:09:34 -0400 |
commit | 7165092fe5ca70bae722ac6cd78421cfd0eec18d (patch) | |
tree | 93714621a6b7e4c7ba20677a5c7f408795132e8c | |
parent | 2cf938aae17203426a89b5955bd1c9668657bfa8 (diff) |
radix-tree,shmem: introduce radix_tree_iter_next()
shmem likes to occasionally drop the lock, schedule, then reacqire the
lock and continue with the iteration from the last place it left off.
This is currently done with a pretty ugly goto. Introduce
radix_tree_iter_next() and use it throughout shmem.c.
[koct9i@gmail.com: fix bug in radix_tree_iter_next() for tagged iteration]
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/radix-tree.h | 16 | ||||
-rw-r--r-- | mm/shmem.c | 12 |
2 files changed, 19 insertions, 9 deletions
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index b211f145c811..51a97ac8bfbf 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h | |||
@@ -403,6 +403,22 @@ void **radix_tree_iter_retry(struct radix_tree_iter *iter) | |||
403 | } | 403 | } |
404 | 404 | ||
405 | /** | 405 | /** |
406 | * radix_tree_iter_next - resume iterating when the chunk may be invalid | ||
407 | * @iter: iterator state | ||
408 | * | ||
409 | * If the iterator needs to release then reacquire a lock, the chunk may | ||
410 | * have been invalidated by an insertion or deletion. Call this function | ||
411 | * to continue the iteration from the next index. | ||
412 | */ | ||
413 | static inline __must_check | ||
414 | void **radix_tree_iter_next(struct radix_tree_iter *iter) | ||
415 | { | ||
416 | iter->next_index = iter->index + 1; | ||
417 | iter->tags = 0; | ||
418 | return NULL; | ||
419 | } | ||
420 | |||
421 | /** | ||
406 | * radix_tree_chunk_size - get current chunk size | 422 | * radix_tree_chunk_size - get current chunk size |
407 | * | 423 | * |
408 | * @iter: pointer to radix tree iterator | 424 | * @iter: pointer to radix tree iterator |
diff --git a/mm/shmem.c b/mm/shmem.c index 91c0dadf48d3..9428c51ab2d6 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -376,7 +376,6 @@ unsigned long shmem_partial_swap_usage(struct address_space *mapping, | |||
376 | 376 | ||
377 | rcu_read_lock(); | 377 | rcu_read_lock(); |
378 | 378 | ||
379 | restart: | ||
380 | radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { | 379 | radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { |
381 | if (iter.index >= end) | 380 | if (iter.index >= end) |
382 | break; | 381 | break; |
@@ -393,8 +392,7 @@ restart: | |||
393 | 392 | ||
394 | if (need_resched()) { | 393 | if (need_resched()) { |
395 | cond_resched_rcu(); | 394 | cond_resched_rcu(); |
396 | start = iter.index + 1; | 395 | slot = radix_tree_iter_next(&iter); |
397 | goto restart; | ||
398 | } | 396 | } |
399 | } | 397 | } |
400 | 398 | ||
@@ -1944,7 +1942,6 @@ static void shmem_tag_pins(struct address_space *mapping) | |||
1944 | start = 0; | 1942 | start = 0; |
1945 | rcu_read_lock(); | 1943 | rcu_read_lock(); |
1946 | 1944 | ||
1947 | restart: | ||
1948 | radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { | 1945 | radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { |
1949 | page = radix_tree_deref_slot(slot); | 1946 | page = radix_tree_deref_slot(slot); |
1950 | if (!page || radix_tree_exception(page)) { | 1947 | if (!page || radix_tree_exception(page)) { |
@@ -1961,8 +1958,7 @@ restart: | |||
1961 | 1958 | ||
1962 | if (need_resched()) { | 1959 | if (need_resched()) { |
1963 | cond_resched_rcu(); | 1960 | cond_resched_rcu(); |
1964 | start = iter.index + 1; | 1961 | slot = radix_tree_iter_next(&iter); |
1965 | goto restart; | ||
1966 | } | 1962 | } |
1967 | } | 1963 | } |
1968 | rcu_read_unlock(); | 1964 | rcu_read_unlock(); |
@@ -1999,7 +1995,6 @@ static int shmem_wait_for_pins(struct address_space *mapping) | |||
1999 | 1995 | ||
2000 | start = 0; | 1996 | start = 0; |
2001 | rcu_read_lock(); | 1997 | rcu_read_lock(); |
2002 | restart: | ||
2003 | radix_tree_for_each_tagged(slot, &mapping->page_tree, &iter, | 1998 | radix_tree_for_each_tagged(slot, &mapping->page_tree, &iter, |
2004 | start, SHMEM_TAG_PINNED) { | 1999 | start, SHMEM_TAG_PINNED) { |
2005 | 2000 | ||
@@ -2033,8 +2028,7 @@ restart: | |||
2033 | continue_resched: | 2028 | continue_resched: |
2034 | if (need_resched()) { | 2029 | if (need_resched()) { |
2035 | cond_resched_rcu(); | 2030 | cond_resched_rcu(); |
2036 | start = iter.index + 1; | 2031 | slot = radix_tree_iter_next(&iter); |
2037 | goto restart; | ||
2038 | } | 2032 | } |
2039 | } | 2033 | } |
2040 | rcu_read_unlock(); | 2034 | rcu_read_unlock(); |