Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Matthew Wilcox and committed by
Linus Torvalds
7165092f 2cf938aa

+19 -9
+16
include/linux/radix-tree.h
··· 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 422 * radix_tree_chunk_size - get current chunk size 407 423 * 408 424 * @iter: pointer to radix tree iterator
+3 -9
mm/shmem.c
··· 376 376 377 377 rcu_read_lock(); 378 378 379 - restart: 380 379 radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { 381 380 if (iter.index >= end) 382 381 break; ··· 392 393 393 394 if (need_resched()) { 394 395 cond_resched_rcu(); 395 - start = iter.index + 1; 396 - goto restart; 396 + slot = radix_tree_iter_next(&iter); 397 397 } 398 398 } 399 399 ··· 1942 1944 start = 0; 1943 1945 rcu_read_lock(); 1944 1946 1945 - restart: 1946 1947 radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { 1947 1948 page = radix_tree_deref_slot(slot); 1948 1949 if (!page || radix_tree_exception(page)) { ··· 1958 1961 1959 1962 if (need_resched()) { 1960 1963 cond_resched_rcu(); 1961 - start = iter.index + 1; 1962 - goto restart; 1964 + slot = radix_tree_iter_next(&iter); 1963 1965 } 1964 1966 } 1965 1967 rcu_read_unlock(); ··· 1995 1999 1996 2000 start = 0; 1997 2001 rcu_read_lock(); 1998 - restart: 1999 2002 radix_tree_for_each_tagged(slot, &mapping->page_tree, &iter, 2000 2003 start, SHMEM_TAG_PINNED) { 2001 2004 ··· 2028 2033 continue_resched: 2029 2034 if (need_resched()) { 2030 2035 cond_resched_rcu(); 2031 - start = iter.index + 1; 2032 - goto restart; 2036 + slot = radix_tree_iter_next(&iter); 2033 2037 } 2034 2038 } 2035 2039 rcu_read_unlock();