Module Name: src
Committed By: yamaguchi
Date: Thu Apr 4 08:20:20 UTC 2024
Modified Files:
src/sys/net/lagg: if_lagg.c if_lagg_lacp.c
Log Message:
lagg(4): Remove unnecessary LAGG_LOCK holding while lagg_proto_detach()
to avoid deadlock in workqueue_wait due to LAGG_LOCK holding
lagg_proto_detach dose not need to hold LAGG_LOCK because only one
context can access to a detaching protocol after sc->sc_var is updated.
But it was held without any reason. And it had caused a deadlock by
holding LAGG_LOCK in caller of workqueue_wait
and waiting for the lock in worker.
To generate a diff of this commit:
cvs rdiff -u -r1.58 -r1.59 src/sys/net/lagg/if_lagg.c
cvs rdiff -u -r1.31 -r1.32 src/sys/net/lagg/if_lagg_lacp.c
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.58 src/sys/net/lagg/if_lagg.c:1.59
--- src/sys/net/lagg/if_lagg.c:1.58 Thu Apr 4 07:55:32 2024
+++ src/sys/net/lagg/if_lagg.c Thu Apr 4 08:20:20 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: if_lagg.c,v 1.58 2024/04/04 07:55:32 yamaguchi Exp $ */
+/* $NetBSD: if_lagg.c,v 1.59 2024/04/04 08:20:20 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.58 2024/04/04 07:55:32 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.59 2024/04/04 08:20:20 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -1649,11 +1649,9 @@ lagg_pr_attach(struct lagg_softc *sc, la
{
struct lagg_variant *newvar, *oldvar;
struct lagg_proto_softc *psc;
- bool cleanup_oldvar;
int error;
error = 0;
- cleanup_oldvar = false;
newvar = kmem_alloc(sizeof(*newvar), KM_SLEEP);
LAGG_LOCK(sc);
@@ -1661,32 +1659,28 @@ lagg_pr_attach(struct lagg_softc *sc, la
if (oldvar != NULL && oldvar->lv_proto == pr) {
error = 0;
- goto done;
+ goto failed;
}
error = lagg_proto_attach(sc, pr, &psc);
if (error != 0)
- goto done;
+ goto failed;
newvar->lv_proto = pr;
newvar->lv_psc = psc;
-
lagg_variant_update(sc, newvar);
- newvar = NULL;
+ lagg_set_linkspeed(sc, 0);
+ LAGG_UNLOCK(sc);
if (oldvar != NULL) {
lagg_proto_detach(oldvar);
- cleanup_oldvar = true;
+ kmem_free(oldvar, sizeof(*oldvar));
}
- lagg_set_linkspeed(sc, 0);
-done:
- LAGG_UNLOCK(sc);
+ return 0;
- if (newvar != NULL)
- kmem_free(newvar, sizeof(*newvar));
- if (cleanup_oldvar)
- kmem_free(oldvar, sizeof(*oldvar));
+failed:
+ kmem_free(newvar, sizeof(*newvar));
return error;
}
@@ -1697,15 +1691,14 @@ lagg_pr_detach(struct lagg_softc *sc)
struct lagg_variant *var;
LAGG_LOCK(sc);
-
var = sc->sc_var;
atomic_store_release(&sc->sc_var, NULL);
pserialize_perform(sc->sc_psz);
+ LAGG_UNLOCK(sc);
if (var != NULL)
lagg_proto_detach(var);
- LAGG_UNLOCK(sc);
if (var != NULL)
kmem_free(var, sizeof(*var));
Index: src/sys/net/lagg/if_lagg_lacp.c
diff -u src/sys/net/lagg/if_lagg_lacp.c:1.31 src/sys/net/lagg/if_lagg_lacp.c:1.32
--- src/sys/net/lagg/if_lagg_lacp.c:1.31 Thu Apr 4 07:45:57 2024
+++ src/sys/net/lagg/if_lagg_lacp.c Thu Apr 4 08:20:20 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: if_lagg_lacp.c,v 1.31 2024/04/04 07:45:57 yamaguchi Exp $ */
+/* $NetBSD: if_lagg_lacp.c,v 1.32 2024/04/04 08:20:20 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.31 2024/04/04 07:45:57 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.32 2024/04/04 08:20:20 yamaguchi Exp $");
#ifdef _KERNEL_OPT
#include "opt_lagg.h"
@@ -536,11 +536,12 @@ lacp_detach(struct lagg_proto_softc *xls
struct lacp_softc *lsc = (struct lacp_softc *)xlsc;
struct lagg_softc *sc __diagused = lsc->lsc_softc;
- KASSERT(LAGG_LOCKED(lsc->lsc_softc));
KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators));
KASSERT(SIMPLEQ_EMPTY(&sc->sc_ports));
+ LAGG_LOCK(lsc->lsc_softc);
lacp_down(xlsc);
+ LAGG_UNLOCK(lsc->lsc_softc);
lagg_workq_wait(lsc->lsc_workq, &lsc->lsc_work_rcvdu);
evcnt_detach(&lsc->lsc_mgethdr_failed);