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