On Mon, May 29, 2017 at 14:16 +0200, Mike Belopuhov wrote:
> Thanks for taking your time to test, but unfortunately I have to
> withdraw both diffs.  I've realised that there's a ton of drivers
> calling ifq_deq_begin manually from their start routines and
> there's no simple solution for that that I can find right now.
> 
> I'll try to come up with something that works for all cases ASAP.

Here you go.  KERNEL_ASSERT_LOCKED might be better written as
NET_ASSERT_LOCKED for the future.  I'm not sure I want to keep
it there though as it's additional code in a hot path.

diff --git sys/net/ifq.c sys/net/ifq.c
index d37be87f444..bad95c840ff 100644
--- sys/net/ifq.c
+++ sys/net/ifq.c
@@ -313,18 +313,28 @@ ifq_deq_commit(struct ifqueue *ifq, struct mbuf *m)
        cookie = m->m_pkthdr.ph_cookie;
 
        ifq->ifq_ops->ifqop_deq_commit(ifq, m, cookie);
        ifq->ifq_len--;
        mtx_leave(&ifq->ifq_mtx);
+
+       if (ifq->ifq_serializer == NULL) {
+               KERNEL_ASSERT_LOCKED();
+               ml_purge(&ifq->ifq_free);
+       }
 }
 
 void
 ifq_deq_rollback(struct ifqueue *ifq, struct mbuf *m)
 {
        KASSERT(m != NULL);
 
        mtx_leave(&ifq->ifq_mtx);
+
+       if (ifq->ifq_serializer == NULL) {
+               KERNEL_ASSERT_LOCKED();
+               ml_purge(&ifq->ifq_free);
+       }
 }
 
 struct mbuf *
 ifq_dequeue(struct ifqueue *ifq)
 {
@@ -379,21 +389,21 @@ ifq_q_leave(struct ifqueue *ifq, void *q)
 }
 
 void
 ifq_mfreem(struct ifqueue *ifq, struct mbuf *m)
 {
-       IFQ_ASSERT_SERIALIZED(ifq);
+       /* IFQ_ASSERT_SERIALIZED(ifq); */
 
        ifq->ifq_len--;
        ifq->ifq_qdrops++;
        ml_enqueue(&ifq->ifq_free, m);
 }
 
 void
 ifq_mfreeml(struct ifqueue *ifq, struct mbuf_list *ml)
 {
-       IFQ_ASSERT_SERIALIZED(ifq);
+       /* IFQ_ASSERT_SERIALIZED(ifq); */
 
        ifq->ifq_len -= ml_len(ml);
        ifq->ifq_qdrops += ml_len(ml);
        ml_enlist(&ifq->ifq_free, ml);
 }

Reply via email to