svn commit: r186391 - head/sys/net
Qing Li
qingli at FreeBSD.org
Mon Dec 22 01:56:57 UTC 2008
Author: qingli
Date: Mon Dec 22 01:56:56 2008
New Revision: 186391
URL: http://svn.freebsd.org/changeset/base/186391
Log:
Provide a condition variable to delay the cloned interface
destroy operation until the referenced clone device has
been closed by the process properly. The behavior is now
consistently with the previous release.
Reviewed by: Kip Macy
Modified:
head/sys/net/if_tun.c
Modified: head/sys/net/if_tun.c
==============================================================================
--- head/sys/net/if_tun.c Mon Dec 22 00:53:47 2008 (r186390)
+++ head/sys/net/if_tun.c Mon Dec 22 01:56:56 2008 (r186391)
@@ -57,6 +57,7 @@
#include <net/if_tun.h>
#include <sys/queue.h>
+#include <sys/condvar.h>
#include <security/mac/mac_framework.h>
@@ -93,6 +94,7 @@ struct tun_softc {
struct sigio *tun_sigio; /* information for async I/O */
struct selinfo tun_rsel; /* read select */
struct mtx tun_mtx; /* protect mutable softc fields */
+ struct cv tun_cv; /* protect against ref'd dev destroy */
};
#define TUN2IFP(sc) ((sc)->tun_ifp)
@@ -253,8 +255,9 @@ tun_destroy(struct tun_softc *tp)
struct cdev *dev;
/* Unlocked read. */
- KASSERT((tp->tun_flags & TUN_OPEN) == 0,
- ("tununits is out of sync - unit %d", TUN2IFP(tp)->if_dunit));
+ mtx_lock(&tp->tun_mtx);
+ if ((tp->tun_flags & TUN_OPEN) != 0)
+ cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx);
CURVNET_SET(TUN2IFP(tp)->if_vnet);
dev = tp->tun_dev;
@@ -264,6 +267,7 @@ tun_destroy(struct tun_softc *tp)
destroy_dev(dev);
knlist_destroy(&tp->tun_rsel.si_note);
mtx_destroy(&tp->tun_mtx);
+ cv_destroy(&tp->tun_cv);
free(tp, M_TUN);
CURVNET_RESTORE();
}
@@ -365,6 +369,7 @@ tuncreate(const char *name, struct cdev
sc = malloc(sizeof(*sc), M_TUN, M_WAITOK | M_ZERO);
mtx_init(&sc->tun_mtx, "tun_mtx", NULL, MTX_DEF);
+ cv_init(&sc->tun_cv, "tun_condvar");
sc->tun_flags = TUN_INITED;
sc->tun_dev = dev;
mtx_lock(&tunmtx);
@@ -449,6 +454,7 @@ tunclose(struct cdev *dev, int foo, int
mtx_lock(&tp->tun_mtx);
tp->tun_flags &= ~TUN_OPEN;
tp->tun_pid = 0;
+ mtx_unlock(&tp->tun_mtx);
/*
* junk all pending output
@@ -457,7 +463,6 @@ tunclose(struct cdev *dev, int foo, int
s = splimp();
IFQ_PURGE(&ifp->if_snd);
splx(s);
- mtx_unlock(&tp->tun_mtx);
if (ifp->if_flags & IFF_UP) {
s = splimp();
@@ -486,10 +491,14 @@ tunclose(struct cdev *dev, int foo, int
if_link_state_change(ifp, LINK_STATE_DOWN);
CURVNET_RESTORE();
+ mtx_lock(&tp->tun_mtx);
funsetown(&tp->tun_sigio);
selwakeuppri(&tp->tun_rsel, PZERO + 1);
KNOTE_UNLOCKED(&tp->tun_rsel.si_note, 0);
TUNDEBUG (ifp, "closed\n");
+
+ cv_broadcast(&tp->tun_cv);
+ mtx_unlock(&tp->tun_mtx);
return (0);
}
More information about the svn-src-all
mailing list