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 <[email protected]>
@@ -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