uipc_mbuf.c (128402) | uipc_mbuf.c (129906) |
---|---|
1/* 2 * Copyright (c) 1982, 1986, 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 16 unchanged lines hidden (view full) --- 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 30 */ 31 32#include <sys/cdefs.h> | 1/* 2 * Copyright (c) 1982, 1986, 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 16 unchanged lines hidden (view full) --- 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 30 */ 31 32#include <sys/cdefs.h> |
33__FBSDID("$FreeBSD: head/sys/kern/uipc_mbuf.c 128402 2004-04-18 13:01:28Z luigi $"); | 33__FBSDID("$FreeBSD: head/sys/kern/uipc_mbuf.c 129906 2004-05-31 21:46:06Z bmilekic $"); |
34 35#include "opt_mac.h" 36#include "opt_param.h" 37#include "opt_mbuf_stress_test.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> --- 39 unchanged lines hidden (view full) --- 81 &m_defraguseless, 0, ""); 82SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragfailure, CTLFLAG_RD, 83 &m_defragfailure, 0, ""); 84SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragrandomfailures, CTLFLAG_RW, 85 &m_defragrandomfailures, 0, ""); 86#endif 87 88/* | 34 35#include "opt_mac.h" 36#include "opt_param.h" 37#include "opt_mbuf_stress_test.h" 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/kernel.h> --- 39 unchanged lines hidden (view full) --- 81 &m_defraguseless, 0, ""); 82SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragfailure, CTLFLAG_RD, 83 &m_defragfailure, 0, ""); 84SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragrandomfailures, CTLFLAG_RW, 85 &m_defragrandomfailures, 0, ""); 86#endif 87 88/* |
89 * Malloc-type for external ext_buf ref counts. 90 */ 91MALLOC_DEFINE(M_MBUF, "mbextcnt", "mbuf external ref counts"); 92 93/* 94 * Allocate a given length worth of mbufs and/or clusters (whatever fits 95 * best) and return a pointer to the top of the allocated chain. If an 96 * existing mbuf chain is provided, then we will append the new chain 97 * to the existing one but still return the top of the newly allocated 98 * chain. 99 */ 100struct mbuf * 101m_getm(struct mbuf *m, int len, int how, short type) 102{ 103 struct mbuf *mb, *top, *cur, *mtail; 104 int num, rem; 105 int i; 106 107 KASSERT(len >= 0, ("m_getm(): len is < 0")); 108 109 /* If m != NULL, we will append to the end of that chain. */ 110 if (m != NULL) 111 for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next); 112 else 113 mtail = NULL; 114 115 /* 116 * Calculate how many mbufs+clusters ("packets") we need and how much 117 * leftover there is after that and allocate the first mbuf+cluster 118 * if required. 119 */ 120 num = len / MCLBYTES; 121 rem = len % MCLBYTES; 122 top = cur = NULL; 123 if (num > 0) { 124 if ((top = cur = m_getcl(how, type, 0)) == NULL) 125 goto failed; 126 } 127 num--; 128 top->m_len = 0; 129 130 for (i = 0; i < num; i++) { 131 mb = m_getcl(how, type, 0); 132 if (mb == NULL) 133 goto failed; 134 mb->m_len = 0; 135 cur = (cur->m_next = mb); 136 } 137 if (rem > 0) { 138 mb = (rem > MINCLSIZE) ? 139 m_getcl(how, type, 0) : m_get(how, type); 140 if (mb == NULL) 141 goto failed; 142 mb->m_len = 0; 143 if (cur == NULL) 144 top = mb; 145 else 146 cur->m_next = mb; 147 } 148 149 if (mtail != NULL) 150 mtail->m_next = top; 151 return top; 152failed: 153 if (top != NULL) 154 m_freem(top); 155 return NULL; 156} 157 158/* 159 * Free an entire chain of mbufs and associated external buffers, if 160 * applicable. 161 */ 162void 163m_freem(struct mbuf *mb) 164{ 165 166 while (mb != NULL) 167 mb = m_free(mb); 168} 169 170/*- 171 * Configure a provided mbuf to refer to the provided external storage 172 * buffer and setup a reference count for said buffer. If the setting 173 * up of the reference count fails, the M_EXT bit will not be set. If 174 * successfull, the M_EXT bit is set in the mbuf's flags. 175 * 176 * Arguments: 177 * mb The existing mbuf to which to attach the provided buffer. 178 * buf The address of the provided external storage buffer. 179 * size The size of the provided buffer. 180 * freef A pointer to a routine that is responsible for freeing the 181 * provided external storage buffer. 182 * args A pointer to an argument structure (of any type) to be passed 183 * to the provided freef routine (may be NULL). 184 * flags Any other flags to be passed to the provided mbuf. 185 * type The type that the external storage buffer should be 186 * labeled with. 187 * 188 * Returns: 189 * Nothing. 190 */ 191void 192m_extadd(struct mbuf *mb, caddr_t buf, u_int size, 193 void (*freef)(void *, void *), void *args, int flags, int type) 194{ 195 u_int *ref_cnt = NULL; 196 197 /* XXX Shouldn't be adding EXT_CLUSTER with this API */ 198 if (type == EXT_CLUSTER) 199 ref_cnt = (u_int *)uma_find_refcnt(zone_clust, 200 mb->m_ext.ext_buf); 201 else if (type == EXT_EXTREF) 202 ref_cnt = mb->m_ext.ref_cnt; 203 mb->m_ext.ref_cnt = (ref_cnt == NULL) ? 204 malloc(sizeof(u_int), M_MBUF, M_NOWAIT) : (u_int *)ref_cnt; 205 if (mb->m_ext.ref_cnt != NULL) { 206 *(mb->m_ext.ref_cnt) = 1; 207 mb->m_flags |= (M_EXT | flags); 208 mb->m_ext.ext_buf = buf; 209 mb->m_data = mb->m_ext.ext_buf; 210 mb->m_ext.ext_size = size; 211 mb->m_ext.ext_free = freef; 212 mb->m_ext.ext_args = args; 213 mb->m_ext.ext_type = type; 214 } 215} 216 217/* 218 * Non-directly-exported function to clean up after mbufs with M_EXT 219 * storage attached to them if the reference count hits 0. 220 */ 221void 222mb_free_ext(struct mbuf *m) 223{ 224 225 MEXT_REM_REF(m); 226 if (atomic_cmpset_int(m->m_ext.ref_cnt, 0, 1)) { 227 if (m->m_ext.ext_type == EXT_PACKET) { 228 uma_zfree(zone_pack, m); 229 return; 230 } else if (m->m_ext.ext_type == EXT_CLUSTER) { 231 uma_zfree(zone_clust, m->m_ext.ext_buf); 232 m->m_ext.ext_buf = NULL; 233 } else { 234 (*(m->m_ext.ext_free))(m->m_ext.ext_buf, 235 m->m_ext.ext_args); 236 if (m->m_ext.ext_type != EXT_EXTREF) 237 free(m->m_ext.ref_cnt, M_MBUF); 238 } 239 } 240 uma_zfree(zone_mbuf, m); 241} 242 243/* |
|
89 * "Move" mbuf pkthdr from "from" to "to". 90 * "from" must have M_PKTHDR set, and "to" must be empty. 91 */ 92void 93m_move_pkthdr(struct mbuf *to, struct mbuf *from) 94{ 95 96#if 0 --- 262 unchanged lines hidden (view full) --- 359 /* While there's more data, get a new mbuf, tack it on, and fill it */ 360 remain = m->m_pkthdr.len; 361 moff = 0; 362 p = ⊤ 363 while (remain > 0 || top == NULL) { /* allow m->m_pkthdr.len == 0 */ 364 struct mbuf *n; 365 366 /* Get the next new mbuf */ | 244 * "Move" mbuf pkthdr from "from" to "to". 245 * "from" must have M_PKTHDR set, and "to" must be empty. 246 */ 247void 248m_move_pkthdr(struct mbuf *to, struct mbuf *from) 249{ 250 251#if 0 --- 262 unchanged lines hidden (view full) --- 514 /* While there's more data, get a new mbuf, tack it on, and fill it */ 515 remain = m->m_pkthdr.len; 516 moff = 0; 517 p = ⊤ 518 while (remain > 0 || top == NULL) { /* allow m->m_pkthdr.len == 0 */ 519 struct mbuf *n; 520 521 /* Get the next new mbuf */ |
367 MGET(n, how, m->m_type); | 522 if (remain >= MINCLSIZE) { 523 n = m_getcl(how, m->m_type, 0); 524 nsize = MCLBYTES; 525 } else { 526 n = m_get(how, m->m_type); 527 nsize = MLEN; 528 } |
368 if (n == NULL) 369 goto nospace; | 529 if (n == NULL) 530 goto nospace; |
370 if (top == NULL) { /* first one, must be PKTHDR */ 371 if (!m_dup_pkthdr(n, m, how)) | 531 532 if (top == NULL) { /* First one, must be PKTHDR */ 533 if (!m_dup_pkthdr(n, m, how)) { 534 m_free(n); |
372 goto nospace; | 535 goto nospace; |
373 nsize = MHLEN; 374 } else /* not the first one */ 375 nsize = MLEN; 376 if (remain >= MINCLSIZE) { 377 MCLGET(n, how); 378 if ((n->m_flags & M_EXT) == 0) { 379 (void)m_free(n); 380 goto nospace; | |
381 } | 536 } |
382 nsize = MCLBYTES; | 537 nsize = MHLEN; |
383 } 384 n->m_len = 0; 385 386 /* Link it into the new chain */ 387 *p = n; 388 p = &n->m_next; 389 390 /* Copy data from original mbuf(s) into new mbuf */ --- 255 unchanged lines hidden (view full) --- 646 * Note that `off' argument is offset into first mbuf of target chain from 647 * which to begin copying the data to. 648 */ 649struct mbuf * 650m_devget(char *buf, int totlen, int off, struct ifnet *ifp, 651 void (*copy)(char *from, caddr_t to, u_int len)) 652{ 653 struct mbuf *m; | 538 } 539 n->m_len = 0; 540 541 /* Link it into the new chain */ 542 *p = n; 543 p = &n->m_next; 544 545 /* Copy data from original mbuf(s) into new mbuf */ --- 255 unchanged lines hidden (view full) --- 801 * Note that `off' argument is offset into first mbuf of target chain from 802 * which to begin copying the data to. 803 */ 804struct mbuf * 805m_devget(char *buf, int totlen, int off, struct ifnet *ifp, 806 void (*copy)(char *from, caddr_t to, u_int len)) 807{ 808 struct mbuf *m; |
654 struct mbuf *top = 0, **mp = ⊤ | 809 struct mbuf *top = NULL, **mp = ⊤ |
655 int len; 656 657 if (off < 0 || off > MHLEN) 658 return (NULL); 659 | 810 int len; 811 812 if (off < 0 || off > MHLEN) 813 return (NULL); 814 |
660 MGETHDR(m, M_DONTWAIT, MT_DATA); 661 if (m == NULL) 662 return (NULL); 663 m->m_pkthdr.rcvif = ifp; 664 m->m_pkthdr.len = totlen; 665 len = MHLEN; 666 | |
667 while (totlen > 0) { | 815 while (totlen > 0) { |
668 if (top) { 669 MGET(m, M_DONTWAIT, MT_DATA); | 816 if (top == NULL) { /* First one, must be PKTHDR */ 817 if (totlen + off >= MINCLSIZE) { 818 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 819 len = MCLBYTES; 820 } else { 821 m = m_gethdr(M_DONTWAIT, MT_DATA); 822 len = MHLEN; 823 824 /* Place initial small packet/header at end of mbuf */ 825 if (m && totlen + off + max_linkhdr <= MLEN) { 826 m->m_data += max_linkhdr; 827 len -= max_linkhdr; 828 } 829 } 830 if (m == NULL) 831 return NULL; 832 m->m_pkthdr.rcvif = ifp; 833 m->m_pkthdr.len = totlen; 834 } else { 835 if (totlen + off >= MINCLSIZE) { 836 m = m_getcl(M_DONTWAIT, MT_DATA, 0); 837 len = MCLBYTES; 838 } else { 839 m = m_get(M_DONTWAIT, MT_DATA); 840 len = MLEN; 841 } |
670 if (m == NULL) { 671 m_freem(top); | 842 if (m == NULL) { 843 m_freem(top); |
672 return (NULL); | 844 return NULL; |
673 } | 845 } |
674 len = MLEN; | |
675 } | 846 } |
676 if (totlen + off >= MINCLSIZE) { 677 MCLGET(m, M_DONTWAIT); 678 if (m->m_flags & M_EXT) 679 len = MCLBYTES; 680 } else { 681 /* 682 * Place initial small packet/header at end of mbuf. 683 */ 684 if (top == NULL && totlen + off + max_linkhdr <= len) { 685 m->m_data += max_linkhdr; 686 len -= max_linkhdr; 687 } 688 } | |
689 if (off) { 690 m->m_data += off; 691 len -= off; 692 off = 0; 693 } 694 m->m_len = len = min(totlen, len); 695 if (copy) 696 copy(buf, mtod(m, caddr_t), (u_int)len); --- 20 unchanged lines hidden (view full) --- 717 int totlen = 0; 718 719 if (m0 == NULL) 720 return; 721 while (off > (mlen = m->m_len)) { 722 off -= mlen; 723 totlen += mlen; 724 if (m->m_next == NULL) { | 847 if (off) { 848 m->m_data += off; 849 len -= off; 850 off = 0; 851 } 852 m->m_len = len = min(totlen, len); 853 if (copy) 854 copy(buf, mtod(m, caddr_t), (u_int)len); --- 20 unchanged lines hidden (view full) --- 875 int totlen = 0; 876 877 if (m0 == NULL) 878 return; 879 while (off > (mlen = m->m_len)) { 880 off -= mlen; 881 totlen += mlen; 882 if (m->m_next == NULL) { |
725 n = m_get_clrd(M_DONTWAIT, m->m_type); | 883 n = m_get(M_DONTWAIT, m->m_type); |
726 if (n == NULL) 727 goto out; | 884 if (n == NULL) 885 goto out; |
886 bzero(mtod(n, caddr_t), MLEN); |
|
728 n->m_len = min(MLEN, len + off); 729 m->m_next = n; 730 } 731 m = m->m_next; 732 } 733 while (len > 0) { 734 mlen = min (m->m_len - off, len); 735 bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen); --- 341 unchanged lines hidden --- | 887 n->m_len = min(MLEN, len + off); 888 m->m_next = n; 889 } 890 m = m->m_next; 891 } 892 while (len > 0) { 893 mlen = min (m->m_len - off, len); 894 bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen); --- 341 unchanged lines hidden --- |