Re: neighbour table RCU
From: Octavian Purdila <hidden>
Date: 2009-09-01 15:57:53
On Tuesday 01 September 2009 09:50:17 Eric Dumazet wrote:
Stephen Hemminger a écrit :quoted
Looking at the neighbour table, it should be possible to get rid of the two reader/writer locks. The hash table lock is pretty amenable to RCU, but the dynamic resizing makes it non-trivial. Thinking of using a combination of RCU and sequence counts so that the reader would just rescan if resize was in progress.I am not sure neigh_tbl_lock rwlock should be changed, I did not see any contention on it.
Speaking about neighbour optimizations, here is a RFC patch which makes the tables double linked, for constant time deletion. It has given us a significant performance improvement - in less then usual setups though, with lots of neighbours. Would something like this be acceptable for upstream? (pardon the p4 diff dump :) - but I think it will give a rough idea, if acceptable will clean it up and properly submit it) BTW, would switching to list_head be better? Thanks, tavi ==== //packages/linux-2.6.7/main/src/include/net/neighbour.h#2 (text) ====
@@ -56,6 +56,7 @@ struct neigh_parms { struct neigh_parms *next; + struct neigh_parms **pprev; int (*neigh_setup)(struct neighbour *); struct neigh_table *tbl; int entries;
==== //packages/linux-2.6.7/main/src/net/core/neighbour.c#3 (text) ====
@@ -1127,8 +1127,10 @@ } p->sysctl_table = NULL; write_lock_bh(&tbl->lock); - p->next = tbl->parms.next; + if ((p->next = tbl->parms.next)) + p->next->pprev = &p->next; tbl->parms.next = p; + p->pprev = &tbl->parms.next; write_unlock_bh(&tbl->lock); } return p;
@@ -1136,21 +1138,14 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms) { - struct neigh_parms **p; - if (!parms || parms == &tbl->parms) return; write_lock_bh(&tbl->lock); - for (p = &tbl->parms.next; *p; p = &(*p)->next) { - if (*p == parms) { - *p = parms->next; - write_unlock_bh(&tbl->lock); - kfree(parms); - return; - } - } + if ((*parms->pprev = parms->next)) + parms->next->pprev = parms->pprev; write_unlock_bh(&tbl->lock); - NEIGH_PRINTK1("neigh_parms_release: not found\n"); + kfree(parms); + return; }