Pull out m_uiomove() functionality from sosend().
authorJeffrey Hsu <hsu@dragonflybsd.org>
Sat, 27 Mar 2004 11:50:45 +0000 (11:50 +0000)
committerJeffrey Hsu <hsu@dragonflybsd.org>
Sat, 27 Mar 2004 11:50:45 +0000 (11:50 +0000)
sys/kern/uipc_mbuf.c
sys/sys/mbuf.h

index 25c7062..c785374 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2004 Jeffrey M. Hsu.  All rights reserved.
  * Copyright (c) 1982, 1986, 1988, 1991, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
@@ -32,7 +33,7 @@
  *
  *     @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
  * $FreeBSD: src/sys/kern/uipc_mbuf.c,v 1.51.2.24 2003/04/15 06:59:29 silby Exp $
- * $DragonFly: src/sys/kern/uipc_mbuf.c,v 1.14 2003/12/28 06:11:32 dillon Exp $
+ * $DragonFly: src/sys/kern/uipc_mbuf.c,v 1.15 2004/03/27 11:50:45 hsu Exp $
  */
 
 #include "opt_param.h"
@@ -45,6 +46,7 @@
 #include <sys/sysctl.h>
 #include <sys/domain.h>
 #include <sys/protosw.h>
+#include <sys/uio.h>
 #include <sys/thread.h>
 #include <sys/globaldata.h>
 
@@ -1674,3 +1676,62 @@ nospace:
                m_freem(m_final);
        return (NULL);
 }
+
+/*
+ * Move data from uio into mbufs.
+ * A length of zero means copy the whole uio.
+ */
+struct mbuf *
+m_uiomove(struct uio *uio, int wait, int len0)
+{
+       struct mbuf *head;              /* result mbuf chain */
+       struct mbuf *m;                 /* current working mbuf */
+       struct mbuf **mp;
+       int resid, datalen, error;
+
+       resid = (len0 == 0) ? uio->uio_resid : min(len0, uio->uio_resid);
+
+       head = NULL;
+       mp = &head;
+       do {
+               if (resid > MHLEN) {
+                       m = m_getcl(wait, MT_DATA, head == NULL ? M_PKTHDR : 0);
+                       if (m == NULL)
+                               goto failed;
+                       if (m->m_flags & M_PKTHDR)
+                               m->m_pkthdr.len = 0;
+               } else {
+                       if (head == NULL) {
+                               MGETHDR(m, wait, MT_DATA);
+                               if (m == NULL)
+                                       goto failed;
+                               m->m_pkthdr.len = 0;
+                               /* Leave room for protocol headers. */
+                               if (resid < MHLEN)
+                                       MH_ALIGN(m, resid);
+                       } else {
+                               MGET(m, wait, MT_DATA);
+                               if (m == NULL)
+                                       goto failed;
+                       }
+               }
+               datalen = min(MCLBYTES, resid);
+               error = uiomove(mtod(m, caddr_t), datalen, uio);
+               if (error) {
+                       m_free(m);
+                       goto failed;
+               }
+               m->m_len = datalen;
+               *mp = m;
+               mp = &m->m_next;
+               head->m_pkthdr.len += datalen;
+               resid -= datalen;
+       } while (resid > 0);
+
+       return (head);
+
+failed:
+       if (head)
+               m_freem(head);
+       return (NULL);
+}
index 9581dbb..92aab75 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)mbuf.h      8.5 (Berkeley) 2/19/95
  * $FreeBSD: src/sys/sys/mbuf.h,v 1.44.2.17 2003/04/15 06:15:02 silby Exp $
- * $DragonFly: src/sys/sys/mbuf.h,v 1.8 2003/12/28 06:11:33 dillon Exp $
+ * $DragonFly: src/sys/sys/mbuf.h,v 1.9 2004/03/27 11:50:45 hsu Exp $
  */
 
 #ifndef _SYS_MBUF_H_
@@ -459,6 +459,8 @@ extern      struct mbuf     *mmbfree;
 extern int              nmbclusters;
 extern int              nmbufs;
 
+struct uio;
+
 void            m_adj(struct mbuf *, int);
 void            m_cat(struct mbuf *, struct mbuf *);
 int             m_clalloc(int, int);
@@ -489,6 +491,7 @@ struct      mbuf    *m_pullup(struct mbuf *, int);
 struct mbuf    *m_retry(int, int);
 struct mbuf    *m_retryhdr(int, int);
 struct mbuf    *m_split(struct mbuf *, int, int);
+struct mbuf    *m_uiomove(struct uio *, int, int);
 caddr_t                m_mclalloc(int how);
 void           m_mclget(struct mbuf *m, int how);
 void           m_mclfree(caddr_t data);