git: c182cf646a4f - main - lagg: Avoid dropping locks when starting the interface
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 11 Feb 2026 18:17:17 UTC
The branch main has been updated by zlei:
URL: https://cgit.FreeBSD.org/src/commit/?id=c182cf646a4f995fa8506afd8afc9541c4d32905
commit c182cf646a4f995fa8506afd8afc9541c4d32905
Author: Zhenlei Huang <zlei@FreeBSD.org>
AuthorDate: 2026-02-11 18:15:41 +0000
Commit: Zhenlei Huang <zlei@FreeBSD.org>
CommitDate: 2026-02-11 18:15:41 +0000
lagg: Avoid dropping locks when starting the interface
The init routine of a lagg(4) interface will not change during the whole
lifecycle. So we can call lagg_init() directly instead of through the
function pointer. Well, that requires a drop and pickup lock, which
unnecessarily expose a small race window. Refactor lagg_init() into
lagg_init_locked() and call the later one to avoid that.
Meanwhile, delay updating the driver managed status until after the
interface is really ready.
Reviewed by: markj
MFC after: 5 days
Differential Revision: https://reviews.freebsd.org/D55198
---
sys/net/if_lagg.c | 36 +++++++++++++++++++-----------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 7a8f82286c02..0333162da0d4 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -139,6 +139,7 @@ static int lagg_port_checkstacking(struct lagg_softc *);
static void lagg_port2req(struct lagg_port *, struct lagg_reqport *);
static void lagg_if_updown(struct lagg_softc *, bool);
static void lagg_init(void *);
+static void lagg_init_locked(struct lagg_softc *);
static void lagg_stop(struct lagg_softc *);
static int lagg_ioctl(struct ifnet *, u_long, caddr_t);
#if defined(KERN_TLS) || defined(RATELIMIT)
@@ -1279,16 +1280,21 @@ static void
lagg_init(void *xsc)
{
struct lagg_softc *sc = (struct lagg_softc *)xsc;
+
+ LAGG_XLOCK(sc);
+ lagg_init_locked(sc);
+ LAGG_XUNLOCK(sc);
+}
+
+static void
+lagg_init_locked(struct lagg_softc *sc)
+{
struct ifnet *ifp = sc->sc_ifp;
struct lagg_port *lp;
- LAGG_XLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- LAGG_XUNLOCK(sc);
+ LAGG_XLOCK_ASSERT(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
return;
- }
-
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
/*
* Update the port lladdrs if needed.
@@ -1310,8 +1316,7 @@ lagg_init(void *xsc)
lagg_watchdog_infiniband(sc);
mtx_unlock(&sc->sc_mtx);
}
-
- LAGG_XUNLOCK(sc);
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
}
static void
@@ -1674,24 +1679,21 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
lagg_setflags(lp, 1);
}
- if (!(ifp->if_flags & IFF_UP) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if ((ifp->if_flags & IFF_UP) == 0 &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
/*
* If interface is marked down and it is running,
* then stop and disable it.
*/
lagg_stop(sc);
- LAGG_XUNLOCK(sc);
- } else if ((ifp->if_flags & IFF_UP) &&
- !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ else if ((ifp->if_flags & IFF_UP) != 0 &&
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
/*
* If interface is marked up and it is stopped, then
* start it.
*/
- LAGG_XUNLOCK(sc);
- (*ifp->if_init)(sc);
- } else
- LAGG_XUNLOCK(sc);
+ lagg_init_locked(sc);
+ LAGG_XUNLOCK(sc);
break;
case SIOCADDMULTI:
case SIOCDELMULTI: