On Thu, Jun 01, 2017 at 10:30 +0200, Mike Belopuhov wrote:
> 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.
> 

dlg@ has sent me his version which is similar in effect.
The big difference is that he completely removes the ifq_free
handling from ifq_serialize. I've OK'ed his diff so you might
want to apply it instead of mine.

Index: ifq.c
===================================================================
RCS file: /cvs/src/sys/net/ifq.c,v
retrieving revision 1.11
diff -u -p -r1.11 ifq.c
--- ifq.c       3 May 2017 20:55:29 -0000       1.11
+++ ifq.c       1 Jun 2017 09:57:41 -0000
@@ -70,7 +70,6 @@ void  ifq_barrier_task(void *);
 void
 ifq_serialize(struct ifqueue *ifq, struct task *t)
 {
-       struct mbuf_list ml = MBUF_LIST_INITIALIZER();
        struct task work;
 
        if (ISSET(t->t_flags, TASK_ONQUEUE))
@@ -97,20 +96,9 @@ ifq_serialize(struct ifqueue *ifq, struc
                        mtx_enter(&ifq->ifq_task_mtx);
                }
 
-               /*
-                * ifq->ifq_free is only modified by dequeue, which
-                * is only called from within this serialization
-                * context. it is therefore safe to access and modify
-                * here without taking ifq->ifq_mtx.
-                */
-               ml = ifq->ifq_free;
-               ml_init(&ifq->ifq_free);
-
                ifq->ifq_serializer = NULL;
        }
        mtx_leave(&ifq->ifq_task_mtx);
-
-       ml_purge(&ml);
 }
 
 int
@@ -286,16 +274,36 @@ ifq_enqueue(struct ifqueue *ifq, struct 
        return (dm == m ? ENOBUFS : 0);
 }
 
+static inline void
+ifq_deq_enter(struct ifqueue *ifq)
+{
+       mtx_enter(&ifq->ifq_mtx);
+}
+
+static inline void
+ifq_deq_leave(struct ifqueue *ifq)
+{
+       struct mbuf_list ml;
+
+       ml = ifq->ifq_free;
+       ml_init(&ifq->ifq_free);
+
+       mtx_leave(&ifq->ifq_mtx);
+
+       if (!ml_empty(&ml))
+               ml_purge(&ml);
+}
+
 struct mbuf *
 ifq_deq_begin(struct ifqueue *ifq)
 {
        struct mbuf *m = NULL;
        void *cookie;
 
-       mtx_enter(&ifq->ifq_mtx);
+       ifq_deq_enter(ifq);
        if (ifq->ifq_len == 0 ||
            (m = ifq->ifq_ops->ifqop_deq_begin(ifq, &cookie)) == NULL) {
-               mtx_leave(&ifq->ifq_mtx);
+               ifq_deq_leave(ifq);
                return (NULL);
        }
 
@@ -314,7 +322,7 @@ ifq_deq_commit(struct ifqueue *ifq, stru
 
        ifq->ifq_ops->ifqop_deq_commit(ifq, m, cookie);
        ifq->ifq_len--;
-       mtx_leave(&ifq->ifq_mtx);
+       ifq_deq_leave(ifq);
 }
 
 void
@@ -322,7 +330,7 @@ ifq_deq_rollback(struct ifqueue *ifq, st
 {
        KASSERT(m != NULL);
 
-       mtx_leave(&ifq->ifq_mtx);
+       ifq_deq_leave(ifq);
 }
 
 struct mbuf *
@@ -381,7 +389,7 @@ ifq_q_leave(struct ifqueue *ifq, void *q
 void
 ifq_mfreem(struct ifqueue *ifq, struct mbuf *m)
 {
-       IFQ_ASSERT_SERIALIZED(ifq);
+       MUTEX_ASSERT_LOCKED(&ifq->ifq_mtx);
 
        ifq->ifq_len--;
        ifq->ifq_qdrops++;
@@ -391,7 +399,7 @@ ifq_mfreem(struct ifqueue *ifq, struct m
 void
 ifq_mfreeml(struct ifqueue *ifq, struct mbuf_list *ml)
 {
-       IFQ_ASSERT_SERIALIZED(ifq);
+       MUTEX_ASSERT_LOCKED(&ifq->ifq_mtx);
 
        ifq->ifq_len -= ml_len(ml);
        ifq->ifq_qdrops += ml_len(ml);

Reply via email to