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

rhashtable: Use rcu_dereference_all and rcu_dereference_all_check

Add rcu_dereference_all and rcu_dereference_all_check so that
library code such as rhashtable can be used with any RCU variant.

As it stands rcu_dereference is used within rashtable, which
creates false-positive warnings if the user calls it from another
RCU context, such as preempt_disable().

Use the rcu_dereference_all and rcu_dereference_all_check calls
in rhashtable to suppress these warnings.

Also replace the rcu_dereference_raw calls in the list iterators
with rcu_dereference_all to uncover buggy calls.

Reported-by: Menglong Dong <dongml2@chinatelecom.cn>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

+33 -7
+26
include/linux/rcupdate.h
··· 713 713 (c) || rcu_read_lock_sched_held(), \ 714 714 __rcu) 715 715 716 + /** 717 + * rcu_dereference_all_check() - rcu_dereference_all with debug checking 718 + * @p: The pointer to read, prior to dereferencing 719 + * @c: The conditions under which the dereference will take place 720 + * 721 + * This is similar to rcu_dereference_check(), but allows protection 722 + * by all forms of vanilla RCU readers, including preemption disabled, 723 + * bh-disabled, and interrupt-disabled regions of code. Note that "vanilla 724 + * RCU" excludes SRCU and the various Tasks RCU flavors. Please note 725 + * that this macro should not be backported to any Linux-kernel version 726 + * preceding v5.0 due to changes in synchronize_rcu() semantics prior 727 + * to that version. 728 + */ 729 + #define rcu_dereference_all_check(p, c) \ 730 + __rcu_dereference_check((p), __UNIQUE_ID(rcu), \ 731 + (c) || rcu_read_lock_any_held(), \ 732 + __rcu) 733 + 716 734 /* 717 735 * The tracing infrastructure traces RCU (we want that), but unfortunately 718 736 * some of the RCU checks causes tracing to lock up the system. ··· 784 766 * Makes rcu_dereference_check() do the dirty work. 785 767 */ 786 768 #define rcu_dereference_sched(p) rcu_dereference_sched_check(p, 0) 769 + 770 + /** 771 + * rcu_dereference_all() - fetch RCU-all-protected pointer for dereferencing 772 + * @p: The pointer to read, prior to dereferencing 773 + * 774 + * Makes rcu_dereference_check() do the dirty work. 775 + */ 776 + #define rcu_dereference_all(p) rcu_dereference_all_check(p, 0) 787 777 788 778 /** 789 779 * rcu_pointer_handoff() - Hand off a pointer from RCU to other mechanism
+7 -7
include/linux/rhashtable.h
··· 272 272 rcu_dereference_protected(p, lockdep_rht_mutex_is_held(ht)) 273 273 274 274 #define rht_dereference_rcu(p, ht) \ 275 - rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht)) 275 + rcu_dereference_all_check(p, lockdep_rht_mutex_is_held(ht)) 276 276 277 277 #define rht_dereference_bucket(p, tbl, hash) \ 278 278 rcu_dereference_protected(p, lockdep_rht_bucket_is_held(tbl, hash)) 279 279 280 280 #define rht_dereference_bucket_rcu(p, tbl, hash) \ 281 - rcu_dereference_check(p, lockdep_rht_bucket_is_held(tbl, hash)) 281 + rcu_dereference_all_check(p, lockdep_rht_bucket_is_held(tbl, hash)) 282 282 283 283 #define rht_entry(tpos, pos, member) \ 284 284 ({ tpos = container_of(pos, typeof(*tpos), member); 1; }) ··· 373 373 static inline struct rhash_head *rht_ptr_rcu( 374 374 struct rhash_lock_head __rcu *const *bkt) 375 375 { 376 - return __rht_ptr(rcu_dereference(*bkt), bkt); 376 + return __rht_ptr(rcu_dereference_all(*bkt), bkt); 377 377 } 378 378 379 379 static inline struct rhash_head *rht_ptr( ··· 497 497 for (({barrier(); }), \ 498 498 pos = head; \ 499 499 !rht_is_a_nulls(pos); \ 500 - pos = rcu_dereference_raw(pos->next)) 500 + pos = rcu_dereference_all(pos->next)) 501 501 502 502 /** 503 503 * rht_for_each_rcu - iterate over rcu hash chain ··· 513 513 for (({barrier(); }), \ 514 514 pos = rht_ptr_rcu(rht_bucket(tbl, hash)); \ 515 515 !rht_is_a_nulls(pos); \ 516 - pos = rcu_dereference_raw(pos->next)) 516 + pos = rcu_dereference_all(pos->next)) 517 517 518 518 /** 519 519 * rht_for_each_entry_rcu_from - iterated over rcu hash chain from given head ··· 560 560 * list returned by rhltable_lookup. 561 561 */ 562 562 #define rhl_for_each_rcu(pos, list) \ 563 - for (pos = list; pos; pos = rcu_dereference_raw(pos->next)) 563 + for (pos = list; pos; pos = rcu_dereference_all(pos->next)) 564 564 565 565 /** 566 566 * rhl_for_each_entry_rcu - iterate over rcu hash table list of given type ··· 574 574 */ 575 575 #define rhl_for_each_entry_rcu(tpos, pos, list, member) \ 576 576 for (pos = list; pos && rht_entry(tpos, pos, member); \ 577 - pos = rcu_dereference_raw(pos->next)) 577 + pos = rcu_dereference_all(pos->next)) 578 578 579 579 static inline int rhashtable_compare(struct rhashtable_compare_arg *arg, 580 580 const void *obj)