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@.

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;

Reply via email to