Module Name: src Committed By: yamaguchi Date: Wed Jan 12 08:23:53 UTC 2022
Modified Files: src/sys/net/lagg: if_lagg.c if_lagg_lacp.c if_laggproto.h Log Message: Fix to call lacp_linkstate with IFNET_LOCK held Network stack calls lacp_linkstate through lagg_port_ioctl when doing "ifconfig up" or "ifconfig down" to an interface that is a member of lagg(4). And IFNET_LOCK in the member interface is held while the ioctl. Therefore, lacp_linkstate is renamed to lacp_linkstate_ifnet_locked, and always called with IFNET_LOCK held. It avoids locking agains myself. To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 src/sys/net/lagg/if_lagg.c cvs rdiff -u -r1.11 -r1.12 src/sys/net/lagg/if_lagg_lacp.c cvs rdiff -u -r1.9 -r1.10 src/sys/net/lagg/if_laggproto.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/lagg/if_lagg.c diff -u src/sys/net/lagg/if_lagg.c:1.29 src/sys/net/lagg/if_lagg.c:1.30 --- src/sys/net/lagg/if_lagg.c:1.29 Wed Jan 12 01:21:36 2022 +++ src/sys/net/lagg/if_lagg.c Wed Jan 12 08:23:53 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg.c,v 1.29 2022/01/12 01:21:36 riastradh Exp $ */ +/* $NetBSD: if_lagg.c,v 1.30 2022/01/12 08:23:53 yamaguchi Exp $ */ /* * Copyright (c) 2005, 2006 Reyk Floeter <r...@openbsd.org> @@ -20,7 +20,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.29 2022/01/12 01:21:36 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.30 2022/01/12 08:23:53 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -102,7 +102,7 @@ static const struct lagg_proto lagg_prot .pr_stopport = lacp_stopport, .pr_protostat = lacp_protostat, .pr_portstat = lacp_portstat, - .pr_linkstate = lacp_linkstate, + .pr_linkstate = lacp_linkstate_ifnet_locked, .pr_ioctl = lacp_ioctl, }, [LAGG_PROTO_FAILOVER] = { @@ -1490,6 +1490,8 @@ lagg_proto_linkstate(struct lagg_softc * lagg_proto pr; int bound; + KASSERT(IFNET_LOCKED(lp->lp_ifp)); + bound = curlwp_bind(); var = lagg_variant_getref(sc, &psref); @@ -2692,6 +2694,8 @@ lagg_port_ioctl(struct ifnet *ifp, u_lon goto fallback; } + KASSERT(IFNET_LOCKED(lp->lp_ifp)); + switch (cmd) { case SIOCSIFCAP: case SIOCSIFMTU: @@ -2817,7 +2821,10 @@ lagg_linkstate_changed(void *xifp) } pserialize_read_exit(s); + IFNET_LOCK(lp->lp_ifp); lagg_proto_linkstate(lp->lp_softc, lp); + IFNET_UNLOCK(lp->lp_ifp); + lagg_port_putref(lp, &psref); curlwp_bindx(bound); } Index: src/sys/net/lagg/if_lagg_lacp.c diff -u src/sys/net/lagg/if_lagg_lacp.c:1.11 src/sys/net/lagg/if_lagg_lacp.c:1.12 --- src/sys/net/lagg/if_lagg_lacp.c:1.11 Thu Jan 6 12:09:42 2022 +++ src/sys/net/lagg/if_lagg_lacp.c Wed Jan 12 08:23:53 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg_lacp.c,v 1.11 2022/01/06 12:09:42 riastradh Exp $ */ +/* $NetBSD: if_lagg_lacp.c,v 1.12 2022/01/12 08:23:53 yamaguchi Exp $ */ /*- * SPDX-License-Identifier: BSD-2-Clause-NetBSD @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.11 2022/01/06 12:09:42 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.12 2022/01/12 08:23:53 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_lagg.h" @@ -212,8 +212,6 @@ static void lacp_dprintf(const struct la #define LACP_LOCK(_sc) mutex_enter(&(_sc)->lsc_lock) #define LACP_UNLOCK(_sc) mutex_exit(&(_sc)->lsc_lock) #define LACP_LOCKED(_sc) mutex_owned(&(_sc)->lsc_lock) -#define LACP_LINKSTATE(_sc, _lp) \ - lacp_linkstate((struct lagg_proto_softc *)(_sc), (_lp)) #define LACP_TIMER_ARM(_lacpp, _timer, _val) \ (_lacpp)->lp_timer[(_timer)] = (_val) #define LACP_TIMER_DISARM(_lacpp, _timer) \ @@ -242,6 +240,7 @@ static void lacp_dprintf(const struct la static void lacp_tick(void *); static void lacp_tick_work(struct lagg_work *, void *); +static void lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *); static uint32_t lacp_ifmedia2lacpmedia(u_int); static void lacp_port_disable(struct lacp_softc *, struct lacp_port *); static void lacp_port_enable(struct lacp_softc *, struct lacp_port *); @@ -673,7 +672,7 @@ lacp_allocport(struct lagg_proto_softc * lp->lp_proto_ctx = (void *)lacpp; lp->lp_prio = ntohs(lacpp->lp_actor.lpi_portprio); - LACP_LINKSTATE(lsc, lp); + lacp_linkstate(xlsc, lp); return 0; } @@ -689,7 +688,7 @@ lacp_startport(struct lagg_proto_softc * prio = (uint16_t)MIN(lp->lp_prio, UINT16_MAX); lacpp->lp_actor.lpi_portprio = htons(prio); - LACP_LINKSTATE((struct lacp_softc *)xlsc, lp); + lacp_linkstate(xlsc, lp); } void @@ -821,7 +820,7 @@ lacp_portstat(struct lagg_proto_softc *x } void -lacp_linkstate(struct lagg_proto_softc *xlsc, struct lagg_port *lp) +lacp_linkstate_ifnet_locked(struct lagg_proto_softc *xlsc, struct lagg_port *lp) { struct lacp_softc *lsc; struct lacp_port *lacpp; @@ -831,6 +830,8 @@ lacp_linkstate(struct lagg_proto_softc * uint32_t media, old_media; int error; + KASSERT(IFNET_LOCKED(lp->lp_ifp)); + lsc = (struct lacp_softc *)xlsc; ifp_port = lp->lp_ifp; @@ -839,9 +840,7 @@ lacp_linkstate(struct lagg_proto_softc * memset(&ifmr, 0, sizeof(ifmr)); ifmr.ifm_count = 0; - IFNET_LOCK(ifp_port); error = if_ioctl(ifp_port, SIOCGIFMEDIA, (void *)&ifmr); - IFNET_UNLOCK(ifp_port); if (error == 0) { media = lacp_ifmedia2lacpmedia(ifmr.ifm_active); } else if (error != ENOTTY){ @@ -2644,3 +2643,14 @@ lacp_ifmedia2lacpmedia(u_int ifmedia) return rv; } + +static void +lacp_linkstate(struct lagg_proto_softc *xlsc, struct lagg_port *lp) +{ + + IFNET_ASSERT_UNLOCKED(lp->lp_ifp); + + IFNET_LOCK(lp->lp_ifp); + lacp_linkstate_ifnet_locked(xlsc, lp); + IFNET_UNLOCK(lp->lp_ifp); +} Index: src/sys/net/lagg/if_laggproto.h diff -u src/sys/net/lagg/if_laggproto.h:1.9 src/sys/net/lagg/if_laggproto.h:1.10 --- src/sys/net/lagg/if_laggproto.h:1.9 Tue Oct 19 07:52:33 2021 +++ src/sys/net/lagg/if_laggproto.h Wed Jan 12 08:23:53 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: if_laggproto.h,v 1.9 2021/10/19 07:52:33 yamaguchi Exp $ */ +/* $NetBSD: if_laggproto.h,v 1.10 2022/01/12 08:23:53 yamaguchi Exp $ */ /* * Copyright (c) 2021 Internet Initiative Japan Inc. @@ -199,8 +199,8 @@ struct lagg_softc { * - IFNET_LOCK(sc_if) -> LAGG_LOCK -> ETHER_LOCK(sc_if) -> a lock in * struct lagg_port_softc * - IFNET_LOCK(sc_if) -> LAGG_LOCK -> IFNET_LOCK(lp_ifp) + * - IFNET_LOCK(lp_ifp) -> a lock in struct lagg_proto_softc * - Currently, there is no combination of following locks - * - IFNET_LOCK(lp_ifp) and a lock in struct lagg_proto_softc * - IFNET_LOCK(lp_ifp) and ETHER_LOCK(sc_if) */ #define LAGG_LOCK(_sc) mutex_enter(&(_sc)->sc_lock) @@ -320,6 +320,6 @@ void lacp_protostat(struct lagg_proto_s struct laggreqproto *); void lacp_portstat(struct lagg_proto_softc *, struct lagg_port *, struct laggreqport *); -void lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *); +void lacp_linkstate_ifnet_locked(struct lagg_proto_softc *, struct lagg_port *); int lacp_ioctl(struct lagg_proto_softc *, struct laggreqproto *); #endif