From 0c33f36dd83c00ff764d2c1479f51c8e5d5deb53 Mon Sep 17 00:00:00 2001 From: Jeffrey Hsu Date: Sat, 27 Mar 2004 11:50:45 +0000 Subject: [PATCH] Pull out m_uiomove() functionality from sosend(). --- sys/kern/uipc_mbuf.c | 63 +++++++++++++++++++++++++++++++++++++++++++- sys/sys/mbuf.h | 5 +++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 25c706291b..c78537403c 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -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 #include #include +#include #include #include @@ -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); +} diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 9581dbbab6..92aab7599a 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -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); -- 2.41.0