this uses the refcnt api to do the heavy lifting.

i think we have all the if_get/if_put calls we need, so this should
be safe at this point.

if anyone wants to test, can you try detaching or destroying
interfaces and check that the ifconfig call that does it doesnt end
up blocking forever?

ok?

Index: if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.380
diff -u -p -r1.380 if.c
--- if.c        13 Sep 2015 18:15:03 -0000      1.380
+++ if.c        27 Sep 2015 05:49:11 -0000
@@ -279,11 +279,7 @@ if_idxmap_insert(struct ifnet *ifp)
        struct srp *map;
        unsigned int index, i;
 
-       /*
-        * give the ifp an initial refcnt of 1 to ensure it will not
-        * be freed until if_idxmap_remove returns.
-        */
-       ifp->if_refcnt = 1;
+       refcnt_init(&ifp->if_refcnt);
 
        /* the kernel lock guarantees serialised modifications to if_idxmap */
        KERNEL_ASSERT_LOCKED();
@@ -345,7 +341,7 @@ if_idxmap_remove(struct ifnet *ifp)
 {
        struct if_map *if_map;
        struct srp *map;
-       unsigned int index, r;
+       unsigned int index;
 
        index = ifp->if_index;
 
@@ -362,10 +358,8 @@ if_idxmap_remove(struct ifnet *ifp)
        if_idxmap.count--;
        /* end of if_idxmap modifications */
 
-       /* release the initial ifp refcnt */
-       r = atomic_dec_int_nv(&ifp->if_refcnt);
-       if (r != 0)
-               printf("%s: refcnt %u\n", ifp->if_xname, r);
+       /* sleep until the last reference is released */
+       refcnt_finalize(&ifp->if_refcnt, "ifidxrm");
 }
 
 void
@@ -1554,7 +1544,7 @@ if_get(unsigned int index)
 struct ifnet *
 if_ref(struct ifnet *ifp)
 {
-       atomic_inc_int(&ifp->if_refcnt);
+       refcnt_take(&ifp->if_refcnt);
 
        return (ifp);
 }
@@ -1565,7 +1555,7 @@ if_put(struct ifnet *ifp)
        if (ifp == NULL)
                return;
 
-       atomic_dec_int(&ifp->if_refcnt);
+       refcnt_rele_wake(&ifp->if_refcnt);
 }
 
 /*
Index: if_var.h
===================================================================
RCS file: /cvs/src/sys/net/if_var.h,v
retrieving revision 1.43
diff -u -p -r1.43 if_var.h
--- if_var.h    13 Sep 2015 17:53:44 -0000      1.43
+++ if_var.h    27 Sep 2015 05:49:11 -0000
@@ -39,6 +39,7 @@
 #include <sys/queue.h>
 #include <sys/mbuf.h>
 #include <sys/srp.h>
+#include <sys/refcnt.h>
 #ifdef _KERNEL
 #include <net/hfsc.h>
 #endif
@@ -119,7 +120,7 @@ TAILQ_HEAD(ifnet_head, ifnet);              /* the a
 
 struct ifnet {                         /* and the entries */
        void    *if_softc;              /* lower-level data for this if */
-       unsigned int if_refcnt;
+       struct  refcnt if_refcnt;
        TAILQ_ENTRY(ifnet) if_list;     /* all struct ifnets are chained */
        TAILQ_ENTRY(ifnet) if_txlist;   /* list of ifnets ready to tx */
        TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */

Reply via email to