4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright (c) 1982, 1986, 1988, 1991, 1993
29 * The Regents of the University of California. All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 #include <smbsrv/smb_kproto.h>
62 #include <smbsrv/smb_kstat.h>
64 static kmem_cache_t
*smb_mbc_cache
= NULL
;
65 static kmem_cache_t
*smb_mbuf_cache
= NULL
;
66 static kmem_cache_t
*smb_mbufcl_cache
= NULL
;
71 if (smb_mbc_cache
!= NULL
)
73 smb_mbc_cache
= kmem_cache_create(SMBSRV_KSTAT_MBC_CACHE
,
74 sizeof (mbuf_chain_t
), 8, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
76 smb_mbuf_cache
= kmem_cache_create("smb_mbuf_cache",
77 sizeof (mbuf_t
), 8, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
79 smb_mbufcl_cache
= kmem_cache_create("smb_mbufcl_cache",
80 MCLBYTES
, 8, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
86 if (smb_mbc_cache
!= NULL
) {
87 kmem_cache_destroy(smb_mbc_cache
);
90 if (smb_mbuf_cache
!= NULL
) {
91 kmem_cache_destroy(smb_mbuf_cache
);
92 smb_mbuf_cache
= NULL
;
94 if (smb_mbufcl_cache
!= NULL
) {
95 kmem_cache_destroy(smb_mbufcl_cache
);
96 smb_mbufcl_cache
= NULL
;
101 smb_mbc_alloc(uint32_t max_bytes
)
106 mbc
= kmem_cache_alloc(smb_mbc_cache
, KM_SLEEP
);
107 bzero(mbc
, sizeof (*mbc
));
108 mbc
->mbc_magic
= SMB_MBC_MAGIC
;
110 if (max_bytes
!= 0) {
111 MGET(m
, M_WAIT
, MT_DATA
);
114 if (max_bytes
> MINCLSIZE
)
117 mbc
->max_bytes
= max_bytes
;
122 smb_mbc_free(mbuf_chain_t
*mbc
)
129 kmem_cache_free(smb_mbc_cache
, mbc
);
135 * Allocate mbufs to hold the amount of data specified.
136 * A pointer to the head of the mbuf list is returned.
139 smb_mbuf_get(uchar_t
*buf
, int nbytes
)
141 struct mbuf
*mhead
= 0;
147 count
= (nbytes
> MCLBYTES
) ? MCLBYTES
: nbytes
;
151 MGET(mhead
, M_WAIT
, MT_DATA
);
154 MGET(m
->m_next
, M_WAIT
, MT_DATA
);
163 bcopy(buf
+ offset
, m
->m_data
, count
);
170 smb_mbuf_kmem_ref(void *p
, uint_t sz
, int incr
)
178 * Allocate enough mbufs to accommodate the residual count in uio,
179 * and setup the uio_iov to point to them.
181 * This is used by the various SMB read code paths. That code is
182 * going to do a disk read into this buffer, so we'd like it to be
183 * large and contiguous. Use an external (M_EXT) buffer.
186 smb_mbuf_allocate(struct uio
*uio
)
189 int len
= uio
->uio_resid
;
191 MGET(m
, M_WAIT
, MT_DATA
);
192 if (len
> MCLBYTES
) {
193 /* Like MCLGET(), but bigger buf. */
194 m
->m_ext
.ext_buf
= kmem_zalloc(len
, KM_SLEEP
);
195 m
->m_data
= m
->m_ext
.ext_buf
;
197 m
->m_ext
.ext_size
= len
;
198 m
->m_ext
.ext_ref
= smb_mbuf_kmem_ref
;
199 } else if (len
> MLEN
) {
200 /* Use the kmem cache. */
205 uio
->uio_iov
->iov_base
= m
->m_data
;
206 uio
->uio_iov
->iov_len
= m
->m_len
;
213 * Trim an mbuf chain to nbytes.
216 smb_mbuf_trim(struct mbuf
*mhead
, int nbytes
)
218 struct mbuf
*m
= mhead
;
221 if (nbytes
<= m
->m_len
) {
223 if (m
->m_next
!= 0) {
235 MBC_LENGTH(struct mbuf_chain
*MBC
)
237 struct mbuf
*m
= (MBC
)->chain
;
248 MBC_MAXBYTES(struct mbuf_chain
*MBC
)
250 return (MBC
->max_bytes
);
254 MBC_SETUP(struct mbuf_chain
*MBC
, uint32_t max_bytes
)
256 bzero((MBC
), sizeof (struct mbuf_chain
));
257 (MBC
)->max_bytes
= max_bytes
;
261 MBC_INIT(struct mbuf_chain
*MBC
, uint32_t max_bytes
)
265 bzero((MBC
), sizeof (struct mbuf_chain
));
267 if (max_bytes
!= 0) {
268 MGET(m
, M_WAIT
, MT_DATA
);
271 if (max_bytes
> MINCLSIZE
)
274 (MBC
)->max_bytes
= max_bytes
;
278 MBC_FLUSH(struct mbuf_chain
*MBC
)
280 extern void m_freem(struct mbuf
*);
283 while ((m
= (MBC
)->chain
) != 0) {
284 (MBC
)->chain
= m
->m_nextpkt
;
288 MBC_SETUP(MBC
, (MBC
)->max_bytes
);
292 MBC_ATTACH_MBUF(struct mbuf_chain
*MBC
, struct mbuf
*MBUF
)
297 (MBC
)->chain_offset
= 0;
298 (MBC
)->chain
= (MBUF
);
302 MBC_APPEND_MBUF(struct mbuf_chain
*MBC
, struct mbuf
*MBUF
)
306 if ((MBC
)->chain
== 0) {
307 (MBC
)->chain
= (MBUF
);
310 while (m
->m_next
!= 0)
316 static int /*ARGSUSED*/
317 mclrefnoop(caddr_t p
, int size
, int adj
)
323 MBC_ATTACH_BUF(struct mbuf_chain
*MBC
, unsigned char *BUF
, int LEN
)
325 MGET((MBC
)->chain
, M_WAIT
, MT_DATA
);
326 (MBC
)->chain_offset
= 0;
327 (MBC
)->chain
->m_flags
|= M_EXT
;
328 (MBC
)->chain
->m_data
= (caddr_t
)(BUF
);
329 (MBC
)->chain
->m_ext
.ext_buf
= (caddr_t
)(BUF
);
330 (MBC
)->chain
->m_len
= (LEN
);
331 (MBC
)->chain
->m_ext
.ext_size
= (LEN
);
332 (MBC
)->chain
->m_ext
.ext_ref
= mclrefnoop
;
333 (MBC
)->max_bytes
= (LEN
);
338 MBC_SHADOW_CHAIN(struct mbuf_chain
*submbc
, struct mbuf_chain
*mbc
,
343 if (off
< 0 || len
< 0 || x
< 0 ||
344 off
> mbc
->max_bytes
|| x
> mbc
->max_bytes
)
348 submbc
->chain_offset
= off
;
349 submbc
->max_bytes
= x
;
350 submbc
->shadow_of
= mbc
;
355 * Free a single mbuf structure. Calls m->m_ext.ext_ref() to free any
356 * associated external buffers if present (indicated by m->m_flags & M_EXT)
359 m_free(struct mbuf
*m
)
368 * Free a list of mbufs. Each mbuf in the list is freed similarly to m_free.
371 m_freem(struct mbuf
*m
)
378 * Lint doesn't like the m = n assignment at the close of the loop
379 * but it is correct. MFREE assigns n = (m)->m_next so the loop
380 * is effectively assigning m = (m)->m_next then exiting when
385 } while ((m
= n
) != 0);
389 * Mbuffer utility routines.
397 m
= kmem_cache_alloc(smb_mbuf_cache
, KM_SLEEP
);
398 bzero(m
, sizeof (*m
));
403 smb_mbuf_free(mbuf_t
*m
)
405 kmem_cache_free(smb_mbuf_cache
, m
);
409 smb_mbufcl_alloc(void)
413 p
= kmem_cache_alloc(smb_mbufcl_cache
, KM_SLEEP
);
419 smb_mbufcl_free(void *p
)
421 kmem_cache_free(smb_mbufcl_cache
, p
);
425 smb_mbufcl_ref(void *p
, uint_t sz
, int incr
)
427 ASSERT3S(sz
, ==, MCLBYTES
);
429 kmem_cache_free(smb_mbufcl_cache
, p
);