The branch main has been updated by kevans:

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

commit 274bf7c8ae7e7b51853cd541481985f0e687f10e
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2025-08-21 14:21:41 +0000
Commit:     Kyle Evans <kev...@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);

Reply via email to