1 /*! NOTE: Most kern_mbuf functions are implemented by our mbuf.c; however, 2 * a certain few non-allocation-related ones which we can copy wholesale 3 * from FreeBSD live here. */ 4 /*- 5 * Copyright (c) 2004, 2005, 6 * Bosko Milekic <bmilekic@FreeBSD.org>. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice unmodified, this list of conditions and the following 13 * disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #include <sys/mbuf.h> 33 34 /* 35 * Allocate a given length worth of mbufs and/or clusters (whatever fits 36 * best) and return a pointer to the top of the allocated chain. If an 37 * existing mbuf chain is provided, then we will append the new chain 38 * to the existing one but still return the top of the newly allocated 39 * chain. 40 */ 41 struct mbuf * 42 m_getm2(struct mbuf *m, int len, int how, short type, int flags) 43 { 44 struct mbuf *mb, *nm = NULL, *mtail = NULL; 45 46 KASSERT(len >= 0, ("%s: len is < 0", __func__)); 47 48 /* Validate flags. */ 49 flags &= (M_PKTHDR | M_EOR); 50 51 /* Packet header mbuf must be first in chain. */ 52 if ((flags & M_PKTHDR) && m != NULL) 53 flags &= ~M_PKTHDR; 54 55 /* Loop and append maximum sized mbufs to the chain tail. */ 56 while (len > 0) { 57 if (len > MCLBYTES) 58 mb = m_getjcl(how, type, (flags & M_PKTHDR), 59 MJUMPAGESIZE); 60 else if (len >= MINCLSIZE) 61 mb = m_getcl(how, type, (flags & M_PKTHDR)); 62 else if (flags & M_PKTHDR) 63 mb = m_gethdr(how, type); 64 else 65 mb = m_get(how, type); 66 67 /* Fail the whole operation if one mbuf can't be allocated. */ 68 if (mb == NULL) { 69 if (nm != NULL) 70 m_freem(nm); 71 return (NULL); 72 } 73 74 /* Book keeping. */ 75 len -= M_SIZE(mb); 76 if (mtail != NULL) 77 mtail->m_next = mb; 78 else 79 nm = mb; 80 mtail = mb; 81 flags &= ~M_PKTHDR; /* Only valid on the first mbuf. */ 82 } 83 if (flags & M_EOR) 84 mtail->m_flags |= M_EOR; /* Only valid on the last mbuf. */ 85 86 /* If mbuf was supplied, append new chain to the end of it. */ 87 if (m != NULL) { 88 for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next) 89 ; 90 mtail->m_next = nm; 91 mtail->m_flags &= ~M_EOR; 92 } else 93 m = nm; 94 95 return (m); 96 } 97 98