Add m_ensure_contig() routine, which is equivalent to m_pullup, but does not
destroy the mbuf chain on failure (it is kept valid).
This commit is contained in:
parent
6459287701
commit
d3cb55ca37
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: uipc_mbuf.c,v 1.147 2012/10/18 19:33:38 para Exp $ */
|
||||
/* $NetBSD: uipc_mbuf.c,v 1.148 2013/01/19 00:51:52 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
|
||||
@ -62,7 +62,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.147 2012/10/18 19:33:38 para Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.148 2013/01/19 00:51:52 rmind Exp $");
|
||||
|
||||
#include "opt_mbuftrace.h"
|
||||
#include "opt_nmbclusters.h"
|
||||
@ -906,21 +906,18 @@ m_adj(struct mbuf *mp, int req_len)
|
||||
}
|
||||
|
||||
/*
|
||||
* Rearrange an mbuf chain so that len bytes are contiguous
|
||||
* and in the data area of an mbuf (so that mtod and dtom
|
||||
* will work for a structure of size len). Returns the resulting
|
||||
* mbuf chain on success, frees it and returns null on failure.
|
||||
* If there is room, it will add up to max_protohdr-len extra bytes to the
|
||||
* contiguous region in an attempt to avoid being called next time.
|
||||
* m_ensure_contig: rearrange an mbuf chain that given length of bytes
|
||||
* would be contiguous and in the data area of an mbuf (therefore, mtod()
|
||||
* would work for a structure of given length).
|
||||
*
|
||||
* => On success, returns true and the resulting mbuf chain; false otherwise.
|
||||
* => The mbuf chain may change, but is always preserved valid.
|
||||
*/
|
||||
int MPFail;
|
||||
|
||||
struct mbuf *
|
||||
m_pullup(struct mbuf *n, int len)
|
||||
bool
|
||||
m_ensure_contig(struct mbuf **m0, int len)
|
||||
{
|
||||
struct mbuf *m;
|
||||
int count;
|
||||
int space;
|
||||
struct mbuf *n = *m0, *m;
|
||||
size_t count, space;
|
||||
|
||||
/*
|
||||
* If first mbuf has no cluster, and has room for len bytes
|
||||
@ -929,17 +926,20 @@ m_pullup(struct mbuf *n, int len)
|
||||
*/
|
||||
if ((n->m_flags & M_EXT) == 0 &&
|
||||
n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
|
||||
if (n->m_len >= len)
|
||||
return (n);
|
||||
if (n->m_len >= len) {
|
||||
return true;
|
||||
}
|
||||
m = n;
|
||||
n = n->m_next;
|
||||
len -= m->m_len;
|
||||
} else {
|
||||
if (len > MHLEN)
|
||||
goto bad;
|
||||
if (len > MHLEN) {
|
||||
return false;
|
||||
}
|
||||
MGET(m, M_DONTWAIT, n->m_type);
|
||||
if (m == 0)
|
||||
goto bad;
|
||||
if (m == NULL) {
|
||||
return false;
|
||||
}
|
||||
MCLAIM(m, n->m_owner);
|
||||
m->m_len = 0;
|
||||
if (n->m_flags & M_PKTHDR) {
|
||||
@ -948,7 +948,7 @@ m_pullup(struct mbuf *n, int len)
|
||||
}
|
||||
space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
|
||||
do {
|
||||
count = min(min(max(len, max_protohdr), space), n->m_len);
|
||||
count = MIN(MIN(MAX(len, max_protohdr), space), n->m_len);
|
||||
memcpy(mtod(m, char *) + m->m_len, mtod(n, void *),
|
||||
(unsigned)count);
|
||||
len -= count;
|
||||
@ -960,16 +960,30 @@ m_pullup(struct mbuf *n, int len)
|
||||
else
|
||||
n = m_free(n);
|
||||
} while (len > 0 && n);
|
||||
if (len > 0) {
|
||||
(void) m_free(m);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
m->m_next = n;
|
||||
return (m);
|
||||
bad:
|
||||
m_freem(n);
|
||||
MPFail++;
|
||||
return (NULL);
|
||||
*m0 = m;
|
||||
|
||||
return len <= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* m_pullup: same as m_ensure_contig(), but destroys mbuf chain on error.
|
||||
*/
|
||||
int MPFail;
|
||||
|
||||
struct mbuf *
|
||||
m_pullup(struct mbuf *n, int len)
|
||||
{
|
||||
struct mbuf *m = n;
|
||||
|
||||
if (!m_ensure_contig(&m, len)) {
|
||||
KASSERT(m != NULL);
|
||||
m_freem(m);
|
||||
MPFail++;
|
||||
m = NULL;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mbuf.h,v 1.150 2012/12/27 14:41:10 christos Exp $ */
|
||||
/* $NetBSD: mbuf.h,v 1.151 2013/01/19 00:51:52 rmind Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc.
|
||||
@ -854,6 +854,8 @@ void m_ext_free(struct mbuf *);
|
||||
char * m_mapin(struct mbuf *);
|
||||
void m_move_pkthdr(struct mbuf *to, struct mbuf *from);
|
||||
|
||||
bool m_ensure_contig(struct mbuf **, int);
|
||||
|
||||
/* Inline routines. */
|
||||
static __inline u_int m_length(const struct mbuf *) __unused;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user