On Thu, Oct 22, 2015 at 07:42:24PM +0200, 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?
One comment inline...
>
> Index: sys/net/route.c
> ===================================================================
> RCS file: /cvs/src/sys/net/route.c,v
> retrieving revision 1.258
> diff -u -p -r1.258 route.c
> --- sys/net/route.c 22 Oct 2015 17:19:38 -0000 1.258
> +++ sys/net/route.c 22 Oct 2015 17:21:52 -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,7 +339,7 @@ rtalloc_mpath(struct sockaddr *dst, uint
> void
> rtref(struct rtentry *rt)
> {
> - rt->rt_refcnt++;
> + atomic_inc_int(&rt->rt_refcnt);
> }
>
> void
> @@ -348,14 +350,16 @@ rtfree(struct rtentry *rt)
> if (rt == NULL)
> return;
>
> - if (--rt->rt_refcnt <= 0) {
> + if (atomic_dec_int_nv(&rt->rt_refcnt) <= 0) {
> KASSERT(!ISSET(rt->rt_flags, RTF_UP));
> KASSERT(!RT_ROOT(rt));
> - rttrash--;
> + atomic_dec_int(&rttrash);
Are you using rttrash for debugging? It's unused anywhere else,
and if it's just incrementing and decrementing a counter only
used for debugging (or possibly not at all!), it might be
better to put it in DEBUG kernels, or just remove it entirely.
> if (rt->rt_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 +372,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 +779,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;
> Index: sys/netmpls/mpls_input.c
> ===================================================================
> RCS file: /cvs/src/sys/netmpls/mpls_input.c,v
> retrieving revision 1.50
> diff -u -p -r1.50 mpls_input.c
> --- sys/netmpls/mpls_input.c 23 Sep 2015 08:49:46 -0000 1.50
> +++ sys/netmpls/mpls_input.c 22 Oct 2015 17:21:52 -0000
> @@ -170,9 +170,7 @@ do_v6:
> }
> }
>
> - KERNEL_LOCK();
> rt = rtalloc(smplstosa(smpls), RT_REPORT|RT_RESOLVE, 0);
> - KERNEL_UNLOCK();
> if (rt == NULL) {
> /* no entry for this label */
> #ifdef MPLS_DEBUG
> @@ -290,9 +288,7 @@ do_v6:
> if (ifp != NULL && rt_mpls->mpls_operation != MPLS_OP_LOCAL)
> break;
>
> - KERNEL_LOCK();
> rtfree(rt);
> - KERNEL_UNLOCK();
> rt = NULL;
> }
>
> @@ -323,11 +319,7 @@ do_v6:
> (*ifp->if_ll_output)(ifp, m, smplstosa(smpls), rt);
> KERNEL_UNLOCK();
> done:
> - if (rt) {
> - KERNEL_LOCK();
> - rtfree(rt);
> - KERNEL_UNLOCK();
> - }
> + rtfree(rt);
> }
>
> int
> @@ -394,7 +386,7 @@ mpls_do_error(struct mbuf *m, int type,
> struct in_ifaddr *ia;
> struct icmp *icp;
> struct ip *ip;
> - int nstk;
> + int nstk, error;
>
> for (nstk = 0; nstk < MPLS_INKERNEL_LOOP_MAX; nstk++) {
> if (m->m_len < sizeof(*shim) &&
> @@ -427,9 +419,7 @@ mpls_do_error(struct mbuf *m, int type,
> smpls->smpls_len = sizeof(*smpls);
> smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK;
>
> - KERNEL_LOCK();
> rt = rtalloc(smplstosa(smpls), RT_REPORT|RT_RESOLVE, 0);
> - KERNEL_UNLOCK();
> if (rt == NULL) {
> /* no entry for this label */
> m_freem(m);
> @@ -442,19 +432,16 @@ mpls_do_error(struct mbuf *m, int type,
> * less interface we need to find some other IP to
> * use as source.
> */
> - KERNEL_LOCK();
> rtfree(rt);
> - KERNEL_UNLOCK();
> m_freem(m);
> return (NULL);
> }
> - KERNEL_LOCK();
> rtfree(rt);
> - if (icmp_reflect(m, NULL, ia)) {
> - KERNEL_UNLOCK();
> - return (NULL);
> - }
> + KERNEL_LOCK();
> + error = icmp_reflect(m, NULL, ia);
> KERNEL_UNLOCK();
> + if (error)
> + return (NULL);
>
> ip = mtod(m, struct ip *);
> /* stuff to fix up which is normaly done in ip_output */
>