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;
 

Reply via email to