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

Reply via email to