git: 274bf7c8ae7e - main - if_tuntap: make SIOCIFDESTROY interruptible

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Thu, 21 Aug 2025 14:22:47 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=274bf7c8ae7e7b51853cd541481985f0e687f10e

commit 274bf7c8ae7e7b51853cd541481985f0e687f10e
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2025-08-21 14:21:41 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2025-08-21 14:22:44 +0000

    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
---
 sys/net/if_tuntap.c | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/sys/net/if_tuntap.c b/sys/net/if_tuntap.c
index 5e6f65c04b2f..275581ea2d4e 100644
--- a/sys/net/if_tuntap.c
+++ b/sys/net/if_tuntap.c
@@ -615,19 +615,34 @@ out:
 	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);