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

Configure Feed

Select the types of activity you want to include in your feed.

neighbour: Add hlist_node to struct neighbour

Add a doubly-linked node to neighbours, so that they
can be deleted without iterating the entire bucket they're in.

Signed-off-by: Gilad Naaman <gnaaman@drivenets.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20241107160444.2913124-2-gnaaman@drivenets.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Gilad Naaman and committed by
Jakub Kicinski
41b3caa7 5e5be503

+21 -1
+2
include/net/neighbour.h
··· 136 136 137 137 struct neighbour { 138 138 struct neighbour __rcu *next; 139 + struct hlist_node hash; 139 140 struct neigh_table *tbl; 140 141 struct neigh_parms *parms; 141 142 unsigned long confirmed; ··· 192 191 193 192 struct neigh_hash_table { 194 193 struct neighbour __rcu **hash_buckets; 194 + struct hlist_head *hash_heads; 195 195 unsigned int hash_shift; 196 196 __u32 hash_rnd[NEIGH_NUM_HASH_RND]; 197 197 struct rcu_head rcu;
+19 -1
net/core/neighbour.c
··· 216 216 neigh = rcu_dereference_protected(n->next, 217 217 lockdep_is_held(&tbl->lock)); 218 218 rcu_assign_pointer(*np, neigh); 219 + hlist_del_rcu(&n->hash); 219 220 neigh_mark_dead(n); 220 221 retval = true; 221 222 } ··· 403 402 rcu_assign_pointer(*np, 404 403 rcu_dereference_protected(n->next, 405 404 lockdep_is_held(&tbl->lock))); 405 + hlist_del_rcu(&n->hash); 406 406 write_lock(&n->lock); 407 407 neigh_del_timer(n); 408 408 neigh_mark_dead(n); ··· 531 529 532 530 static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift) 533 531 { 532 + size_t hash_heads_size = (1 << shift) * sizeof(struct hlist_head); 534 533 size_t size = (1 << shift) * sizeof(struct neighbour *); 535 - struct neigh_hash_table *ret; 536 534 struct neighbour __rcu **buckets; 535 + struct hlist_head *hash_heads; 536 + struct neigh_hash_table *ret; 537 537 int i; 538 538 539 539 ret = kmalloc(sizeof(*ret), GFP_ATOMIC); 540 540 if (!ret) 541 541 return NULL; 542 + 542 543 buckets = kvzalloc(size, GFP_ATOMIC); 543 544 if (!buckets) { 544 545 kfree(ret); 545 546 return NULL; 546 547 } 548 + hash_heads = kvzalloc(hash_heads_size, GFP_ATOMIC); 549 + if (!hash_heads) { 550 + kvfree(buckets); 551 + kfree(ret); 552 + return NULL; 553 + } 547 554 ret->hash_buckets = buckets; 555 + ret->hash_heads = hash_heads; 548 556 ret->hash_shift = shift; 549 557 for (i = 0; i < NEIGH_NUM_HASH_RND; i++) 550 558 neigh_get_hash_rnd(&ret->hash_rnd[i]); ··· 568 556 rcu); 569 557 570 558 kvfree(nht->hash_buckets); 559 + kvfree(nht->hash_heads); 571 560 kfree(nht); 572 561 } 573 562 ··· 605 592 new_nht->hash_buckets[hash], 606 593 lockdep_is_held(&tbl->lock))); 607 594 rcu_assign_pointer(new_nht->hash_buckets[hash], n); 595 + hlist_del_rcu(&n->hash); 596 + hlist_add_head_rcu(&n->hash, &new_nht->hash_heads[hash]); 608 597 } 609 598 } 610 599 ··· 717 702 rcu_dereference_protected(nht->hash_buckets[hash_val], 718 703 lockdep_is_held(&tbl->lock))); 719 704 rcu_assign_pointer(nht->hash_buckets[hash_val], n); 705 + hlist_add_head_rcu(&n->hash, &nht->hash_heads[hash_val]); 720 706 write_unlock_bh(&tbl->lock); 721 707 neigh_dbg(2, "neigh %p is created\n", n); 722 708 rc = n; ··· 1003 987 rcu_assign_pointer(*np, 1004 988 rcu_dereference_protected(n->next, 1005 989 lockdep_is_held(&tbl->lock))); 990 + hlist_del_rcu(&n->hash); 1006 991 neigh_mark_dead(n); 1007 992 write_unlock(&n->lock); 1008 993 neigh_cleanup_and_release(n); ··· 3133 3116 rcu_assign_pointer(*np, 3134 3117 rcu_dereference_protected(n->next, 3135 3118 lockdep_is_held(&tbl->lock))); 3119 + hlist_del_rcu(&n->hash); 3136 3120 neigh_mark_dead(n); 3137 3121 } else 3138 3122 np = &n->next;