Deleted Added
full compact
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 = &top;
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 = &top;
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 = &top;
809 struct mbuf *top = NULL, **mp = &top;
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 ---