Module Name: src Committed By: rmind Date: Sat Jan 19 00:51:53 UTC 2013
Modified Files: src/sys/kern: uipc_mbuf.c src/sys/sys: mbuf.h Log Message: Add m_ensure_contig() routine, which is equivalent to m_pullup, but does not destroy the mbuf chain on failure (it is kept valid). To generate a diff of this commit: cvs rdiff -u -r1.147 -r1.148 src/sys/kern/uipc_mbuf.c cvs rdiff -u -r1.150 -r1.151 src/sys/sys/mbuf.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/uipc_mbuf.c diff -u src/sys/kern/uipc_mbuf.c:1.147 src/sys/kern/uipc_mbuf.c:1.148 --- src/sys/kern/uipc_mbuf.c:1.147 Thu Oct 18 19:33:38 2012 +++ src/sys/kern/uipc_mbuf.c Sat Jan 19 00:51:52 2013 @@ -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; } /* Index: src/sys/sys/mbuf.h diff -u src/sys/sys/mbuf.h:1.150 src/sys/sys/mbuf.h:1.151 --- src/sys/sys/mbuf.h:1.150 Thu Dec 27 14:41:10 2012 +++ src/sys/sys/mbuf.h Sat Jan 19 00:51:52 2013 @@ -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;