mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:04:41 +01:00
rhashtable: Enable context analysis
Enable context analysis for rhashtable, which was used as an initial test as it contains a combination of RCU, mutex, and bit_spinlock usage. Users of rhashtable now also benefit from annotations on the API, which will now warn if the RCU read lock is not held where required. Signed-off-by: Marco Elver <elver@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20251219154418.3592607-33-elver@google.com
This commit is contained in:
parent
c3d3023f1c
commit
322366b8f1
3 changed files with 18 additions and 5 deletions
|
|
@ -245,16 +245,17 @@ void *rhashtable_insert_slow(struct rhashtable *ht, const void *key,
|
|||
void rhashtable_walk_enter(struct rhashtable *ht,
|
||||
struct rhashtable_iter *iter);
|
||||
void rhashtable_walk_exit(struct rhashtable_iter *iter);
|
||||
int rhashtable_walk_start_check(struct rhashtable_iter *iter) __acquires(RCU);
|
||||
int rhashtable_walk_start_check(struct rhashtable_iter *iter) __acquires_shared(RCU);
|
||||
|
||||
static inline void rhashtable_walk_start(struct rhashtable_iter *iter)
|
||||
__acquires_shared(RCU)
|
||||
{
|
||||
(void)rhashtable_walk_start_check(iter);
|
||||
}
|
||||
|
||||
void *rhashtable_walk_next(struct rhashtable_iter *iter);
|
||||
void *rhashtable_walk_peek(struct rhashtable_iter *iter);
|
||||
void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases(RCU);
|
||||
void rhashtable_walk_stop(struct rhashtable_iter *iter) __releases_shared(RCU);
|
||||
|
||||
void rhashtable_free_and_destroy(struct rhashtable *ht,
|
||||
void (*free_fn)(void *ptr, void *arg),
|
||||
|
|
@ -325,6 +326,7 @@ static inline struct rhash_lock_head __rcu **rht_bucket_insert(
|
|||
|
||||
static inline unsigned long rht_lock(struct bucket_table *tbl,
|
||||
struct rhash_lock_head __rcu **bkt)
|
||||
__acquires(__bitlock(0, bkt))
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -337,6 +339,7 @@ static inline unsigned long rht_lock(struct bucket_table *tbl,
|
|||
static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
|
||||
struct rhash_lock_head __rcu **bucket,
|
||||
unsigned int subclass)
|
||||
__acquires(__bitlock(0, bucket))
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
|
@ -349,6 +352,7 @@ static inline unsigned long rht_lock_nested(struct bucket_table *tbl,
|
|||
static inline void rht_unlock(struct bucket_table *tbl,
|
||||
struct rhash_lock_head __rcu **bkt,
|
||||
unsigned long flags)
|
||||
__releases(__bitlock(0, bkt))
|
||||
{
|
||||
lock_map_release(&tbl->dep_map);
|
||||
bit_spin_unlock(0, (unsigned long *)bkt);
|
||||
|
|
@ -424,13 +428,14 @@ static inline void rht_assign_unlock(struct bucket_table *tbl,
|
|||
struct rhash_lock_head __rcu **bkt,
|
||||
struct rhash_head *obj,
|
||||
unsigned long flags)
|
||||
__releases(__bitlock(0, bkt))
|
||||
{
|
||||
if (rht_is_a_nulls(obj))
|
||||
obj = NULL;
|
||||
lock_map_release(&tbl->dep_map);
|
||||
rcu_assign_pointer(*bkt, (void *)obj);
|
||||
preempt_enable();
|
||||
__release(bitlock);
|
||||
__release(__bitlock(0, bkt));
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
|
@ -612,6 +617,7 @@ static __always_inline struct rhash_head *__rhashtable_lookup(
|
|||
struct rhashtable *ht, const void *key,
|
||||
const struct rhashtable_params params,
|
||||
const enum rht_lookup_freq freq)
|
||||
__must_hold_shared(RCU)
|
||||
{
|
||||
struct rhashtable_compare_arg arg = {
|
||||
.ht = ht,
|
||||
|
|
@ -666,6 +672,7 @@ restart:
|
|||
static __always_inline void *rhashtable_lookup(
|
||||
struct rhashtable *ht, const void *key,
|
||||
const struct rhashtable_params params)
|
||||
__must_hold_shared(RCU)
|
||||
{
|
||||
struct rhash_head *he = __rhashtable_lookup(ht, key, params,
|
||||
RHT_LOOKUP_NORMAL);
|
||||
|
|
@ -676,6 +683,7 @@ static __always_inline void *rhashtable_lookup(
|
|||
static __always_inline void *rhashtable_lookup_likely(
|
||||
struct rhashtable *ht, const void *key,
|
||||
const struct rhashtable_params params)
|
||||
__must_hold_shared(RCU)
|
||||
{
|
||||
struct rhash_head *he = __rhashtable_lookup(ht, key, params,
|
||||
RHT_LOOKUP_LIKELY);
|
||||
|
|
@ -727,6 +735,7 @@ static __always_inline void *rhashtable_lookup_fast(
|
|||
static __always_inline struct rhlist_head *rhltable_lookup(
|
||||
struct rhltable *hlt, const void *key,
|
||||
const struct rhashtable_params params)
|
||||
__must_hold_shared(RCU)
|
||||
{
|
||||
struct rhash_head *he = __rhashtable_lookup(&hlt->ht, key, params,
|
||||
RHT_LOOKUP_NORMAL);
|
||||
|
|
@ -737,6 +746,7 @@ static __always_inline struct rhlist_head *rhltable_lookup(
|
|||
static __always_inline struct rhlist_head *rhltable_lookup_likely(
|
||||
struct rhltable *hlt, const void *key,
|
||||
const struct rhashtable_params params)
|
||||
__must_hold_shared(RCU)
|
||||
{
|
||||
struct rhash_head *he = __rhashtable_lookup(&hlt->ht, key, params,
|
||||
RHT_LOOKUP_LIKELY);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ lib-$(CONFIG_MIN_HEAP) += min_heap.o
|
|||
lib-y += kobject.o klist.o
|
||||
obj-y += lockref.o
|
||||
|
||||
CONTEXT_ANALYSIS_rhashtable.o := y
|
||||
|
||||
obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \
|
||||
bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
|
||||
list_sort.o uuid.o iov_iter.o clz_ctz.o \
|
||||
|
|
|
|||
|
|
@ -358,6 +358,7 @@ static int rhashtable_rehash_table(struct rhashtable *ht)
|
|||
static int rhashtable_rehash_alloc(struct rhashtable *ht,
|
||||
struct bucket_table *old_tbl,
|
||||
unsigned int size)
|
||||
__must_hold(&ht->mutex)
|
||||
{
|
||||
struct bucket_table *new_tbl;
|
||||
int err;
|
||||
|
|
@ -392,6 +393,7 @@ static int rhashtable_rehash_alloc(struct rhashtable *ht,
|
|||
* bucket locks or concurrent RCU protected lookups and traversals.
|
||||
*/
|
||||
static int rhashtable_shrink(struct rhashtable *ht)
|
||||
__must_hold(&ht->mutex)
|
||||
{
|
||||
struct bucket_table *old_tbl = rht_dereference(ht->tbl, ht);
|
||||
unsigned int nelems = atomic_read(&ht->nelems);
|
||||
|
|
@ -724,7 +726,7 @@ EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
|
|||
* resize events and always continue.
|
||||
*/
|
||||
int rhashtable_walk_start_check(struct rhashtable_iter *iter)
|
||||
__acquires(RCU)
|
||||
__acquires_shared(RCU)
|
||||
{
|
||||
struct rhashtable *ht = iter->ht;
|
||||
bool rhlist = ht->rhlist;
|
||||
|
|
@ -940,7 +942,6 @@ EXPORT_SYMBOL_GPL(rhashtable_walk_peek);
|
|||
* hash table.
|
||||
*/
|
||||
void rhashtable_walk_stop(struct rhashtable_iter *iter)
|
||||
__releases(RCU)
|
||||
{
|
||||
struct rhashtable *ht;
|
||||
struct bucket_table *tbl = iter->walker.tbl;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue