1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/sunddi.h>
28 #include <sys/kmem.h>
29 #include <sys/sysmacros.h>
30 #include <smbsrv/smb_kproto.h>
31 #include <smbsrv/alloc.h>
32 
33 #define	MEM_HDR_SIZE	8
34 static uint32_t smb_memsize(void *);
35 
36 void *
37 smb_malloc(uint32_t size)
38 {
39 	uint32_t	*hdr;
40 	uint8_t		*p;
41 
42 	size += MEM_HDR_SIZE;
43 	hdr = kmem_zalloc(size, KM_SLEEP);
44 	*hdr = size;
45 
46 	p = (uint8_t *)hdr;
47 	p += MEM_HDR_SIZE;
48 	return (p);
49 }
50 
51 char *
52 smb_strdup(const char *ptr)
53 {
54 	char	*p;
55 	size_t	size;
56 
57 	size = strlen(ptr) + 1;
58 	p = smb_malloc(size);
59 	(void) memcpy(p, ptr, size);
60 	return (p);
61 }
62 
63 static uint32_t
64 smb_memsize(void *ptr)
65 {
66 	uint32_t	*p;
67 
68 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
69 	p = (uint32_t *)((uint8_t *)ptr - MEM_HDR_SIZE);
70 
71 	return (*p);
72 }
73 
74 void *
75 smb_realloc(void *ptr, uint32_t size)
76 {
77 	void		*new_ptr;
78 	uint32_t	current_size;
79 
80 
81 	if (ptr == NULL)
82 		return (smb_malloc(size));
83 
84 	if (size == 0) {
85 		smb_mfree(ptr);
86 		return (NULL);
87 	}
88 
89 	current_size = smb_memsize(ptr) - MEM_HDR_SIZE;
90 	if (size <= current_size)
91 		return (ptr);
92 
93 	new_ptr = smb_malloc(size);
94 	(void) memcpy(new_ptr, ptr, current_size);
95 	smb_mfree(ptr);
96 
97 	return (new_ptr);
98 }
99 
100 void
101 smb_mfree(void *ptr)
102 {
103 	uint8_t	*p;
104 
105 	if (ptr == NULL)
106 		return;
107 
108 	p = (uint8_t *)ptr - MEM_HDR_SIZE;
109 	/*LINTED E_BAD_PTR_CAST_ALIGN*/
110 	kmem_free(p, *(uint32_t *)p);
111 }
112 
113 /*
114  * Initialize the list for request-specific temporary storage.
115  */
116 void
117 smb_srm_init(smb_request_t *sr)
118 {
119 	list_create(&sr->sr_storage, sizeof (smb_srm_t),
120 	    offsetof(smb_srm_t, srm_lnd));
121 }
122 
123 /*
124  * Free everything on the request-specific temporary storage list
125  * and destroy the list.
126  */
127 void
128 smb_srm_fini(smb_request_t *sr)
129 {
130 	smb_srm_t	*srm;
131 
132 	while ((srm = list_head(&sr->sr_storage)) != NULL) {
133 		list_remove(&sr->sr_storage, srm);
134 		smb_mfree(srm);
135 	}
136 
137 	list_destroy(&sr->sr_storage);
138 }
139 
140 /*
141  * Allocate memory and associate it with the specified request.
142  * Memory allocated here can only be used for the duration of
143  * this request; it will be freed automatically on completion
144  * of the request
145  */
146 void *
147 smb_srm_alloc(smb_request_t *sr, size_t size)
148 {
149 	smb_srm_t	*srm;
150 
151 	size += sizeof (smb_srm_t);
152 	srm = smb_malloc(size);
153 	srm->srm_size = size;
154 	srm->srm_sr = sr;
155 	list_insert_tail(&sr->sr_storage, srm);
156 
157 	/*
158 	 * The memory allocated for use be the caller is
159 	 * immediately after our storage context area.
160 	 */
161 	return (void *)(srm + 1);
162 }
163 
164 /*
165  * Allocate or resize memory previously allocated for the specified
166  * request.
167  */
168 void *
169 smb_srm_realloc(smb_request_t *sr, void *p, size_t size)
170 {
171 	smb_srm_t 	*old_srm = (smb_srm_t *)p;
172 	smb_srm_t 	*new_srm;
173 
174 	if (old_srm == NULL)
175 		return (smb_srm_alloc(sr, size));
176 
177 	old_srm--;
178 	list_remove(&sr->sr_storage, old_srm);
179 
180 	size += sizeof (smb_srm_t);
181 	new_srm = smb_realloc(old_srm, size);
182 	new_srm->srm_size = smb_memsize(new_srm);
183 	new_srm->srm_sr = sr;
184 	list_insert_tail(&sr->sr_storage, new_srm);
185 
186 	/*
187 	 * The memory allocated for use be the caller is
188 	 * immediately after our storage context area.
189 	 */
190 	return (void *)(new_srm + 1);
191 }
192