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 *
_nscd_create_int_addrDB()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
_nscd_add_int_addr(void * ptr,int type,nscd_seq_num_t seq_num)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 *
_nscd_is_int_addr(void * ptr,nscd_seq_num_t seq_num)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
_nscd_del_int_addr(void * ptr,nscd_seq_num_t seq_num)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
_nscd_destroy_int_addrDB()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