commit 542af9092c905bf9bf12cdca04549827fab36c52 Author: David Gwynne Date: Tue Feb 24 16:20:05 2015 +1000 provide functions to requeue mbufs on mbuf_queues or mbuf_lists, and to requeue mbuf_lists on mbuf_queues. diff --git a/share/man/man9/mbuf.9 b/share/man/man9/mbuf.9 index dc90145..8ba36b9 100644 --- a/share/man/man9/mbuf.9 +++ b/share/man/man9/mbuf.9 @@ -117,6 +117,8 @@ .Fn "ml_enqueue" "struct mbuf_list *ml" "struct mbuf *m" .Ft struct mbuf * .Fn "ml_dequeue" "struct mbuf_list *ml" +.Ft void +.Fn "ml_requeue" "struct mbuf_list *ml" "struct mbuf *m" .Ft struct mbuf * .Fn "ml_dechain" "struct mbuf_list *ml" .Ft struct mbuf * @@ -138,9 +140,13 @@ .Ft struct mbuf * .Fn "mq_dequeue" "struct mbuf_queue *mq" .Ft int +.Fn "mq_requeue" "struct mbuf_queue *mq" "struct mbuf *m" +.Ft int .Fn "mq_enlist" "struct mbuf_queue *mq" "struct mbuf_list *ml" .Ft void .Fn "mq_delist" "struct mbuf_queue *mq" "struct mbuf_list *ml" +.Ft int +.Fn "mq_relist" "struct mbuf_queue *mq" "struct mbuf_list *ml" .Ft struct mbuf * .Fn "mq_dechain" "struct mbuf_queue *mq" .Ft struct mbuf * @@ -789,6 +795,12 @@ mbuf list. Dequeue an mbuf from the front of the .Fa ml mbuf list. +.It Fn "ml_requeue" "struct mbuf_list *ml" "struct mbuf *m" +Enqueue mbuf +.Fa m +at the head of the +.Fa ml +mbuf list. .It Fn "ml_dechain" "struct mbuf_list *ml" Dequeues all mbufs from the .Fa ml @@ -870,6 +882,14 @@ mbuf queue. Dequeue an mbuf from the front of the .Fa mq mbuf queue. +.It Fn "mq_requeue" "struct mbuf_queue *mq" "struct mbuf *m" +Enqueue mbuf +.Fa m +at the head of the +.Fa mq +mbuf queue. +Note, this operation will succeed even if it will cause the queue to exceed its +maximum length. .It Fn "mq_enlist" "struct mbuf_queue *mq" "struct mbuf_list *ml" Enqueue all the mbufs on the .Fa ml @@ -883,6 +903,14 @@ Dequeue all the mbufs on the mbuf queue on to the .Fa ml mbuf list. +.It Fn "mq_relist" "struct mbuf_queue *mq" "struct mbuf_list *ml" +Enqueue all the mbufs on the +.Fa ml +mbuf list at the head of the +.Fa mq +mbuf queue. +Note, this operation will succeed even if it will cause the queue to exceed its +maximum length. .It Fn "mq_dechain" "struct mbuf_queue *mq" Dequeue all mbufs from the .Fa mq @@ -933,6 +961,7 @@ already exist on the queue. .Fn ml_init , .Fn ml_enqueue , .Fn ml_dequeue , +.Fn ml_requeue , .Fn ml_dechain , .Fn ml_len , .Fn ml_empty , @@ -941,8 +970,10 @@ already exist on the queue. .Fn mq_init , .Fn mq_enqueue , .Fn mq_dequeue , +.Fn mq_requeue , .Fn mq_enlist , .Fn mq_delist , +.Fn mq_relist , .Fn mq_dechain , .Fn mq_len , .Fn mq_empty , @@ -994,10 +1025,17 @@ returns 0 if the mbuf was successfully queued, or non-zero if the mbuf was freed because it would cause the queue to exceed its maximum length. .Pp +.Fn mq_requeue +returns non-zero if the mbuf queue is full, otherwise 0. +length. +.Pp .Fn mq_enlist returns the number of mbufs that were dropped from the list if the length of the queue exceeded its maximum length. .Pp +.Fn mq_relist +returns non-zero if the mbuf queue is now full, otherwise 0. +.Pp .Fn mq_drops returns the number of mbufs that were freed during .Fn mq_enqueue diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index c17c810..1a9cd03 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1297,6 +1297,19 @@ ml_dequeue(struct mbuf_list *ml) return (m); } +void +ml_requeue(struct mbuf_list *ml, struct mbuf *m) +{ + if (ml->ml_tail == NULL) + ml->ml_head = ml->ml_tail = m; + else { + m->m_nextpkt = ml->ml_head; + ml->ml_head = m; + } + + ml->ml_len++; +} + struct mbuf * ml_dechain(struct mbuf_list *ml) { @@ -1383,6 +1396,19 @@ mq_dequeue(struct mbuf_queue *mq) } int +mq_requeue(struct mbuf_queue *mq, struct mbuf *m) +{ + int full; + + mtx_enter(&mq->mq_mtx); + ml_requeue(&mq->mq_list, m); + full = mq_len(mq) >= mq->mq_maxlen; + mtx_leave(&mq->mq_mtx); + + return (full); +} + +int mq_enlist(struct mbuf_queue *mq, struct mbuf_list *ml) { struct mbuf *m; @@ -1414,6 +1440,28 @@ mq_delist(struct mbuf_queue *mq, struct mbuf_list *ml) mtx_leave(&mq->mq_mtx); } +int +mq_relist(struct mbuf_queue *mq, struct mbuf_list *ml) +{ + int full; + + if (ml_empty(ml)) + return (mq_len(mq) > mq->mq_maxlen); + + mtx_enter(&mq->mq_mtx); + if (ml_empty(&mq->mq_list)) + mq->mq_list = *ml; + else { + ml->ml_tail->m_nextpkt = mq->mq_list.ml_head; + mq->mq_list.ml_head = ml->ml_head; + mq->mq_list.ml_len += ml->ml_len; + } + full = mq_len(mq) > mq->mq_maxlen; + mtx_leave(&mq->mq_mtx); + + return (full); +} + struct mbuf * mq_dechain(struct mbuf_queue *mq) { diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index b813d6b..34fe78e 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -496,6 +496,7 @@ struct mbuf_list { void ml_init(struct mbuf_list *); void ml_enqueue(struct mbuf_list *, struct mbuf *); struct mbuf * ml_dequeue(struct mbuf_list *); +void ml_requeue(struct mbuf_list *, struct mbuf *); struct mbuf * ml_dechain(struct mbuf_list *); struct mbuf * ml_filter(struct mbuf_list *, int (*)(void *, const struct mbuf *), void *); @@ -523,8 +524,10 @@ struct mbuf_queue { void mq_init(struct mbuf_queue *, u_int, int); int mq_enqueue(struct mbuf_queue *, struct mbuf *); struct mbuf * mq_dequeue(struct mbuf_queue *); +int mq_requeue(struct mbuf_queue *, struct mbuf *); int mq_enlist(struct mbuf_queue *, struct mbuf_list *); void mq_delist(struct mbuf_queue *, struct mbuf_list *); +int mq_relist(struct mbuf_queue *, struct mbuf_list *); struct mbuf * mq_dechain(struct mbuf_queue *); struct mbuf * mq_filter(struct mbuf_queue *, int (*)(void *, const struct mbuf *), void *);