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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdlib.h> 29 #include <stdio.h> 30 #include "nscd_db.h" 31 #include "nscd_log.h" 32 33 static rwlock_t addrDB_rwlock = DEFAULTRWLOCK; 34 static nscd_db_t *addrDB = NULL; 35 36 /* 37 * internal structure representing a nscd internal address 38 */ 39 typedef struct nscd_int_addr { 40 int to_delete; /* no longer valid */ 41 int type; 42 void *ptr; 43 nscd_seq_num_t seq_num; 44 rwlock_t rwlock; /* used to serialize get and destroy */ 45 } nscd_int_addr_t; 46 47 /* 48 * FUNCTION: _nscd_create_int_addrDB 49 * 50 * Create the internal address database to keep track of the 51 * memory allocated by _nscd_alloc. 52 */ 53 void * 54 _nscd_create_int_addrDB() 55 { 56 57 nscd_db_t *ret; 58 char *me = "_nscd_create_int_addrDB"; 59 60 _NSCD_LOG(NSCD_LOG_INT_ADDR | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) 61 (me, "initializing the internal address database\n"); 62 63 (void) rw_wrlock(&addrDB_rwlock); 64 65 if (addrDB != NULL) { 66 (void) rw_unlock(&addrDB_rwlock); 67 return (addrDB); 68 } 69 70 ret = _nscd_alloc_db(NSCD_DB_SIZE_LARGE); 71 72 if (ret != NULL) 73 addrDB = ret; 74 75 (void) rw_unlock(&addrDB_rwlock); 76 77 return (ret); 78 } 79 80 /* 81 * FUNCTION: _nscd_add_int_addr 82 * 83 * Add an address of 'type' to the internal address database. 84 */ 85 nscd_rc_t 86 _nscd_add_int_addr( 87 void *ptr, 88 int type, 89 nscd_seq_num_t seq_num) 90 { 91 int size; 92 char buf[2 * sizeof (ptr) + 1]; 93 nscd_db_entry_t *db_entry; 94 nscd_int_addr_t *int_addr; 95 96 if (ptr == NULL) 97 return (NSCD_INVALID_ARGUMENT); 98 99 (void) snprintf(buf, sizeof (buf), "%p", ptr); 100 101 size = sizeof (*int_addr); 102 103 db_entry = _nscd_alloc_db_entry(NSCD_DATA_ADDR, 104 (const char *)buf, size, 1, 1); 105 if (db_entry == NULL) 106 return (NSCD_NO_MEMORY); 107 108 int_addr = (nscd_int_addr_t *)*(db_entry->data_array); 109 int_addr->ptr = ptr; 110 int_addr->type = type; 111 int_addr->seq_num = seq_num; 112 (void) rwlock_init(&int_addr->rwlock, USYNC_THREAD, NULL); 113 114 (void) rw_wrlock(&addrDB_rwlock); 115 (void) _nscd_add_db_entry(addrDB, buf, db_entry, 116 NSCD_ADD_DB_ENTRY_FIRST); 117 (void) rw_unlock(&addrDB_rwlock); 118 119 return (NSCD_SUCCESS); 120 } 121 122 /* 123 * FUNCTION: _nscd_is_int_addr 124 * 125 * Check to see if an address can be found in the internal 126 * address database, if so, obtain a reader lock on the 127 * associated rw_lock. The caller needs to unlock it when 128 * done using the data. 129 */ 130 rwlock_t * 131 _nscd_is_int_addr( 132 void *ptr, 133 nscd_seq_num_t seq_num) 134 { 135 char *me = "_nscd_is_int_addr"; 136 char ptrstr[1 + 2 * sizeof (ptr)]; 137 rwlock_t *addr_rwlock; 138 const nscd_db_entry_t *db_entry; 139 140 if (ptr == NULL) 141 return (NULL); 142 143 (void) snprintf(ptrstr, sizeof (ptrstr), "%p", ptr); 144 145 (void) rw_rdlock(&addrDB_rwlock); 146 147 db_entry = _nscd_get_db_entry(addrDB, NSCD_DATA_ADDR, 148 (const char *)ptrstr, NSCD_GET_FIRST_DB_ENTRY, 0); 149 150 if (db_entry != NULL) { 151 nscd_int_addr_t *int_addr; 152 153 int_addr = (nscd_int_addr_t *)*(db_entry->data_array); 154 addr_rwlock = &int_addr->rwlock; 155 (void) rw_rdlock(addr_rwlock); 156 157 /* 158 * If the data is marked as to be deleted 159 * or the sequence number does not match, 160 * return NULL. 161 */ 162 if (int_addr->to_delete == 1 || 163 int_addr->seq_num != seq_num) { 164 (void) rw_unlock(addr_rwlock); 165 addr_rwlock = NULL; 166 } 167 168 _NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_DEBUG) 169 (me, "found %p, seq# = %lld\n", ptr, int_addr->seq_num); 170 } else 171 addr_rwlock = NULL; 172 173 (void) rw_unlock(&addrDB_rwlock); 174 175 return (addr_rwlock); 176 } 177 178 /* 179 * FUNCTION: _nscd_del_int_addr 180 * 181 * Delete an address from the internal address database. 182 */ 183 void 184 _nscd_del_int_addr( 185 void *ptr, 186 nscd_seq_num_t seq_num) 187 { 188 char *me = "_nscd_del_int_addr"; 189 char ptrstr[1 + 2 * sizeof (ptr)]; 190 rwlock_t *addr_rwlock; 191 nscd_int_addr_t *int_addr; 192 const nscd_db_entry_t *db_entry; 193 194 if (ptr == NULL) 195 return; 196 197 _NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_DEBUG) 198 (me, "deleting int addr %p (%d)\n", ptr, seq_num); 199 (void) snprintf(ptrstr, sizeof (ptrstr), "%p", ptr); 200 201 (void) rw_rdlock(&addrDB_rwlock); 202 /* 203 * first find the db entry and make sure that 204 * no one is currently locking it. i.e., 205 * no one is waiting to use the same address. 206 * If it is locked, rw_wrlock() will not return 207 * until it is unlocked. 208 */ 209 db_entry = _nscd_get_db_entry(addrDB, 210 NSCD_DATA_ADDR, 211 (const char *)ptrstr, 212 NSCD_GET_FIRST_DB_ENTRY, 0); 213 if (db_entry != NULL) { 214 int_addr = (nscd_int_addr_t *)*(db_entry->data_array); 215 addr_rwlock = &int_addr->rwlock; 216 (void) rw_wrlock(addr_rwlock); 217 } else { 218 (void) rw_unlock(&addrDB_rwlock); 219 return; 220 } 221 (void) rw_unlock(&addrDB_rwlock); 222 223 /* 224 * delete the db entry if the sequence numbers match 225 */ 226 if (int_addr->seq_num == seq_num) { 227 (void) rw_wrlock(&addrDB_rwlock); 228 (void) _nscd_delete_db_entry(addrDB, 229 NSCD_DATA_ADDR, 230 (const char *)ptrstr, 231 NSCD_DEL_FIRST_DB_ENTRY, 0); 232 (void) rw_unlock(&addrDB_rwlock); 233 } 234 } 235 236 /* 237 * FUNCTION: _nscd_destroy_int_addrDB 238 * 239 * Destroy the internal address database. 240 */ 241 void 242 _nscd_destroy_int_addrDB() 243 { 244 (void) rw_wrlock(&addrDB_rwlock); 245 _nscd_free_db(addrDB); 246 addrDB = NULL; 247 (void) rw_unlock(&addrDB_rwlock); 248 } 249