xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_alloc.c (revision 12508:edb7861a1533)
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*12508Samw@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw  */
245331Samw 
255331Samw #include <sys/types.h>
265331Samw #include <sys/sunddi.h>
275331Samw #include <sys/kmem.h>
285331Samw #include <sys/sysmacros.h>
2910966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h>
305331Samw #include <smbsrv/alloc.h>
315331Samw 
3211963SAfshin.Ardakani@Sun.COM #define	SMB_SMH_MAGIC		0x534D485F	/* 'SMH_' */
3311963SAfshin.Ardakani@Sun.COM #define	SMB_SMH_VALID(_smh_)	ASSERT((_smh_)->smh_magic == SMB_SMH_MAGIC)
3411963SAfshin.Ardakani@Sun.COM #define	SMB_MEM2SMH(_mem_)	((smb_mem_header_t *)(_mem_) - 1)
355331Samw 
3611963SAfshin.Ardakani@Sun.COM typedef struct smb_mem_header {
3711963SAfshin.Ardakani@Sun.COM 	uint32_t	smh_magic;
3811963SAfshin.Ardakani@Sun.COM 	size_t		smh_size;
3911963SAfshin.Ardakani@Sun.COM 	smb_request_t	*smh_sr;
4011963SAfshin.Ardakani@Sun.COM 	list_node_t	smh_lnd;
4111963SAfshin.Ardakani@Sun.COM } smb_mem_header_t;
4211963SAfshin.Ardakani@Sun.COM 
4311963SAfshin.Ardakani@Sun.COM static void *smb_alloc(smb_request_t *, size_t, boolean_t);
4411963SAfshin.Ardakani@Sun.COM static void smb_free(smb_request_t *, void *, boolean_t);
4511963SAfshin.Ardakani@Sun.COM static void *smb_realloc(smb_request_t *, void *, size_t, boolean_t);
4611963SAfshin.Ardakani@Sun.COM 
4711963SAfshin.Ardakani@Sun.COM /*
4811963SAfshin.Ardakani@Sun.COM  * Allocate memory.
4911963SAfshin.Ardakani@Sun.COM  */
505331Samw void *
smb_mem_alloc(size_t size)5111963SAfshin.Ardakani@Sun.COM smb_mem_alloc(size_t size)
525331Samw {
5311963SAfshin.Ardakani@Sun.COM 	return (smb_alloc(NULL, size, B_FALSE));
5411963SAfshin.Ardakani@Sun.COM }
555331Samw 
5611963SAfshin.Ardakani@Sun.COM /*
5711963SAfshin.Ardakani@Sun.COM  * Allocate memory and zero it out.
5811963SAfshin.Ardakani@Sun.COM  */
5911963SAfshin.Ardakani@Sun.COM void *
smb_mem_zalloc(size_t size)6011963SAfshin.Ardakani@Sun.COM smb_mem_zalloc(size_t size)
6111963SAfshin.Ardakani@Sun.COM {
6211963SAfshin.Ardakani@Sun.COM 	return (smb_alloc(NULL, size, B_TRUE));
635331Samw }
645331Samw 
6511963SAfshin.Ardakani@Sun.COM /*
6611963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated.
6711963SAfshin.Ardakani@Sun.COM  *
6811963SAfshin.Ardakani@Sun.COM  * The address passed in MUST be considered invalid when this function returns.
6911963SAfshin.Ardakani@Sun.COM  */
7011963SAfshin.Ardakani@Sun.COM void *
smb_mem_realloc(void * ptr,size_t size)7111963SAfshin.Ardakani@Sun.COM smb_mem_realloc(void *ptr, size_t size)
7211963SAfshin.Ardakani@Sun.COM {
7311963SAfshin.Ardakani@Sun.COM 	return (smb_realloc(NULL, ptr, size, B_FALSE));
7411963SAfshin.Ardakani@Sun.COM }
7511963SAfshin.Ardakani@Sun.COM 
7611963SAfshin.Ardakani@Sun.COM /*
7711963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated. If the new size is greater
7811963SAfshin.Ardakani@Sun.COM  * than the current size, the extra space is zeroed out. If the new size is less
7911963SAfshin.Ardakani@Sun.COM  * then the current size the space truncated is zeroed out.
8011963SAfshin.Ardakani@Sun.COM  *
8111963SAfshin.Ardakani@Sun.COM  * The address passed in MUST be considered invalid when this function returns.
8211963SAfshin.Ardakani@Sun.COM  */
8311963SAfshin.Ardakani@Sun.COM void *
smb_mem_rezalloc(void * ptr,size_t size)8411963SAfshin.Ardakani@Sun.COM smb_mem_rezalloc(void *ptr, size_t size)
8511963SAfshin.Ardakani@Sun.COM {
8611963SAfshin.Ardakani@Sun.COM 	return (smb_realloc(NULL, ptr, size, B_TRUE));
8711963SAfshin.Ardakani@Sun.COM }
8811963SAfshin.Ardakani@Sun.COM 
8911963SAfshin.Ardakani@Sun.COM /*
9011963SAfshin.Ardakani@Sun.COM  * Free memory previously allocated with smb_malloc(), smb_zalloc(),
9111963SAfshin.Ardakani@Sun.COM  * smb_remalloc() or smb_rezalloc().
9211963SAfshin.Ardakani@Sun.COM  */
9311963SAfshin.Ardakani@Sun.COM void
smb_mem_free(void * ptr)9411963SAfshin.Ardakani@Sun.COM smb_mem_free(void *ptr)
9511963SAfshin.Ardakani@Sun.COM {
9611963SAfshin.Ardakani@Sun.COM 	smb_free(NULL, ptr, B_FALSE);
9711963SAfshin.Ardakani@Sun.COM }
9811963SAfshin.Ardakani@Sun.COM 
9911963SAfshin.Ardakani@Sun.COM /*
10011963SAfshin.Ardakani@Sun.COM  * Free memory previously allocated with smb_mem_malloc(), smb_mem_zalloc(),
10111963SAfshin.Ardakani@Sun.COM  * smb_mem_remalloc() or smb_mem_rezalloc() or smb_mem_strdup(). The memory will
10211963SAfshin.Ardakani@Sun.COM  * be zeroed out before being actually freed.
10311963SAfshin.Ardakani@Sun.COM  */
10411963SAfshin.Ardakani@Sun.COM void
smb_mem_zfree(void * ptr)10511963SAfshin.Ardakani@Sun.COM smb_mem_zfree(void *ptr)
10611963SAfshin.Ardakani@Sun.COM {
10711963SAfshin.Ardakani@Sun.COM 	smb_free(NULL, ptr, B_TRUE);
10811963SAfshin.Ardakani@Sun.COM }
10911963SAfshin.Ardakani@Sun.COM 
11011963SAfshin.Ardakani@Sun.COM /*
11111963SAfshin.Ardakani@Sun.COM  * Duplicate a string.
11211963SAfshin.Ardakani@Sun.COM  */
1135331Samw char *
smb_mem_strdup(const char * ptr)11411963SAfshin.Ardakani@Sun.COM smb_mem_strdup(const char *ptr)
1155331Samw {
11610966SJordan.Brown@Sun.COM 	char	*p;
11710966SJordan.Brown@Sun.COM 	size_t	size;
1185331Samw 
1195331Samw 	size = strlen(ptr) + 1;
12011963SAfshin.Ardakani@Sun.COM 	p = smb_alloc(NULL, size, B_FALSE);
12111963SAfshin.Ardakani@Sun.COM 	bcopy(ptr, p, size);
1225331Samw 	return (p);
1235331Samw }
1245331Samw 
12510966SJordan.Brown@Sun.COM /*
12610966SJordan.Brown@Sun.COM  * Initialize the list for request-specific temporary storage.
12710966SJordan.Brown@Sun.COM  */
12810966SJordan.Brown@Sun.COM void
smb_srm_init(smb_request_t * sr)12910966SJordan.Brown@Sun.COM smb_srm_init(smb_request_t *sr)
13010966SJordan.Brown@Sun.COM {
13111963SAfshin.Ardakani@Sun.COM 	list_create(&sr->sr_storage, sizeof (smb_mem_header_t),
13211963SAfshin.Ardakani@Sun.COM 	    offsetof(smb_mem_header_t, smh_lnd));
13310966SJordan.Brown@Sun.COM }
13410966SJordan.Brown@Sun.COM 
13510966SJordan.Brown@Sun.COM /*
13611963SAfshin.Ardakani@Sun.COM  * Free everything on the request-specific temporary storage list and destroy
13711963SAfshin.Ardakani@Sun.COM  * the list.
13810966SJordan.Brown@Sun.COM  */
13910966SJordan.Brown@Sun.COM void
smb_srm_fini(smb_request_t * sr)14010966SJordan.Brown@Sun.COM smb_srm_fini(smb_request_t *sr)
14110966SJordan.Brown@Sun.COM {
14211963SAfshin.Ardakani@Sun.COM 	smb_mem_header_t	*smh;
14310966SJordan.Brown@Sun.COM 
14411963SAfshin.Ardakani@Sun.COM 	while ((smh = list_head(&sr->sr_storage)) != NULL)
14511963SAfshin.Ardakani@Sun.COM 		smb_free(sr, ++smh, B_FALSE);
14610966SJordan.Brown@Sun.COM 	list_destroy(&sr->sr_storage);
14710966SJordan.Brown@Sun.COM }
14810966SJordan.Brown@Sun.COM 
14910966SJordan.Brown@Sun.COM /*
15010966SJordan.Brown@Sun.COM  * Allocate memory and associate it with the specified request.
15111963SAfshin.Ardakani@Sun.COM  * Memory allocated here can only be used for the duration of this request; it
15211963SAfshin.Ardakani@Sun.COM  * will be freed automatically on completion of the request.
15310966SJordan.Brown@Sun.COM  */
15410966SJordan.Brown@Sun.COM void *
smb_srm_alloc(smb_request_t * sr,size_t size)15510966SJordan.Brown@Sun.COM smb_srm_alloc(smb_request_t *sr, size_t size)
15610966SJordan.Brown@Sun.COM {
15711963SAfshin.Ardakani@Sun.COM 	return (smb_alloc(sr, size, B_FALSE));
15810966SJordan.Brown@Sun.COM }
15910966SJordan.Brown@Sun.COM 
16010966SJordan.Brown@Sun.COM /*
16111963SAfshin.Ardakani@Sun.COM  * Allocate memory, zero it out and associate it with the specified request.
16211963SAfshin.Ardakani@Sun.COM  * Memory allocated here can only be used for the duration of this request; it
16311963SAfshin.Ardakani@Sun.COM  * will be freed automatically on completion of the request.
16411963SAfshin.Ardakani@Sun.COM  */
16511963SAfshin.Ardakani@Sun.COM void *
smb_srm_zalloc(smb_request_t * sr,size_t size)16611963SAfshin.Ardakani@Sun.COM smb_srm_zalloc(smb_request_t *sr, size_t size)
16711963SAfshin.Ardakani@Sun.COM {
16811963SAfshin.Ardakani@Sun.COM 	return (smb_alloc(sr, size, B_TRUE));
16911963SAfshin.Ardakani@Sun.COM }
17011963SAfshin.Ardakani@Sun.COM 
17111963SAfshin.Ardakani@Sun.COM /*
17211963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated for the specified request.
17311963SAfshin.Ardakani@Sun.COM  *
17411963SAfshin.Ardakani@Sun.COM  * The address passed in MUST be considered invalid when this function returns.
17510966SJordan.Brown@Sun.COM  */
17610966SJordan.Brown@Sun.COM void *
smb_srm_realloc(smb_request_t * sr,void * p,size_t size)17710966SJordan.Brown@Sun.COM smb_srm_realloc(smb_request_t *sr, void *p, size_t size)
17810966SJordan.Brown@Sun.COM {
17911963SAfshin.Ardakani@Sun.COM 	return (smb_realloc(sr, p, size, B_FALSE));
18011963SAfshin.Ardakani@Sun.COM }
18111963SAfshin.Ardakani@Sun.COM 
18211963SAfshin.Ardakani@Sun.COM /*
18311963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated for the specified request. If
18411963SAfshin.Ardakani@Sun.COM  * the new size is greater than the current size, the extra space is zeroed out.
18511963SAfshin.Ardakani@Sun.COM  * If the new size is less then the current size the space truncated is zeroed
18611963SAfshin.Ardakani@Sun.COM  * out.
18711963SAfshin.Ardakani@Sun.COM  *
18811963SAfshin.Ardakani@Sun.COM  * The address passed in MUST be considered invalid when this function returns.
18911963SAfshin.Ardakani@Sun.COM  */
19011963SAfshin.Ardakani@Sun.COM void *
smb_srm_rezalloc(smb_request_t * sr,void * p,size_t size)19111963SAfshin.Ardakani@Sun.COM smb_srm_rezalloc(smb_request_t *sr, void *p, size_t size)
19211963SAfshin.Ardakani@Sun.COM {
19311963SAfshin.Ardakani@Sun.COM 	return (smb_realloc(sr, p, size, B_TRUE));
19411963SAfshin.Ardakani@Sun.COM }
19510966SJordan.Brown@Sun.COM 
196*12508Samw@Sun.COM char *
smb_srm_strdup(smb_request_t * sr,const char * s)197*12508Samw@Sun.COM smb_srm_strdup(smb_request_t *sr, const char *s)
198*12508Samw@Sun.COM {
199*12508Samw@Sun.COM 	char	*p;
200*12508Samw@Sun.COM 	size_t	size;
201*12508Samw@Sun.COM 
202*12508Samw@Sun.COM 	size = strlen(s) + 1;
203*12508Samw@Sun.COM 	p = smb_srm_alloc(sr, size);
204*12508Samw@Sun.COM 	bcopy(s, p, size);
205*12508Samw@Sun.COM 	return (p);
206*12508Samw@Sun.COM }
207*12508Samw@Sun.COM 
20811963SAfshin.Ardakani@Sun.COM /*
20911963SAfshin.Ardakani@Sun.COM  * Allocate memory.
21011963SAfshin.Ardakani@Sun.COM  *
21111963SAfshin.Ardakani@Sun.COM  * sr	If not NULL, request the memory allocated must be associated with.
21211963SAfshin.Ardakani@Sun.COM  *
21311963SAfshin.Ardakani@Sun.COM  * size	Size of the meory to allocate.
21411963SAfshin.Ardakani@Sun.COM  *
21511963SAfshin.Ardakani@Sun.COM  * zero	If true the memory allocated will be zeroed out.
21611963SAfshin.Ardakani@Sun.COM  */
21711963SAfshin.Ardakani@Sun.COM static void *
smb_alloc(smb_request_t * sr,size_t size,boolean_t zero)21811963SAfshin.Ardakani@Sun.COM smb_alloc(smb_request_t *sr, size_t size, boolean_t zero)
21911963SAfshin.Ardakani@Sun.COM {
22011963SAfshin.Ardakani@Sun.COM 	smb_mem_header_t	*smh;
22110966SJordan.Brown@Sun.COM 
22211963SAfshin.Ardakani@Sun.COM 	if (zero) {
22311963SAfshin.Ardakani@Sun.COM 		smh = kmem_zalloc(size + sizeof (smb_mem_header_t), KM_SLEEP);
22411963SAfshin.Ardakani@Sun.COM 	} else {
22511963SAfshin.Ardakani@Sun.COM 		smh = kmem_alloc(size + sizeof (smb_mem_header_t), KM_SLEEP);
22611963SAfshin.Ardakani@Sun.COM 		smh->smh_sr = NULL;
22711963SAfshin.Ardakani@Sun.COM 		bzero(&smh->smh_lnd, sizeof (smh->smh_lnd));
22811963SAfshin.Ardakani@Sun.COM 	}
22911963SAfshin.Ardakani@Sun.COM 	smh->smh_sr = sr;
23011963SAfshin.Ardakani@Sun.COM 	smh->smh_size = size;
23111963SAfshin.Ardakani@Sun.COM 	smh->smh_magic = SMB_SMH_MAGIC;
23211963SAfshin.Ardakani@Sun.COM 	if (sr != NULL) {
23311963SAfshin.Ardakani@Sun.COM 		SMB_REQ_VALID(sr);
23411963SAfshin.Ardakani@Sun.COM 		list_insert_tail(&sr->sr_storage, smh);
23511963SAfshin.Ardakani@Sun.COM 	}
23611963SAfshin.Ardakani@Sun.COM 	return (++smh);
23711963SAfshin.Ardakani@Sun.COM }
23810966SJordan.Brown@Sun.COM 
23911963SAfshin.Ardakani@Sun.COM /*
24011963SAfshin.Ardakani@Sun.COM  * Free memory.
24111963SAfshin.Ardakani@Sun.COM  *
24211963SAfshin.Ardakani@Sun.COM  * sr	If not NULL, request the memory to free is associated with.
24311963SAfshin.Ardakani@Sun.COM  *
24411963SAfshin.Ardakani@Sun.COM  * ptr	Memory address
24511963SAfshin.Ardakani@Sun.COM  *
24611963SAfshin.Ardakani@Sun.COM  * zero	If true the memory is zeroed out before being freed.
24711963SAfshin.Ardakani@Sun.COM  */
24811963SAfshin.Ardakani@Sun.COM static void
smb_free(smb_request_t * sr,void * ptr,boolean_t zero)24911963SAfshin.Ardakani@Sun.COM smb_free(smb_request_t *sr, void *ptr, boolean_t zero)
25011963SAfshin.Ardakani@Sun.COM {
25111963SAfshin.Ardakani@Sun.COM 	smb_mem_header_t	*smh;
25211963SAfshin.Ardakani@Sun.COM 
25311963SAfshin.Ardakani@Sun.COM 	if (ptr != NULL) {
25411963SAfshin.Ardakani@Sun.COM 		smh = SMB_MEM2SMH(ptr);
25511963SAfshin.Ardakani@Sun.COM 		SMB_SMH_VALID(smh);
25611963SAfshin.Ardakani@Sun.COM 		ASSERT(sr == smh->smh_sr);
25711963SAfshin.Ardakani@Sun.COM 		if (sr != NULL) {
25811963SAfshin.Ardakani@Sun.COM 			SMB_REQ_VALID(sr);
25911963SAfshin.Ardakani@Sun.COM 			list_remove(&sr->sr_storage, smh);
26011963SAfshin.Ardakani@Sun.COM 		}
26111963SAfshin.Ardakani@Sun.COM 		if (zero)
26211963SAfshin.Ardakani@Sun.COM 			bzero(ptr, smh->smh_size);
26311963SAfshin.Ardakani@Sun.COM 
26411963SAfshin.Ardakani@Sun.COM 		smh->smh_magic = 0;
26511963SAfshin.Ardakani@Sun.COM 		kmem_free(smh, smh->smh_size + sizeof (smb_mem_header_t));
26611963SAfshin.Ardakani@Sun.COM 	}
26711963SAfshin.Ardakani@Sun.COM }
26810966SJordan.Brown@Sun.COM 
26911963SAfshin.Ardakani@Sun.COM /*
27011963SAfshin.Ardakani@Sun.COM  * Allocate or resize memory previously allocated.
27111963SAfshin.Ardakani@Sun.COM  *
27211963SAfshin.Ardakani@Sun.COM  * sr	If not NULL, request the memory is associated with.
27311963SAfshin.Ardakani@Sun.COM  *
27411963SAfshin.Ardakani@Sun.COM  * ptr	Memory address
27511963SAfshin.Ardakani@Sun.COM  *
27611963SAfshin.Ardakani@Sun.COM  * size	New size
27711963SAfshin.Ardakani@Sun.COM  *
27811963SAfshin.Ardakani@Sun.COM  * zero	If true zero out the extra space or the truncated space.
27911963SAfshin.Ardakani@Sun.COM  */
28011963SAfshin.Ardakani@Sun.COM static void *
smb_realloc(smb_request_t * sr,void * ptr,size_t size,boolean_t zero)28111963SAfshin.Ardakani@Sun.COM smb_realloc(smb_request_t *sr, void *ptr, size_t size, boolean_t zero)
28211963SAfshin.Ardakani@Sun.COM {
28311963SAfshin.Ardakani@Sun.COM 	smb_mem_header_t	*smh;
28411963SAfshin.Ardakani@Sun.COM 	void			*new_ptr;
28511963SAfshin.Ardakani@Sun.COM 
28611963SAfshin.Ardakani@Sun.COM 	if (ptr == NULL)
28711963SAfshin.Ardakani@Sun.COM 		return (smb_alloc(sr, size, zero));
28811963SAfshin.Ardakani@Sun.COM 
28911963SAfshin.Ardakani@Sun.COM 	smh = SMB_MEM2SMH(ptr);
29011963SAfshin.Ardakani@Sun.COM 	SMB_SMH_VALID(smh);
29111963SAfshin.Ardakani@Sun.COM 	ASSERT(sr == smh->smh_sr);
29211963SAfshin.Ardakani@Sun.COM 
29311963SAfshin.Ardakani@Sun.COM 	if (size == 0) {
29411963SAfshin.Ardakani@Sun.COM 		smb_free(sr, ptr, zero);
29511963SAfshin.Ardakani@Sun.COM 		return (NULL);
29611963SAfshin.Ardakani@Sun.COM 	}
29711963SAfshin.Ardakani@Sun.COM 	if (smh->smh_size >= size) {
29811963SAfshin.Ardakani@Sun.COM 		if ((zero) & (smh->smh_size > size))
29911963SAfshin.Ardakani@Sun.COM 			bzero((caddr_t)ptr + size, smh->smh_size - size);
30011963SAfshin.Ardakani@Sun.COM 		return (ptr);
30111963SAfshin.Ardakani@Sun.COM 	}
30211963SAfshin.Ardakani@Sun.COM 	new_ptr = smb_alloc(sr, size, B_FALSE);
30311963SAfshin.Ardakani@Sun.COM 	bcopy(ptr, new_ptr, smh->smh_size);
30411963SAfshin.Ardakani@Sun.COM 	if (zero)
30511963SAfshin.Ardakani@Sun.COM 		bzero((caddr_t)new_ptr + smh->smh_size, size - smh->smh_size);
30611963SAfshin.Ardakani@Sun.COM 
30711963SAfshin.Ardakani@Sun.COM 	smb_free(sr, ptr, zero);
30811963SAfshin.Ardakani@Sun.COM 	return (new_ptr);
30910966SJordan.Brown@Sun.COM }
310