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);