mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 18:51:56 -04:00
rhashtable: Per bucket locks & deferred expansion/shrinking
Introduces an array of spinlocks to protect bucket mutations. The number of spinlocks per CPU is configurable and selected based on the hash of the bucket. This allows for parallel insertions and removals of entries which do not share a lock. The patch also defers expansion and shrinking to a worker queue which allows insertion and removal from atomic context. Insertions and deletions may occur in parallel to it and are only held up briefly while the particular bucket is linked or unzipped. Mutations of the bucket table pointer is protected by a new mutex, read access is RCU protected. In the event of an expansion or shrinking, the new bucket table allocated is exposed as a so called future table as soon as the resize process starts. Lookups, deletions, and insertions will briefly use both tables. The future table becomes the main table after an RCU grace period and initial linking of the old to the new table was performed. Optimization of the chains to make use of the new number of buckets follows only the new table is in use. The side effect of this is that during that RCU grace period, a bucket traversal using any rht_for_each() variant on the main table will not see any insertions performed during the RCU grace period which would at that point land in the future table. The lookup will see them as it searches both tables if needed. Having multiple insertions and removals occur in parallel requires nelems to become an atomic counter. Signed-off-by: Thomas Graf <[email protected]> Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
parent
113948d841
commit
97defe1ecf
4 changed files with 384 additions and 153 deletions
|
|
@ -114,15 +114,6 @@ static atomic_t nl_table_users = ATOMIC_INIT(0);
|
|||
DEFINE_MUTEX(nl_sk_hash_lock);
|
||||
EXPORT_SYMBOL_GPL(nl_sk_hash_lock);
|
||||
|
||||
#ifdef CONFIG_PROVE_LOCKING
|
||||
static int lockdep_nl_sk_hash_is_held(void *parent)
|
||||
{
|
||||
if (debug_locks)
|
||||
return lockdep_is_held(&nl_sk_hash_lock) || lockdep_is_held(&nl_table_lock);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ATOMIC_NOTIFIER_HEAD(netlink_chain);
|
||||
|
||||
static DEFINE_SPINLOCK(netlink_tap_lock);
|
||||
|
|
@ -1063,7 +1054,8 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
|
|||
goto err;
|
||||
|
||||
err = -ENOMEM;
|
||||
if (BITS_PER_LONG > 32 && unlikely(table->hash.nelems >= UINT_MAX))
|
||||
if (BITS_PER_LONG > 32 &&
|
||||
unlikely(atomic_read(&table->hash.nelems) >= UINT_MAX))
|
||||
goto err;
|
||||
|
||||
nlk_sk(sk)->portid = portid;
|
||||
|
|
@ -3122,9 +3114,6 @@ static int __init netlink_proto_init(void)
|
|||
.max_shift = 16, /* 64K */
|
||||
.grow_decision = rht_grow_above_75,
|
||||
.shrink_decision = rht_shrink_below_30,
|
||||
#ifdef CONFIG_PROVE_LOCKING
|
||||
.mutex_is_held = lockdep_nl_sk_hash_is_held,
|
||||
#endif
|
||||
};
|
||||
|
||||
if (err != 0)
|
||||
|
|
|
|||
Loading…
Reference in a new issue