diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2024-11-20 02:18:46 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2024-11-20 02:18:46 +0000 |
commit | 9bb5f5946fe1bfd777b4367d0843d238d951f801 (patch) | |
tree | 94a016e3bc295c6e20100f7786b15b4218a26284 | |
parent | 2acd40fdb3af267ac7ecad29ede14615eaaf54d3 (diff) |
provide ifq_deq_set_oactive.
ifq_deq_set_oactive is a variation on ifq_set_oactive that can be
called inside an if_deq_begin "transaction".
afresh@ found de(4) was calling ifq_set_oactive while holding the
ifq mutex via ifq_deq_begin, which led to a panic because ifq_set_oactive
also tries to take the ifq mutex. ifq_deq_set_oactive assumes the
caller is already holding the mutex.
de(4) is confusing, so it seemed simpler to add a small tweak to
ifqs than try and do major surgery on such a hairy driver.
tested by afresh@
-rw-r--r-- | sys/net/ifq.c | 13 | ||||
-rw-r--r-- | sys/net/ifq.h | 3 |
2 files changed, 14 insertions, 2 deletions
diff --git a/sys/net/ifq.c b/sys/net/ifq.c index a9565739d9d..7368aa50a57 100644 --- a/sys/net/ifq.c +++ b/sys/net/ifq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ifq.c,v 1.54 2024/11/09 04:09:56 jsg Exp $ */ +/* $OpenBSD: ifq.c,v 1.55 2024/11/20 02:18:45 dlg Exp $ */ /* * Copyright (c) 2015 David Gwynne <dlg@openbsd.org> @@ -156,6 +156,17 @@ ifq_set_oactive(struct ifqueue *ifq) } void +ifq_deq_set_oactive(struct ifqueue *ifq) +{ + MUTEX_ASSERT_LOCKED(&ifq->ifq_mtx); + + if (!ifq->ifq_oactive) { + ifq->ifq_oactive = 1; + ifq->ifq_oactives++; + } +} + +void ifq_restart_task(void *p) { struct ifqueue *ifq = p; diff --git a/sys/net/ifq.h b/sys/net/ifq.h index e7ee259e3ab..18fdb4180ef 100644 --- a/sys/net/ifq.h +++ b/sys/net/ifq.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ifq.h,v 1.41 2023/11/10 15:51:24 bluhm Exp $ */ +/* $OpenBSD: ifq.h,v 1.42 2024/11/20 02:18:45 dlg Exp $ */ /* * Copyright (c) 2015 David Gwynne <dlg@openbsd.org> @@ -444,6 +444,7 @@ void ifq_q_leave(struct ifqueue *, void *); void ifq_serialize(struct ifqueue *, struct task *); void ifq_barrier(struct ifqueue *); void ifq_set_oactive(struct ifqueue *); +void ifq_deq_set_oactive(struct ifqueue *); int ifq_deq_sleep(struct ifqueue *, struct mbuf **, int, int, const char *, volatile unsigned int *, |