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