summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2015-09-30 11:33:52 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2015-09-30 11:33:52 +0000
commitded5ecd296e14ad5fdbd36dcd07f55568e05bb34 (patch)
tree9310339668cadc2803e67e4524ebfae62f4f436e
parent2ad11d0c31f71936373640703c1f19c7316d8911 (diff)
sleep until all references to an interface have been released during detach.
this is done by moving to the refcnt api and using refcnt_finalize. tested by Hrjove Popovski ok mpi@
-rw-r--r--sys/net/if.c20
-rw-r--r--sys/net/if_var.h5
2 files changed, 10 insertions, 15 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index d5460277f67..e6a48ddbc68 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.381 2015/09/27 16:50:03 stsp Exp $ */
+/* $OpenBSD: if.c,v 1.382 2015/09/30 11:33:51 dlg Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -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 +1548,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 +1559,7 @@ if_put(struct ifnet *ifp)
if (ifp == NULL)
return;
- atomic_dec_int(&ifp->if_refcnt);
+ refcnt_rele_wake(&ifp->if_refcnt);
}
int
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 3e921c3f7e7..2df9825013e 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_var.h,v 1.45 2015/09/28 08:24:53 mpi Exp $ */
+/* $OpenBSD: if_var.h,v 1.46 2015/09/30 11:33:51 dlg Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -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 actual queue head */
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 */