aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-10-11 09:16:57 -0700
committerDavid S. Miller <davem@davemloft.net>2010-10-11 09:16:57 -0700
commit34d101dd6204bd100fc2e6f7b5f9a10f959ce2c9 (patch)
tree77b714a4de7273ec53dac80396b94a2f896cfa95 /include
parentirda: Fix heap memory corruption in iriap.c (diff)
downloadlinux-dev-34d101dd6204bd100fc2e6f7b5f9a10f959ce2c9.tar.xz
linux-dev-34d101dd6204bd100fc2e6f7b5f9a10f959ce2c9.zip
neigh: speedup neigh_hh_init()
When a new dst is used to send a frame, neigh_resolve_output() tries to associate an struct hh_cache to this dst, calling neigh_hh_init() with the neigh rwlock write locked. Most of the time, hh_cache is already known and linked into neighbour, so we find it and increment its refcount. This patch changes the logic so that we call neigh_hh_init() with neighbour lock read locked only, so that fast path can be run in parallel by concurrent cpus. This brings part of the speedup we got with commit c7d4426a98a5f (introduce DST_NOCACHE flag) for non cached dsts, even for cached ones, removing one of the contention point that routers hit on multiqueue enabled machines. Further improvements would need to use a seqlock instead of an rwlock to protect neigh->ha[], to not dirty neigh too often and remove two atomic ops. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/netdevice.h6
1 files changed, 6 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6abcef67b178..4160db3721ba 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -281,6 +281,12 @@ struct hh_cache {
unsigned long hh_data[HH_DATA_ALIGN(LL_MAX_HEADER) / sizeof(long)];
};
+static inline void hh_cache_put(struct hh_cache *hh)
+{
+ if (atomic_dec_and_test(&hh->hh_refcnt))
+ kfree(hh);
+}
+
/* Reserve HH_DATA_MOD byte aligned hard_header_len, but at least that much.
* Alternative is:
* dev->hard_header_len ? (dev->hard_header_len +