Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet Stop callout in arp_rtrequest(RTM_DELETE)



details:   https://anonhg.NetBSD.org/src/rev/7d1c57b933ff
branches:  trunk
changeset: 341138:7d1c57b933ff
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Tue Oct 20 07:46:59 2015 +0000

description:
Stop callout in arp_rtrequest(RTM_DELETE)

This change fixes arptimer panic after removing an interface
(say by drvctl -d), which is reported by Takahiro Hayashi.

This change also fixes llentry's reference counting; we have
to take into account rtentry#rt_llinfo as well as arptimer.

diffstat:

 sys/netinet/if_arp.c |  30 +++++++++++++++++++-----------
 1 files changed, 19 insertions(+), 11 deletions(-)

diffs (71 lines):

diff -r fe82fd8ce2b6 -r 7d1c57b933ff sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c      Tue Oct 20 07:35:15 2015 +0000
+++ b/sys/netinet/if_arp.c      Tue Oct 20 07:46:59 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_arp.c,v 1.190 2015/10/20 07:35:15 ozaki-r Exp $     */
+/*     $NetBSD: if_arp.c,v 1.191 2015/10/20 07:46:59 ozaki-r Exp $     */
 
 /*-
  * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.190 2015/10/20 07:35:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.191 2015/10/20 07:46:59 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -635,6 +635,7 @@
                        break;
                }
                rt->rt_llinfo = la;
+               LLE_ADDREF(la);
                switch (ifp->if_type) {
 #if NTOKEN > 0
                case IFT_ISO88025:
@@ -662,17 +663,14 @@
                rt->rt_llinfo = NULL;
                rt->rt_flags &= ~RTF_LLINFO;
 
+               /* Have to do before IF_AFDATA_WLOCK to avoid deadlock */
+               callout_halt(&la->la_timer, &la->lle_lock);
+               /* XXX: LOR avoidance. We still have ref on lle. */
                LLE_RUNLOCK(la);
 
                flags |= LLE_EXCLUSIVE;
                IF_AFDATA_WLOCK(ifp);
-
-               la = lla_lookup(LLTABLE(ifp), flags, rt_getkey(rt));
-               /* This shouldn't happen */
-               if (la == NULL) {
-                       IF_AFDATA_WUNLOCK(ifp);
-                       break;
-               }
+               LLE_WLOCK(la);
 
                if (la->la_opaque != NULL) {
                        switch (ifp->if_type) {
@@ -695,10 +693,20 @@
                        la->la_rt->rt_refcnt--;
                        la->la_rt = NULL;
                }
-               llentry_free(la);
+
+               /* Guard against race with other llentry_free(). */
+               if (la->la_flags & LLE_LINKED) {
+                       size_t pkts_dropped;
+
+                       LLE_REMREF(la);
+                       pkts_dropped = llentry_free(la);
+                       ARP_STATADD(ARP_STAT_DFRDROPPED, pkts_dropped);
+               } else {
+                       LLE_FREE_LOCKED(la);
+               }
+               la = NULL;
 
                IF_AFDATA_WUNLOCK(ifp);
-               la = NULL;
        }
 
        if (la != NULL) {



Home | Main Index | Thread Index | Old Index