Implement m_getm() which will perform an "all or nothing" mbuf + cluster

allocation, as required.

If m_getm() receives NULL as a first argument, then it allocates `len'
(second argument) bytes worth of mbufs + clusters and returns the chain
only if it was able to allocate everything.
If the first argument is non-NULL, then it should be an existing mbuf
chain (e.g. pre-allocated mbuf sitting on a ring, on some list, etc.) and
so it will allocate `len' bytes worth of clusters and mbufs, as needed,
and append them to the tail of the passed in chain, only if it was able
to allocate everything requested.

If allocation fails, only what was allocated by the routine will be freed,
and NULL will be returned.

Also, get rid of existing m_getm() in netncp code and replace calls to it
to calls to this new generic code.

Heavily Reviewed by: bp
This commit is contained in:
bmilekic 2001-02-14 05:13:04 +00:00
parent 1c970ba5b3
commit cc2f31e1a4
3 changed files with 70 additions and 28 deletions

View File

@ -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)
{

View File

@ -46,8 +46,6 @@
#include <netncp/ncp_ncp.h>
#include <netncp/ncp_nls.h>
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));

View File

@ -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);