Index: head/sys/net/if_lagg.c =================================================================== --- head/sys/net/if_lagg.c +++ head/sys/net/if_lagg.c @@ -751,7 +751,6 @@ * is predictable and `ifconfig laggN create ...` command * will lead to the same result each time. */ - LAGG_RLOCK(); CK_SLIST_FOREACH(tlp, &sc->sc_ports, lp_entries) { if (tlp->lp_ifp->if_index < ifp->if_index && ( CK_SLIST_NEXT(tlp, lp_entries) == NULL || @@ -759,7 +758,6 @@ ifp->if_index)) break; } - LAGG_RUNLOCK(); if (tlp != NULL) CK_SLIST_INSERT_AFTER(tlp, lp, lp_entries); else @@ -1537,14 +1535,17 @@ struct lagg_lb *lb; uint32_t p; + LAGG_RLOCK(); switch (sc->sc_proto) { case LAGG_PROTO_FAILOVER: lp = lagg_link_active(sc, sc->sc_primary); break; case LAGG_PROTO_LOADBALANCE: if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) == 0 || - params->hdr.flowtype == M_HASHTYPE_NONE) + params->hdr.flowtype == M_HASHTYPE_NONE) { + LAGG_RUNLOCK(); return (EOPNOTSUPP); + } p = params->hdr.flowid >> sc->flowid_shift; p %= sc->sc_count; lb = (struct lagg_lb *)sc->sc_psc; @@ -1553,16 +1554,22 @@ break; case LAGG_PROTO_LACP: if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) == 0 || - params->hdr.flowtype == M_HASHTYPE_NONE) + params->hdr.flowtype == M_HASHTYPE_NONE) { + LAGG_RUNLOCK(); return (EOPNOTSUPP); + } lp = lacp_select_tx_port_by_hash(sc, params->hdr.flowid); break; default: + LAGG_RUNLOCK(); return (EOPNOTSUPP); } - if (lp == NULL) + if (lp == NULL) { + LAGG_RUNLOCK(); return (EOPNOTSUPP); + } ifp = lp->lp_ifp; + LAGG_RUNLOCK(); if (ifp == NULL || ifp->if_snd_tag_alloc == NULL || (ifp->if_capenable & IFCAP_TXRTLMT) == 0) return (EOPNOTSUPP); @@ -1853,12 +1860,18 @@ lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp) { struct lagg_port *lp_next, *rval = NULL; - struct epoch_tracker net_et; /* * Search a port which reports an active link state. */ + /* + * This is called with either LAGG_RLOCK() held or + * LAGG_XLOCK(sc) held. + */ + if (!in_epoch(net_epoch_preempt)) + LAGG_XLOCK_ASSERT(sc); + if (lp == NULL) goto search; if (LAGG_PORTACTIVE(lp)) { @@ -1871,15 +1884,12 @@ goto found; } - search: - epoch_enter_preempt(net_epoch_preempt, &net_et); +search: CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (LAGG_PORTACTIVE(lp_next)) { - epoch_exit_preempt(net_epoch_preempt, &net_et); return (lp_next); } } - epoch_exit_preempt(net_epoch_preempt, &net_et); found: return (rval); } @@ -1961,7 +1971,7 @@ struct lagg_port *lp, *last = NULL; struct mbuf *m0; - LAGG_RLOCK(); + LAGG_RLOCK_ASSERT(); CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (!LAGG_PORTACTIVE(lp)) continue; @@ -1982,7 +1992,6 @@ } last = lp; } - LAGG_RUNLOCK(); if (last == NULL) { m_freem(m); @@ -2095,7 +2104,7 @@ rv = 0; bzero(&lb->lb_ports, sizeof(lb->lb_ports)); - LAGG_RLOCK(); + LAGG_XLOCK_ASSERT(sc); CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (lp_next == lp) continue; @@ -2108,7 +2117,6 @@ sc->sc_ifname, lp_next->lp_ifp->if_xname, i); lb->lb_ports[i++] = lp_next; } - LAGG_RUNLOCK(); return (rv); }