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 <r...@openbsd.org>
@@ -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);

Reply via email to