Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Add m_ensure_contig() routine, which is equivalent to m_...



details:   https://anonhg.NetBSD.org/src/rev/163646c3dff1
branches:  trunk
changeset: 784122:163646c3dff1
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sat Jan 19 00:51:52 2013 +0000

description:
Add m_ensure_contig() routine, which is equivalent to m_pullup, but does not
destroy the mbuf chain on failure (it is kept valid).

diffstat:

 sys/kern/uipc_mbuf.c |  76 ++++++++++++++++++++++++++++++---------------------
 sys/sys/mbuf.h       |   4 ++-
 2 files changed, 48 insertions(+), 32 deletions(-)

diffs (144 lines):

diff -r 6bbb1aff8e77 -r 163646c3dff1 sys/kern/uipc_mbuf.c
--- a/sys/kern/uipc_mbuf.c      Sat Jan 19 00:35:24 2013 +0000
+++ b/sys/kern/uipc_mbuf.c      Sat Jan 19 00:51:52 2013 +0000
@@ -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 @@
 }
 
 /*
- * 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 @@
         */
        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 @@
        }
        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 @@
                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;
 }
 
 /*
diff -r 6bbb1aff8e77 -r 163646c3dff1 sys/sys/mbuf.h
--- a/sys/sys/mbuf.h    Sat Jan 19 00:35:24 2013 +0000
+++ b/sys/sys/mbuf.h    Sat Jan 19 00:51:52 2013 +0000
@@ -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 @@
 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;
 



Home | Main Index | Thread Index | Old Index