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