xref: /titanic_52/usr/src/cmd/nscd/nscd_intaddr.c (revision cb5caa98562cf06753163f558cbcfe30b8f4673a)
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