xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_alloc.c (revision 11963:061945695ce1)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*11963SAfshin.Ardakani@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw #include <sys/types.h>
275331Samw #include <sys/sunddi.h>
285331Samw #include <sys/kmem.h>
295331Samw #include <sys/sysmacros.h>
3010966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
315331Samw #include <smbsrv/alloc.h>
325331Samw 
33*11963SAfshin.Ardakani@Sun.COM #define	SMB_SMH_MAGIC		0x534D485F	/* 'SMH_' */
34*11963SAfshin.Ardakani@Sun.COM #define	SMB_SMH_VALID(_smh_)	ASSERT((_smh_)->smh_magic == SMB_SMH_MAGIC)
35*11963SAfshin.Ardakani@Sun.COM #define	SMB_MEM2SMH(_mem_)	((smb_mem_header_t *)(_mem_) - 1)
365331Samw 
37*11963SAfshin.Ardakani@Sun.COM typedef struct smb_mem_header {
38*11963SAfshin.Ardakani@Sun.COM 	uint32_t	smh_magic;
39*11963SAfshin.Ardakani@Sun.COM 	size_t		smh_size;
40*11963SAfshin.Ardakani@Sun.COM 	smb_request_t	*smh_sr;
41*11963SAfshin.Ardakani@Sun.COM 	list_node_t	smh_lnd;
42*11963SAfshin.Ardakani@Sun.COM } smb_mem_header_t;
43*11963SAfshin.Ardakani@Sun.COM 
44*11963SAfshin.Ardakani@Sun.COM static void *smb_alloc(smb_request_t *, size_t, boolean_t);
45*11963SAfshin.Ardakani@Sun.COM static void smb_free(smb_request_t *, void *, boolean_t);
46*11963SAfshin.Ardakani@Sun.COM static void *smb_realloc(smb_request_t *, void *, size_t, boolean_t);
47*11963SAfshin.Ardakani@Sun.COM 
48*11963SAfshin.Ardakani@Sun.COM /*
49*11963SAfshin.Ardakani@Sun.COM  * Allocate memory.
50*11963SAfshin.Ardakani@Sun.COM  */
515331Samw void *
52*11963SAfshin.Ardakani@Sun.COM smb_mem_alloc(size_t size)
535331Samw {
54*11963SAfshin.Ardakani@Sun.COM 	return (smb_alloc(NULL, size, B_FALSE));
55*11963SAfshin.Ardakani@Sun.COM }
565331Samw 
57*11963SAfshin.Ardakani@Sun.COM /*
58*11963SAfshin.Ardakani@Sun.COM  * Allocate memory and zero it out.
59*11963SAfshin.Ardakani@Sun.COM  */
60*11963SAfshin.Ardakani@Sun.COM void *
61*11963SAfshin.Ardakani@Sun.COM smb_mem_zalloc(size_t size)
62*11963SAfshin.Ardakani@Sun.COM {
63*11963SAfshin.Ardakani@Sun.COM 	return (smb_alloc(NULL, size, B_TRUE));
645331Samw }
655331Samw 
66*11963SAfshin.Ardakani@Sun.COM /*
67*11963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated.
68*11963SAfshin.Ardakani@Sun.COM  *
69*11963SAfshin.Ardakani@Sun.COM  * The address passed in MUST be considered invalid when this function returns.
70*11963SAfshin.Ardakani@Sun.COM  */
71*11963SAfshin.Ardakani@Sun.COM void *
72*11963SAfshin.Ardakani@Sun.COM smb_mem_realloc(void *ptr, size_t size)
73*11963SAfshin.Ardakani@Sun.COM {
74*11963SAfshin.Ardakani@Sun.COM 	return (smb_realloc(NULL, ptr, size, B_FALSE));
75*11963SAfshin.Ardakani@Sun.COM }
76*11963SAfshin.Ardakani@Sun.COM 
77*11963SAfshin.Ardakani@Sun.COM /*
78*11963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated. If the new size is greater
79*11963SAfshin.Ardakani@Sun.COM  * than the current size, the extra space is zeroed out. If the new size is less
80*11963SAfshin.Ardakani@Sun.COM  * then the current size the space truncated is zeroed out.
81*11963SAfshin.Ardakani@Sun.COM  *
82*11963SAfshin.Ardakani@Sun.COM  * The address passed in MUST be considered invalid when this function returns.
83*11963SAfshin.Ardakani@Sun.COM  */
84*11963SAfshin.Ardakani@Sun.COM void *
85*11963SAfshin.Ardakani@Sun.COM smb_mem_rezalloc(void *ptr, size_t size)
86*11963SAfshin.Ardakani@Sun.COM {
87*11963SAfshin.Ardakani@Sun.COM 	return (smb_realloc(NULL, ptr, size, B_TRUE));
88*11963SAfshin.Ardakani@Sun.COM }
89*11963SAfshin.Ardakani@Sun.COM 
90*11963SAfshin.Ardakani@Sun.COM /*
91*11963SAfshin.Ardakani@Sun.COM  * Free memory previously allocated with smb_malloc(), smb_zalloc(),
92*11963SAfshin.Ardakani@Sun.COM  * smb_remalloc() or smb_rezalloc().
93*11963SAfshin.Ardakani@Sun.COM  */
94*11963SAfshin.Ardakani@Sun.COM void
95*11963SAfshin.Ardakani@Sun.COM smb_mem_free(void *ptr)
96*11963SAfshin.Ardakani@Sun.COM {
97*11963SAfshin.Ardakani@Sun.COM 	smb_free(NULL, ptr, B_FALSE);
98*11963SAfshin.Ardakani@Sun.COM }
99*11963SAfshin.Ardakani@Sun.COM 
100*11963SAfshin.Ardakani@Sun.COM /*
101*11963SAfshin.Ardakani@Sun.COM  * Free memory previously allocated with smb_mem_malloc(), smb_mem_zalloc(),
102*11963SAfshin.Ardakani@Sun.COM  * smb_mem_remalloc() or smb_mem_rezalloc() or smb_mem_strdup(). The memory will
103*11963SAfshin.Ardakani@Sun.COM  * be zeroed out before being actually freed.
104*11963SAfshin.Ardakani@Sun.COM  */
105*11963SAfshin.Ardakani@Sun.COM void
106*11963SAfshin.Ardakani@Sun.COM smb_mem_zfree(void *ptr)
107*11963SAfshin.Ardakani@Sun.COM {
108*11963SAfshin.Ardakani@Sun.COM 	smb_free(NULL, ptr, B_TRUE);
109*11963SAfshin.Ardakani@Sun.COM }
110*11963SAfshin.Ardakani@Sun.COM 
111*11963SAfshin.Ardakani@Sun.COM /*
112*11963SAfshin.Ardakani@Sun.COM  * Duplicate a string.
113*11963SAfshin.Ardakani@Sun.COM  */
1145331Samw char *
115*11963SAfshin.Ardakani@Sun.COM smb_mem_strdup(const char *ptr)
1165331Samw {
11710966SJordan.Brown@Sun.COM 	char	*p;
11810966SJordan.Brown@Sun.COM 	size_t	size;
1195331Samw 
1205331Samw 	size = strlen(ptr) + 1;
121*11963SAfshin.Ardakani@Sun.COM 	p = smb_alloc(NULL, size, B_FALSE);
122*11963SAfshin.Ardakani@Sun.COM 	bcopy(ptr, p, size);
1235331Samw 	return (p);
1245331Samw }
1255331Samw 
12610966SJordan.Brown@Sun.COM /*
12710966SJordan.Brown@Sun.COM  * Initialize the list for request-specific temporary storage.
12810966SJordan.Brown@Sun.COM  */
12910966SJordan.Brown@Sun.COM void
13010966SJordan.Brown@Sun.COM smb_srm_init(smb_request_t *sr)
13110966SJordan.Brown@Sun.COM {
132*11963SAfshin.Ardakani@Sun.COM 	list_create(&sr->sr_storage, sizeof (smb_mem_header_t),
133*11963SAfshin.Ardakani@Sun.COM 	    offsetof(smb_mem_header_t, smh_lnd));
13410966SJordan.Brown@Sun.COM }
13510966SJordan.Brown@Sun.COM 
13610966SJordan.Brown@Sun.COM /*
137*11963SAfshin.Ardakani@Sun.COM  * Free everything on the request-specific temporary storage list and destroy
138*11963SAfshin.Ardakani@Sun.COM  * the list.
13910966SJordan.Brown@Sun.COM  */
14010966SJordan.Brown@Sun.COM void
14110966SJordan.Brown@Sun.COM smb_srm_fini(smb_request_t *sr)
14210966SJordan.Brown@Sun.COM {
143*11963SAfshin.Ardakani@Sun.COM 	smb_mem_header_t	*smh;
14410966SJordan.Brown@Sun.COM 
145*11963SAfshin.Ardakani@Sun.COM 	while ((smh = list_head(&sr->sr_storage)) != NULL)
146*11963SAfshin.Ardakani@Sun.COM 		smb_free(sr, ++smh, B_FALSE);
14710966SJordan.Brown@Sun.COM 	list_destroy(&sr->sr_storage);
14810966SJordan.Brown@Sun.COM }
14910966SJordan.Brown@Sun.COM 
15010966SJordan.Brown@Sun.COM /*
15110966SJordan.Brown@Sun.COM  * Allocate memory and associate it with the specified request.
152*11963SAfshin.Ardakani@Sun.COM  * Memory allocated here can only be used for the duration of this request; it
153*11963SAfshin.Ardakani@Sun.COM  * will be freed automatically on completion of the request.
15410966SJordan.Brown@Sun.COM  */
15510966SJordan.Brown@Sun.COM void *
15610966SJordan.Brown@Sun.COM smb_srm_alloc(smb_request_t *sr, size_t size)
15710966SJordan.Brown@Sun.COM {
158*11963SAfshin.Ardakani@Sun.COM 	return (smb_alloc(sr, size, B_FALSE));
15910966SJordan.Brown@Sun.COM }
16010966SJordan.Brown@Sun.COM 
16110966SJordan.Brown@Sun.COM /*
162*11963SAfshin.Ardakani@Sun.COM  * Allocate memory, zero it out and associate it with the specified request.
163*11963SAfshin.Ardakani@Sun.COM  * Memory allocated here can only be used for the duration of this request; it
164*11963SAfshin.Ardakani@Sun.COM  * will be freed automatically on completion of the request.
165*11963SAfshin.Ardakani@Sun.COM  */
166*11963SAfshin.Ardakani@Sun.COM void *
167*11963SAfshin.Ardakani@Sun.COM smb_srm_zalloc(smb_request_t *sr, size_t size)
168*11963SAfshin.Ardakani@Sun.COM {
169*11963SAfshin.Ardakani@Sun.COM 	return (smb_alloc(sr, size, B_TRUE));
170*11963SAfshin.Ardakani@Sun.COM }
171*11963SAfshin.Ardakani@Sun.COM 
172*11963SAfshin.Ardakani@Sun.COM /*
173*11963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated for the specified request.
174*11963SAfshin.Ardakani@Sun.COM  *
175*11963SAfshin.Ardakani@Sun.COM  * The address passed in MUST be considered invalid when this function returns.
17610966SJordan.Brown@Sun.COM  */
17710966SJordan.Brown@Sun.COM void *
17810966SJordan.Brown@Sun.COM smb_srm_realloc(smb_request_t *sr, void *p, size_t size)
17910966SJordan.Brown@Sun.COM {
180*11963SAfshin.Ardakani@Sun.COM 	return (smb_realloc(sr, p, size, B_FALSE));
181*11963SAfshin.Ardakani@Sun.COM }
182*11963SAfshin.Ardakani@Sun.COM 
183*11963SAfshin.Ardakani@Sun.COM /*
184*11963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated for the specified request. If
185*11963SAfshin.Ardakani@Sun.COM  * the new size is greater than the current size, the extra space is zeroed out.
186*11963SAfshin.Ardakani@Sun.COM  * If the new size is less then the current size the space truncated is zeroed
187*11963SAfshin.Ardakani@Sun.COM  * out.
188*11963SAfshin.Ardakani@Sun.COM  *
189*11963SAfshin.Ardakani@Sun.COM  * The address passed in MUST be considered invalid when this function returns.
190*11963SAfshin.Ardakani@Sun.COM  */
191*11963SAfshin.Ardakani@Sun.COM void *
192*11963SAfshin.Ardakani@Sun.COM smb_srm_rezalloc(smb_request_t *sr, void *p, size_t size)
193*11963SAfshin.Ardakani@Sun.COM {
194*11963SAfshin.Ardakani@Sun.COM 	return (smb_realloc(sr, p, size, B_TRUE));
195*11963SAfshin.Ardakani@Sun.COM }
19610966SJordan.Brown@Sun.COM 
197*11963SAfshin.Ardakani@Sun.COM /*
198*11963SAfshin.Ardakani@Sun.COM  * Allocate memory.
199*11963SAfshin.Ardakani@Sun.COM  *
200*11963SAfshin.Ardakani@Sun.COM  * sr	If not NULL, request the memory allocated must be associated with.
201*11963SAfshin.Ardakani@Sun.COM  *
202*11963SAfshin.Ardakani@Sun.COM  * size	Size of the meory to allocate.
203*11963SAfshin.Ardakani@Sun.COM  *
204*11963SAfshin.Ardakani@Sun.COM  * zero	If true the memory allocated will be zeroed out.
205*11963SAfshin.Ardakani@Sun.COM  */
206*11963SAfshin.Ardakani@Sun.COM static void *
207*11963SAfshin.Ardakani@Sun.COM smb_alloc(smb_request_t *sr, size_t size, boolean_t zero)
208*11963SAfshin.Ardakani@Sun.COM {
209*11963SAfshin.Ardakani@Sun.COM 	smb_mem_header_t	*smh;
21010966SJordan.Brown@Sun.COM 
211*11963SAfshin.Ardakani@Sun.COM 	if (zero) {
212*11963SAfshin.Ardakani@Sun.COM 		smh = kmem_zalloc(size + sizeof (smb_mem_header_t), KM_SLEEP);
213*11963SAfshin.Ardakani@Sun.COM 	} else {
214*11963SAfshin.Ardakani@Sun.COM 		smh = kmem_alloc(size + sizeof (smb_mem_header_t), KM_SLEEP);
215*11963SAfshin.Ardakani@Sun.COM 		smh->smh_sr = NULL;
216*11963SAfshin.Ardakani@Sun.COM 		bzero(&smh->smh_lnd, sizeof (smh->smh_lnd));
217*11963SAfshin.Ardakani@Sun.COM 	}
218*11963SAfshin.Ardakani@Sun.COM 	smh->smh_sr = sr;
219*11963SAfshin.Ardakani@Sun.COM 	smh->smh_size = size;
220*11963SAfshin.Ardakani@Sun.COM 	smh->smh_magic = SMB_SMH_MAGIC;
221*11963SAfshin.Ardakani@Sun.COM 	if (sr != NULL) {
222*11963SAfshin.Ardakani@Sun.COM 		SMB_REQ_VALID(sr);
223*11963SAfshin.Ardakani@Sun.COM 		list_insert_tail(&sr->sr_storage, smh);
224*11963SAfshin.Ardakani@Sun.COM 	}
225*11963SAfshin.Ardakani@Sun.COM 	return (++smh);
226*11963SAfshin.Ardakani@Sun.COM }
22710966SJordan.Brown@Sun.COM 
228*11963SAfshin.Ardakani@Sun.COM /*
229*11963SAfshin.Ardakani@Sun.COM  * Free memory.
230*11963SAfshin.Ardakani@Sun.COM  *
231*11963SAfshin.Ardakani@Sun.COM  * sr	If not NULL, request the memory to free is associated with.
232*11963SAfshin.Ardakani@Sun.COM  *
233*11963SAfshin.Ardakani@Sun.COM  * ptr	Memory address
234*11963SAfshin.Ardakani@Sun.COM  *
235*11963SAfshin.Ardakani@Sun.COM  * zero	If true the memory is zeroed out before being freed.
236*11963SAfshin.Ardakani@Sun.COM  */
237*11963SAfshin.Ardakani@Sun.COM static void
238*11963SAfshin.Ardakani@Sun.COM smb_free(smb_request_t *sr, void *ptr, boolean_t zero)
239*11963SAfshin.Ardakani@Sun.COM {
240*11963SAfshin.Ardakani@Sun.COM 	smb_mem_header_t	*smh;
241*11963SAfshin.Ardakani@Sun.COM 
242*11963SAfshin.Ardakani@Sun.COM 	if (ptr != NULL) {
243*11963SAfshin.Ardakani@Sun.COM 		smh = SMB_MEM2SMH(ptr);
244*11963SAfshin.Ardakani@Sun.COM 		SMB_SMH_VALID(smh);
245*11963SAfshin.Ardakani@Sun.COM 		ASSERT(sr == smh->smh_sr);
246*11963SAfshin.Ardakani@Sun.COM 		if (sr != NULL) {
247*11963SAfshin.Ardakani@Sun.COM 			SMB_REQ_VALID(sr);
248*11963SAfshin.Ardakani@Sun.COM 			list_remove(&sr->sr_storage, smh);
249*11963SAfshin.Ardakani@Sun.COM 		}
250*11963SAfshin.Ardakani@Sun.COM 		if (zero)
251*11963SAfshin.Ardakani@Sun.COM 			bzero(ptr, smh->smh_size);
252*11963SAfshin.Ardakani@Sun.COM 
253*11963SAfshin.Ardakani@Sun.COM 		smh->smh_magic = 0;
254*11963SAfshin.Ardakani@Sun.COM 		kmem_free(smh, smh->smh_size + sizeof (smb_mem_header_t));
255*11963SAfshin.Ardakani@Sun.COM 	}
256*11963SAfshin.Ardakani@Sun.COM }
25710966SJordan.Brown@Sun.COM 
258*11963SAfshin.Ardakani@Sun.COM /*
259*11963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated.
260*11963SAfshin.Ardakani@Sun.COM  *
261*11963SAfshin.Ardakani@Sun.COM  * sr	If not NULL, request the memory is associated with.
262*11963SAfshin.Ardakani@Sun.COM  *
263*11963SAfshin.Ardakani@Sun.COM  * ptr	Memory address
264*11963SAfshin.Ardakani@Sun.COM  *
265*11963SAfshin.Ardakani@Sun.COM  * size	New size
266*11963SAfshin.Ardakani@Sun.COM  *
267*11963SAfshin.Ardakani@Sun.COM  * zero	If true zero out the extra space or the truncated space.
268*11963SAfshin.Ardakani@Sun.COM  */
269*11963SAfshin.Ardakani@Sun.COM static void *
270*11963SAfshin.Ardakani@Sun.COM smb_realloc(smb_request_t *sr, void *ptr, size_t size, boolean_t zero)
271*11963SAfshin.Ardakani@Sun.COM {
272*11963SAfshin.Ardakani@Sun.COM 	smb_mem_header_t	*smh;
273*11963SAfshin.Ardakani@Sun.COM 	void			*new_ptr;
274*11963SAfshin.Ardakani@Sun.COM 
275*11963SAfshin.Ardakani@Sun.COM 	if (ptr == NULL)
276*11963SAfshin.Ardakani@Sun.COM 		return (smb_alloc(sr, size, zero));
277*11963SAfshin.Ardakani@Sun.COM 
278*11963SAfshin.Ardakani@Sun.COM 	smh = SMB_MEM2SMH(ptr);
279*11963SAfshin.Ardakani@Sun.COM 	SMB_SMH_VALID(smh);
280*11963SAfshin.Ardakani@Sun.COM 	ASSERT(sr == smh->smh_sr);
281*11963SAfshin.Ardakani@Sun.COM 
282*11963SAfshin.Ardakani@Sun.COM 	if (size == 0) {
283*11963SAfshin.Ardakani@Sun.COM 		smb_free(sr, ptr, zero);
284*11963SAfshin.Ardakani@Sun.COM 		return (NULL);
285*11963SAfshin.Ardakani@Sun.COM 	}
286*11963SAfshin.Ardakani@Sun.COM 	if (smh->smh_size >= size) {
287*11963SAfshin.Ardakani@Sun.COM 		if ((zero) & (smh->smh_size > size))
288*11963SAfshin.Ardakani@Sun.COM 			bzero((caddr_t)ptr + size, smh->smh_size - size);
289*11963SAfshin.Ardakani@Sun.COM 		return (ptr);
290*11963SAfshin.Ardakani@Sun.COM 	}
291*11963SAfshin.Ardakani@Sun.COM 	new_ptr = smb_alloc(sr, size, B_FALSE);
292*11963SAfshin.Ardakani@Sun.COM 	bcopy(ptr, new_ptr, smh->smh_size);
293*11963SAfshin.Ardakani@Sun.COM 	if (zero)
294*11963SAfshin.Ardakani@Sun.COM 		bzero((caddr_t)new_ptr + smh->smh_size, size - smh->smh_size);
295*11963SAfshin.Ardakani@Sun.COM 
296*11963SAfshin.Ardakani@Sun.COM 	smb_free(sr, ptr, zero);
297*11963SAfshin.Ardakani@Sun.COM 	return (new_ptr);
29810966SJordan.Brown@Sun.COM }
299