On Fri, Oct 23, 2015 at 02:41:34PM +0200, Martin Pieuchot wrote: > On 22/10/15(Thu) 19:42, Martin Pieuchot wrote: > > Now that we have a single refcounting mechanism for route entries, I'd > > like to use atomic operations and grab the KERNEL_LOCK only if a CPU is > > dropping the last reference on an entry. > > > > Currently this only matters for MPLS. I intentionally use atomic_* ops > > because I'd like to see be able to see if a counter goes negative. > > > > For symmetry reasons I'm also moving the KERNEL_LOCK() inside rtalloc(). > > These two functions are my current targets. > > > > Comments, oks? > > Updated diff after some comments from dlg@ and bluhm@.
OK bluhm@ > > Index: net/route.c > =================================================================== > RCS file: /cvs/src/sys/net/route.c,v > retrieving revision 1.258 > diff -u -p -r1.258 route.c > --- net/route.c 22 Oct 2015 17:19:38 -0000 1.258 > +++ net/route.c 23 Oct 2015 12:38:58 -0000 > @@ -215,6 +215,7 @@ rtalloc(struct sockaddr *dst, int flags, > info.rti_info[RTAX_DST] = dst; > > s = splsoftnet(); > + KERNEL_LOCK(); > rt = rtable_match(tableid, dst); > if (rt != NULL) { > if ((rt->rt_flags & RTF_CLONING) && ISSET(flags, RT_RESOLVE)) { > @@ -236,6 +237,7 @@ miss: > if (ISSET(flags, RT_REPORT)) > rt_missmsg(RTM_MISS, &info, 0, NULL, error, tableid); > } > + KERNEL_UNLOCK(); > splx(s); > return (rt); > } > @@ -337,25 +339,29 @@ rtalloc_mpath(struct sockaddr *dst, uint > void > rtref(struct rtentry *rt) > { > - rt->rt_refcnt++; > + atomic_inc_int(&rt->rt_refcnt); > } > > void > rtfree(struct rtentry *rt) > { > struct ifaddr *ifa; > + int refcnt; > > if (rt == NULL) > return; > > - if (--rt->rt_refcnt <= 0) { > + refcnt = (int)atomic_dec_int_nv(&rt->rt_refcnt); > + if (refcnt <= 0) { > KASSERT(!ISSET(rt->rt_flags, RTF_UP)); > KASSERT(!RT_ROOT(rt)); > - rttrash--; > - if (rt->rt_refcnt < 0) { > + atomic_dec_int(&rttrash); > + if (refcnt < 0) { > printf("rtfree: %p not freed (neg refs)\n", rt); > return; > } > + > + KERNEL_LOCK(); > rt_timer_remove_all(rt); > ifa = rt->rt_ifa; > if (ifa) > @@ -368,6 +374,8 @@ rtfree(struct rtentry *rt) > if (rt->rt_gateway) > free(rt->rt_gateway, M_RTABLE, 0); > free(rt_key(rt), M_RTABLE, 0); > + KERNEL_UNLOCK(); > + > pool_put(&rtentry_pool, rt); > } > } > @@ -773,7 +781,7 @@ rtrequest1(int req, struct rt_addrinfo * > rt->rt_flags &= ~RTF_UP; > if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) > ifa->ifa_rtrequest(RTM_DELETE, rt); > - rttrash++; > + atomic_inc_int(&rttrash); > > if (ret_nrt != NULL) > *ret_nrt = rt;