diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2015-09-30 11:33:52 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2015-09-30 11:33:52 +0000 |
commit | ded5ecd296e14ad5fdbd36dcd07f55568e05bb34 (patch) | |
tree | 9310339668cadc2803e67e4524ebfae62f4f436e | |
parent | 2ad11d0c31f71936373640703c1f19c7316d8911 (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.c | 20 | ||||
-rw-r--r-- | sys/net/if_var.h | 5 |
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 */ |