Module Name: src Committed By: dyoung Date: Mon Aug 8 19:10:33 UTC 2011
Modified Files: src/sys/kern: uipc_mbuf.c uipc_mbuf2.c src/sys/sys: mbuf.h Log Message: Miscellaneous mbuf changes: 1 Add some protection against double-freeing mbufs in DIAGNOSTIC kernels. 2 Add a m_defrag() that's derived from sys/dev/pci/if_vge.c:vge_m_defrag(). This one copies the packet header. 3 Constify m_tag_find(). To generate a diff of this commit: cvs rdiff -u -r1.141 -r1.142 src/sys/kern/uipc_mbuf.c cvs rdiff -u -r1.28 -r1.29 src/sys/kern/uipc_mbuf2.c cvs rdiff -u -r1.144 -r1.145 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.141 src/sys/kern/uipc_mbuf.c:1.142 --- src/sys/kern/uipc_mbuf.c:1.141 Wed Jul 27 14:35:34 2011 +++ src/sys/kern/uipc_mbuf.c Mon Aug 8 19:10:33 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_mbuf.c,v 1.141 2011/07/27 14:35:34 uebayasi Exp $ */ +/* $NetBSD: uipc_mbuf.c,v 1.142 2011/08/08 19:10:33 dyoung 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.141 2011/07/27 14:35:34 uebayasi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.142 2011/08/08 19:10:33 dyoung Exp $"); #include "opt_mbuftrace.h" #include "opt_nmbclusters.h" @@ -494,6 +494,8 @@ { struct mbuf *m; + KASSERT(type != MT_FREE); + m = pool_cache_get(mb_cache, nowait == M_WAIT ? PR_WAITOK|PR_LIMITFAIL : 0); if (m == NULL) @@ -1249,6 +1251,62 @@ return error; } +/* + * Copy the mbuf chain to a new mbuf chain that is as short as possible. + * Return the new mbuf chain on success, NULL on failure. On success, + * free the old mbuf chain. + */ +struct mbuf * +m_defrag(struct mbuf *mold, int flags) +{ + struct mbuf *m0, *mn, *n; + size_t sz = mold->m_pkthdr.len; + +#ifdef DIAGNOSTIC + if ((mold->m_flags & M_PKTHDR) == 0) + panic("m_defrag: not a mbuf chain header"); +#endif + + MGETHDR(m0, flags, MT_DATA); + if (m0 == NULL) + return NULL; + M_COPY_PKTHDR(m0, mold); + mn = m0; + + do { + if (sz > MHLEN) { + MCLGET(mn, M_DONTWAIT); + if ((mn->m_flags & M_EXT) == 0) { + m_freem(m0); + return NULL; + } + } + + mn->m_len = MIN(sz, MCLBYTES); + + m_copydata(mold, mold->m_pkthdr.len - sz, mn->m_len, + mtod(mn, void *)); + + sz -= mn->m_len; + + if (sz > 0) { + /* need more mbufs */ + MGET(n, M_NOWAIT, MT_DATA); + if (n == NULL) { + m_freem(m0); + return NULL; + } + + mn->m_next = n; + mn = n; + } + } while (sz > 0); + + m_freem(mold); + + return m0; +} + int m_copyback0(struct mbuf **mp0, int off, int len, const void *vp, int flags, int how) Index: src/sys/kern/uipc_mbuf2.c diff -u src/sys/kern/uipc_mbuf2.c:1.28 src/sys/kern/uipc_mbuf2.c:1.29 --- src/sys/kern/uipc_mbuf2.c:1.28 Sat Apr 18 14:58:04 2009 +++ src/sys/kern/uipc_mbuf2.c Mon Aug 8 19:10:33 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_mbuf2.c,v 1.28 2009/04/18 14:58:04 tsutsui Exp $ */ +/* $NetBSD: uipc_mbuf2.c,v 1.29 2011/08/08 19:10:33 dyoung Exp $ */ /* $KAME: uipc_mbuf2.c,v 1.29 2001/02/14 13:42:10 itojun Exp $ */ /* @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf2.c,v 1.28 2009/04/18 14:58:04 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf2.c,v 1.29 2011/08/08 19:10:33 dyoung Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -335,7 +335,7 @@ /* Find a tag, starting from a given position. */ struct m_tag * -m_tag_find(struct mbuf *m, int type, struct m_tag *t) +m_tag_find(const struct mbuf *m, int type, struct m_tag *t) { struct m_tag *p; Index: src/sys/sys/mbuf.h diff -u src/sys/sys/mbuf.h:1.144 src/sys/sys/mbuf.h:1.145 --- src/sys/sys/mbuf.h:1.144 Fri Oct 24 22:31:40 2008 +++ src/sys/sys/mbuf.h Mon Aug 8 19:10:33 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: mbuf.h,v 1.144 2008/10/24 22:31:40 dyoung Exp $ */ +/* $NetBSD: mbuf.h,v 1.145 2011/08/08 19:10:33 dyoung Exp $ */ /*- * Copyright (c) 1996, 1997, 1999, 2001, 2007 The NetBSD Foundation, Inc. @@ -551,6 +551,8 @@ if ((m)->m_flags & M_EXT) { \ m_ext_free(m); \ } else { \ + KASSERT(m->m_type != MT_FREE); \ + m->m_type = MT_FREE; \ pool_cache_put(mb_cache, (m)); \ } \ @@ -667,6 +669,7 @@ /* change mbuf to new type */ #define MCHTYPE(m, t) \ do { \ + KASSERT((t) != MT_FREE); \ mbstat_type_add((m)->m_type, -1); \ mbstat_type_add(t, 1); \ (m)->m_type = t; \ @@ -823,6 +826,7 @@ struct mbuf *m_split(struct mbuf *,int, int); struct mbuf *m_getptr(struct mbuf *, int, int *); void m_adj(struct mbuf *, int); +struct mbuf *m_defrag(struct mbuf *, int); int m_apply(struct mbuf *, int, int, int (*)(void *, void *, unsigned int), void *); void m_cat(struct mbuf *,struct mbuf *); @@ -854,7 +858,7 @@ void m_tag_delete(struct mbuf *, struct m_tag *); void m_tag_delete_chain(struct mbuf *, struct m_tag *); void m_tag_delete_nonpersistent(struct mbuf *); -struct m_tag *m_tag_find(struct mbuf *, int, struct m_tag *); +struct m_tag *m_tag_find(const struct mbuf *, int, struct m_tag *); struct m_tag *m_tag_copy(struct m_tag *); int m_tag_copy_chain(struct mbuf *, struct mbuf *); void m_tag_init(struct mbuf *);