diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index ff174e35a283..c8cf25c40fad 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -463,7 +463,7 @@ m_reclaim(void) /* * Space allocation routines. - * These are also available as macros + * Some of these are also available as macros * for critical paths. */ struct mbuf * @@ -505,6 +505,72 @@ m_free(struct mbuf *m) return (n); } +/* + * struct mbuf * + * m_getm(m, len, how, type) + * + * This will allocate len-worth of mbufs and/or mbuf clusters (whatever fits + * best) and return a pointer to the top of the allocated chain. If m is + * non-null, then we assume that it is a single mbuf or an mbuf chain to + * which we want len bytes worth of mbufs and/or clusters attached, and so + * if we succeed in allocating it, we will just return a pointer to m. + * + * If we happen to fail at any point during the allocation, we will free + * up everything we have already allocated and return NULL. + * + */ +struct mbuf * +m_getm(struct mbuf *m, int len, int how, int type) +{ + struct mbuf *top, *tail, *mp, *mtail = NULL; + + KASSERT(len >= 0, ("len is < 0 in m_getm")); + + MGET(mp, type, how); + if (mp == NULL) + return (NULL); + else if (len > MINCLSIZE) { + MCLGET(mp, how); + if ((mp->m_flags & M_EXT) == 0) { + m_free(mp); + return (NULL); + } + } + mp->m_len = 0; + len -= M_TRAILINGSPACE(mp); + + if (m != NULL) + for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next); + else + m = mp; + + top = tail = mp; + while (len > 0) { + MGET(mp, type, how); + if (mp == NULL) + goto failed; + + tail->m_next = mp; + tail = mp; + if (len > MINCLSIZE) { + MCLGET(mp, how); + if ((mp->m_flags & M_EXT) == 0) + goto failed; + } + + mp->m_len = 0; + len -= M_TRAILINGSPACE(mp); + } + + if (mtail != NULL) + mtail->m_next = top; + return (m); + +failed: + m_freem(top); + return (NULL); +} + void m_freem(struct mbuf *m) { diff --git a/sys/netncp/ncp_rq.c b/sys/netncp/ncp_rq.c index e661f5edda82..dacdee0cc615 100644 --- a/sys/netncp/ncp_rq.c +++ b/sys/netncp/ncp_rq.c @@ -46,8 +46,6 @@ #include #include -static struct mbuf* m_getm(struct mbuf *top, int len); - int ncp_rq_head(struct ncp_rq *rqp, u_int32_t ptype, u_int8_t fn,struct proc *p, struct ucred *cred) @@ -98,29 +96,6 @@ ncp_rq_done(struct ncp_rq *rqp) { return (0); } -static struct mbuf* -m_getm(struct mbuf *top, int len) { - int rest = len, mlen; - struct mbuf *m=0,*mp; - - mp = top; - while (rest > 0) { -/* NCPSDEBUG("%d\n",rest);*/ - m = m_get(M_TRYWAIT, MT_DATA); - if (rest > MINCLSIZE) { - MCLGET(m,M_TRYWAIT); - mlen = ( (m->m_flags & M_EXT) == 0) ? MLEN : MCLBYTES; - } else { - mlen = MLEN; - } - m->m_len = 0/*min(mlen,rest)*/; - mp->m_next = m; - mp = m; - rest -= mlen; - } - return top; -} - /* * Routines to fill the request */ @@ -182,7 +157,7 @@ ncp_rq_pathstring(struct ncp_rq *rqp, int size, char *name, struct ncp_nlstables m->m_len += cplen; } if (size) { - m_getm(m, size); + m = m_getm(m, size, MT_DATA, M_TRYWAIT); while (size > 0){ m = m->m_next; cplen = min(size, M_TRAILINGSPACE(m)); @@ -215,7 +190,7 @@ ncp_rq_putanymem(struct ncp_rq *rqp, caddr_t source, int size, int type) { m->m_len += cplen; } if (size) { - m_getm(m, size); + m = m_getm(m, size, MT_DATA, M_TRYWAIT); while (size > 0){ m = m->m_next; cplen = min(size, M_TRAILINGSPACE(m)); diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 316c018eae7d..2ea81b030eb8 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -665,6 +665,7 @@ struct mbuf *m_dup(struct mbuf *, int); struct mbuf *m_free(struct mbuf *); void m_freem(struct mbuf *); struct mbuf *m_get(int, int); +struct mbuf *m_getm(struct mbuf *, int, int, int); struct mbuf *m_getclr(int, int); struct mbuf *m_gethdr(int, int); int m_mballoc(int, int);