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