if_tuntap: make SIOCIFDESTROY interruptible
There's no good justification to permanently hang a thread until the tunnel can be destroyed. Make it interruptible so that the admin can ^C it and remedy the situation if something erroneously has the tunnel open, rather than forcing them to open another shell to resolve it. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D39740
This commit is contained in:
+26
-14
@@ -615,19 +615,34 @@ tunclone(void *arg, struct ucred *cred, char *name, int namelen,
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
static void
|
||||
tun_destroy(struct tuntap_softc *tp)
|
||||
static int
|
||||
tun_destroy(struct tuntap_softc *tp, bool may_intr)
|
||||
{
|
||||
int error;
|
||||
|
||||
TUN_LOCK(tp);
|
||||
MPASS((tp->tun_flags & TUN_DYING) == 0);
|
||||
tp->tun_flags |= TUN_DYING;
|
||||
if (tp->tun_busy != 0)
|
||||
cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx);
|
||||
else
|
||||
TUN_UNLOCK(tp);
|
||||
error = 0;
|
||||
while (tp->tun_busy != 0) {
|
||||
if (may_intr)
|
||||
error = cv_wait_sig(&tp->tun_cv, &tp->tun_mtx);
|
||||
else
|
||||
cv_wait(&tp->tun_cv, &tp->tun_mtx);
|
||||
if (error != 0) {
|
||||
tp->tun_flags &= ~TUN_DYING;
|
||||
TUN_UNLOCK(tp);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
TUN_UNLOCK(tp);
|
||||
|
||||
CURVNET_SET(TUN2IFP(tp)->if_vnet);
|
||||
|
||||
mtx_lock(&tunmtx);
|
||||
TAILQ_REMOVE(&tunhead, tp, tun_list);
|
||||
mtx_unlock(&tunmtx);
|
||||
|
||||
/* destroy_dev will take care of any alias. */
|
||||
destroy_dev(tp->tun_dev);
|
||||
seldrain(&tp->tun_rsel);
|
||||
@@ -648,6 +663,8 @@ tun_destroy(struct tuntap_softc *tp)
|
||||
cv_destroy(&tp->tun_cv);
|
||||
free(tp, M_TUN);
|
||||
CURVNET_RESTORE();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -655,12 +672,7 @@ tun_clone_destroy(struct if_clone *ifc __unused, struct ifnet *ifp, uint32_t fla
|
||||
{
|
||||
struct tuntap_softc *tp = ifp->if_softc;
|
||||
|
||||
mtx_lock(&tunmtx);
|
||||
TAILQ_REMOVE(&tunhead, tp, tun_list);
|
||||
mtx_unlock(&tunmtx);
|
||||
tun_destroy(tp);
|
||||
|
||||
return (0);
|
||||
return (tun_destroy(tp, true));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -702,9 +714,9 @@ tun_uninit(const void *unused __unused)
|
||||
|
||||
mtx_lock(&tunmtx);
|
||||
while ((tp = TAILQ_FIRST(&tunhead)) != NULL) {
|
||||
TAILQ_REMOVE(&tunhead, tp, tun_list);
|
||||
mtx_unlock(&tunmtx);
|
||||
tun_destroy(tp);
|
||||
/* tun_destroy() will remove it from the tailq. */
|
||||
tun_destroy(tp, false);
|
||||
mtx_lock(&tunmtx);
|
||||
}
|
||||
mtx_unlock(&tunmtx);
|
||||
|
||||
Reference in New Issue
Block a user