xref: /titanic_54/usr/src/cmd/nscd/nscd_nswstate.c (revision d2ba247c74bd2c38b10920c89050bd94245b8589)
1cb5caa98Sdjl /*
2cb5caa98Sdjl  * CDDL HEADER START
3cb5caa98Sdjl  *
4cb5caa98Sdjl  * The contents of this file are subject to the terms of the
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * You may not use this file except in compliance with the License.
7cb5caa98Sdjl  *
8cb5caa98Sdjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9cb5caa98Sdjl  * or http://www.opensolaris.org/os/licensing.
10cb5caa98Sdjl  * See the License for the specific language governing permissions
11cb5caa98Sdjl  * and limitations under the License.
12cb5caa98Sdjl  *
13cb5caa98Sdjl  * When distributing Covered Code, include this CDDL HEADER in each
14cb5caa98Sdjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15cb5caa98Sdjl  * If applicable, add the following below this CDDL HEADER, with the
16cb5caa98Sdjl  * fields enclosed by brackets "[]" replaced with your own identifying
17cb5caa98Sdjl  * information: Portions Copyright [yyyy] [name of copyright owner]
18cb5caa98Sdjl  *
19cb5caa98Sdjl  * CDDL HEADER END
20cb5caa98Sdjl  */
21cb5caa98Sdjl /*
22*d2ba247cSmichen  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23cb5caa98Sdjl  * Use is subject to license terms.
24cb5caa98Sdjl  */
25cb5caa98Sdjl 
26cb5caa98Sdjl #pragma ident	"%Z%%M%	%I%	%E% SMI"
27cb5caa98Sdjl 
28cb5caa98Sdjl #include <stdio.h>
29cb5caa98Sdjl #include <stdlib.h>
30cb5caa98Sdjl #include <assert.h>
31cb5caa98Sdjl #include <string.h>
32cb5caa98Sdjl #include "nscd_switch.h"
33cb5caa98Sdjl #include "nscd_log.h"
34cb5caa98Sdjl 
35cb5caa98Sdjl /*
36cb5caa98Sdjl  * nscd_nsw_state_t list for each nss database. Protected
37cb5caa98Sdjl  * by the readers/writer lock nscd_nsw_state_base_lock.
38cb5caa98Sdjl  */
39cb5caa98Sdjl nscd_nsw_state_base_t **nscd_nsw_state_base;
40cb5caa98Sdjl static rwlock_t nscd_nsw_state_base_lock = DEFAULTRWLOCK;
41cb5caa98Sdjl 
42cb5caa98Sdjl static void
43cb5caa98Sdjl _nscd_free_nsw_state(
44cb5caa98Sdjl 	nscd_nsw_state_t	*s)
45cb5caa98Sdjl {
46cb5caa98Sdjl 
47cb5caa98Sdjl 	int			i;
48cb5caa98Sdjl 	char			*me = "_nscd_free_nsw_state";
49cb5caa98Sdjl 
50cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
51cb5caa98Sdjl 	(me, "freeing nsw state = %p\n", s);
52cb5caa98Sdjl 
53cb5caa98Sdjl 	if (s == NULL)
54cb5caa98Sdjl 		return;
55cb5caa98Sdjl 
56cb5caa98Sdjl 	if (s->nsw_cfg_p != NULL)
57cb5caa98Sdjl 		/*
58cb5caa98Sdjl 		 * an nsw state without base does not reference
59cb5caa98Sdjl 		 * count the nsw config data (ie not using a
60cb5caa98Sdjl 		 * shared one), so the one created for it should
61cb5caa98Sdjl 		 * be freed
62cb5caa98Sdjl 		 */
63cb5caa98Sdjl 		if ((*s->nsw_cfg_p)->nobase != 1)
64cb5caa98Sdjl 			_nscd_release((nscd_acc_data_t *)s->nsw_cfg_p);
65cb5caa98Sdjl 		else
663d047983Smichen 			(void) _nscd_set((nscd_acc_data_t *)s->nsw_cfg_p, NULL);
67cb5caa98Sdjl 
68cb5caa98Sdjl 	if (s->be_db_pp != NULL) {
69cb5caa98Sdjl 		for (i = 0; i < s->max_src; i++) {
70cb5caa98Sdjl 			if (s->be_db_pp[i] == NULL)
71cb5caa98Sdjl 				continue;
72cb5caa98Sdjl 			_nscd_release((nscd_acc_data_t *)s->be_db_pp[i]);
73cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
74cb5caa98Sdjl 			(me, "release db be ptr %p\n", s->be_db_pp[i]);
75cb5caa98Sdjl 		}
76cb5caa98Sdjl 		free(s->be_db_pp);
77cb5caa98Sdjl 	}
78cb5caa98Sdjl 
79cb5caa98Sdjl 	if (s->be != NULL) {
80cb5caa98Sdjl 		for (i = 0; i < s->max_src; i++) {
81cb5caa98Sdjl 			if (s->be[i] == NULL)
82cb5caa98Sdjl 				continue;
83cb5caa98Sdjl 			if (s->getent == 1)
84cb5caa98Sdjl 				(void) NSS_INVOKE_DBOP(s->be[i],
85cb5caa98Sdjl 				    NSS_DBOP_ENDENT, 0);
86cb5caa98Sdjl 			(void) NSS_INVOKE_DBOP(s->be[i],
87cb5caa98Sdjl 			    NSS_DBOP_DESTRUCTOR, 0);
88cb5caa98Sdjl 		}
89cb5caa98Sdjl 		free(s->be);
90cb5caa98Sdjl 	}
91cb5caa98Sdjl 
92bf1e3beeSmichen 	if (s->be_constr != NULL)
93bf1e3beeSmichen 		free(s->be_constr);
94bf1e3beeSmichen 
95*d2ba247cSmichen 	if (s->be_version_p != NULL)
96*d2ba247cSmichen 		free(s->be_version_p);
97*d2ba247cSmichen 
98cb5caa98Sdjl 	s->base = NULL;
99cb5caa98Sdjl 
100cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
101cb5caa98Sdjl 	(me, "nsw state %p freed \n", s);
102cb5caa98Sdjl 
103cb5caa98Sdjl 	free(s);
104cb5caa98Sdjl }
105cb5caa98Sdjl 
106cb5caa98Sdjl static void
107cb5caa98Sdjl _nscd_free_nsw_state_base(
108cb5caa98Sdjl 	nscd_acc_data_t		*data)
109cb5caa98Sdjl {
110cb5caa98Sdjl 	nscd_nsw_state_base_t	*base = (nscd_nsw_state_base_t *)data;
111cb5caa98Sdjl 	nscd_nsw_state_t	*s, *ts;
112cb5caa98Sdjl 	int			i;
113cb5caa98Sdjl 	char			*me = "_nscd_free_nsw_state_base";
114cb5caa98Sdjl 
115cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
116cb5caa98Sdjl 	(me, "freeing db state base %p\n", base);
117cb5caa98Sdjl 
118cb5caa98Sdjl 	if (base == NULL)
119cb5caa98Sdjl 		return;
120cb5caa98Sdjl 
121cb5caa98Sdjl 	for (i = 0; i < 2; i++) {
122cb5caa98Sdjl 		if (i == 1)
123cb5caa98Sdjl 			s = base->nsw_state.first;
124cb5caa98Sdjl 		else
125cb5caa98Sdjl 			s = base->nsw_state_thr.first;
126cb5caa98Sdjl 
127cb5caa98Sdjl 		while (s != NULL) {
128cb5caa98Sdjl 			ts = s->next;
129cb5caa98Sdjl 			_nscd_free_nsw_state(s);
130cb5caa98Sdjl 			s = ts;
131cb5caa98Sdjl 		}
132cb5caa98Sdjl 	}
133cb5caa98Sdjl 
134cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
135cb5caa98Sdjl 	(me, "nsw state base %p freed \n", base);
136cb5caa98Sdjl }
137cb5caa98Sdjl 
138cb5caa98Sdjl void
139cb5caa98Sdjl _nscd_free_all_nsw_state_base()
140cb5caa98Sdjl {
141cb5caa98Sdjl 	nscd_nsw_state_base_t	*base;
142cb5caa98Sdjl 	int			i;
143cb5caa98Sdjl 	char			*me = "_nscd_free_all_nsw_state_base";
144cb5caa98Sdjl 
145cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
146cb5caa98Sdjl 	(me, "freeing all db state base\n");
147cb5caa98Sdjl 
148cb5caa98Sdjl 	(void) rw_wrlock(&nscd_nsw_state_base_lock);
149cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_DB; i++) {
150cb5caa98Sdjl 
151cb5caa98Sdjl 		base = nscd_nsw_state_base[i];
152cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
153cb5caa98Sdjl 		    NSCD_LOG_LEVEL_DEBUG)
154cb5caa98Sdjl 		(me, "freeing db state base (%d) %p \n", i, base);
155cb5caa98Sdjl 
156cb5caa98Sdjl 		if (base == NULL)
157cb5caa98Sdjl 			continue;
158cb5caa98Sdjl 
159cb5caa98Sdjl 		nscd_nsw_state_base[i] = (nscd_nsw_state_base_t *)
160cb5caa98Sdjl 		    _nscd_set((nscd_acc_data_t *)base, NULL);
161cb5caa98Sdjl 	}
162cb5caa98Sdjl 	(void) rw_unlock(&nscd_nsw_state_base_lock);
163cb5caa98Sdjl }
164cb5caa98Sdjl 
165cb5caa98Sdjl static nscd_nsw_state_t *
166cb5caa98Sdjl _nscd_create_nsw_state(
167cb5caa98Sdjl 	nscd_nsw_params_t	*params)
168cb5caa98Sdjl {
169cb5caa98Sdjl 	nscd_nsw_state_t	*s;
170cb5caa98Sdjl 	nscd_nsw_config_t	*nsw_cfg;
171cb5caa98Sdjl 	nscd_db_t		**be_db_p, *be_db;
172cb5caa98Sdjl 	int			i, nobe = 1;
173cb5caa98Sdjl 	char			*me = "_nscd_create_nsw_state";
174cb5caa98Sdjl 
175cb5caa98Sdjl 
176cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
177cb5caa98Sdjl 	(me, "creating nsw state...\n");
178cb5caa98Sdjl 
179cb5caa98Sdjl 	s = calloc(1, sizeof (nscd_nsw_state_t));
180cb5caa98Sdjl 	if (s == NULL) {
181cb5caa98Sdjl 		if ((*s->nsw_cfg_p)->nobase  != 1)
182cb5caa98Sdjl 			_nscd_release((nscd_acc_data_t *)params->nswcfg);
183cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
184cb5caa98Sdjl 		(me, "not able to allocate a nsw state\n");
185cb5caa98Sdjl 		return (NULL);
186cb5caa98Sdjl 	} else
187cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
188cb5caa98Sdjl 		(me, "nsw state %p allocated\n", s);
189cb5caa98Sdjl 
190cb5caa98Sdjl 	s->dbi = params->dbi;
191cb5caa98Sdjl 	s->next = NULL;
192cb5caa98Sdjl 
193cb5caa98Sdjl 	nsw_cfg = *params->nswcfg;
194cb5caa98Sdjl 
195cb5caa98Sdjl 	s->nsw_cfg_p = params->nswcfg;
196cb5caa98Sdjl 	s->config = nsw_cfg->nsw_config;
197cb5caa98Sdjl 	s->max_src = nsw_cfg->max_src;
198cb5caa98Sdjl 	s->p = params->p;
199cb5caa98Sdjl 
200cb5caa98Sdjl 	s->be = calloc(s->max_src, sizeof (nss_backend_t **));
201cb5caa98Sdjl 	if (s->be == NULL) {
202cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
203cb5caa98Sdjl 		(me, "not able to allocate s->be\n");
204cb5caa98Sdjl 
205cb5caa98Sdjl 		_nscd_free_nsw_state(s);
206cb5caa98Sdjl 		return (NULL);
207cb5caa98Sdjl 	} else {
208cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
209cb5caa98Sdjl 		(me, "db be array %p allocated\n", s->be);
210cb5caa98Sdjl 	}
211cb5caa98Sdjl 
212bf1e3beeSmichen 	s->be_constr = (nss_backend_constr_t *)calloc(s->max_src,
213bf1e3beeSmichen 	    sizeof (nss_backend_constr_t));
214bf1e3beeSmichen 	if (s->be_constr == NULL) {
215bf1e3beeSmichen 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
216bf1e3beeSmichen 		(me, "not able to allocate s->be_constr\n");
217bf1e3beeSmichen 
218bf1e3beeSmichen 		_nscd_free_nsw_state(s);
219bf1e3beeSmichen 		return (NULL);
220bf1e3beeSmichen 	} else {
221bf1e3beeSmichen 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
222bf1e3beeSmichen 		(me, "db be constructor array %p allocated\n", s->be_constr);
223bf1e3beeSmichen 	}
224bf1e3beeSmichen 
225*d2ba247cSmichen 	s->be_version_p = (void **)calloc(s->max_src, sizeof (void *));
226*d2ba247cSmichen 	if (s->be_version_p == NULL) {
227*d2ba247cSmichen 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
228*d2ba247cSmichen 		(me, "not able to allocate s->be_version_p\n");
229*d2ba247cSmichen 
230*d2ba247cSmichen 		_nscd_free_nsw_state(s);
231*d2ba247cSmichen 		return (NULL);
232*d2ba247cSmichen 	} else {
233*d2ba247cSmichen 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
234*d2ba247cSmichen 		(me, "db be version ptr array %p allocated\n", s->be_version_p);
235*d2ba247cSmichen 	}
236*d2ba247cSmichen 
237cb5caa98Sdjl 	s->be_db_pp = calloc(s->max_src, sizeof (nscd_db_t ***));
238cb5caa98Sdjl 	if (s->be_db_pp == NULL) {
239cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
240cb5caa98Sdjl 		(me, "not able to allocate s->be_db_pp\n");
241cb5caa98Sdjl 		_nscd_free_nsw_state(s);
242cb5caa98Sdjl 		return (NULL);
243cb5caa98Sdjl 	} else {
244cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
245cb5caa98Sdjl 		(me, "be_db_pp array %p allocated\n", s->be_db_pp);
246cb5caa98Sdjl 	}
247cb5caa98Sdjl 
248cb5caa98Sdjl 	/* create the source:database backends */
249cb5caa98Sdjl 	for (i = 0;  i < s->max_src;  i++) {
250cb5caa98Sdjl 		nss_backend_t		*be;
251cb5caa98Sdjl 		int			srci;
252cb5caa98Sdjl 		char			*srcn;
253cb5caa98Sdjl 		const char		*dbn;
254cb5caa98Sdjl 		struct __nsw_lookup_v1	*lkp;
255cb5caa98Sdjl 		const nscd_db_entry_t	*dbe;
256cb5caa98Sdjl 		nscd_be_info_t		*be_info;
257cb5caa98Sdjl 
258cb5caa98Sdjl 		if (i == 0)
259cb5caa98Sdjl 			lkp = s->config->lookups;
260cb5caa98Sdjl 		else
261cb5caa98Sdjl 			lkp = lkp->next;
262cb5caa98Sdjl 		if (lkp == NULL) {
263cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
264cb5caa98Sdjl 			(me, "error: lkp is NULL\n");
265cb5caa98Sdjl 			_nscd_free_nsw_state(s);
266cb5caa98Sdjl 			return (NULL);
267cb5caa98Sdjl 		}
268cb5caa98Sdjl 
269cb5caa98Sdjl 		srci = nsw_cfg->src_idx[i];
270cb5caa98Sdjl 		srcn = lkp->service_name;
271cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
272cb5caa98Sdjl 		(me, "source name = %s, index = %d\n", srcn, srci);
273cb5caa98Sdjl 
274cb5caa98Sdjl 		be_db_p = (nscd_db_t **)_nscd_get(
275cb5caa98Sdjl 		    (nscd_acc_data_t *)nscd_src_backend_db[srci]);
276cb5caa98Sdjl 		if (be_db_p == NULL) {
277cb5caa98Sdjl 			_nscd_free_nsw_state(s);
278cb5caa98Sdjl 			return (NULL);
279cb5caa98Sdjl 		}
280cb5caa98Sdjl 		be_db = *be_db_p;
281cb5caa98Sdjl 		s->be_db_pp[i] = be_db_p;
282cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
283cb5caa98Sdjl 		(me, "be db ptr array %p referenced\n", be_db_p);
284cb5caa98Sdjl 
285cb5caa98Sdjl 		be_info = NULL;
286cb5caa98Sdjl 		be = NULL;
287cb5caa98Sdjl 		dbn = params->p.name;
288cb5caa98Sdjl 		dbe = _nscd_get_db_entry(be_db, NSCD_DATA_BACKEND_INFO,
289cb5caa98Sdjl 		    (const char *)dbn, NSCD_GET_FIRST_DB_ENTRY, 0);
290cb5caa98Sdjl 		if (dbe != NULL)
291cb5caa98Sdjl 			be_info = (nscd_be_info_t *)*(dbe->data_array);
292cb5caa98Sdjl 
293cb5caa98Sdjl 		if (be_info == NULL || be_info->be_constr == NULL) {
294cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
295cb5caa98Sdjl 			(me, "no backend info or be_constr is NULL "
296cb5caa98Sdjl 			    "for <%s : %s>\n", NSCD_NSW_SRC_NAME(srci),
297cb5caa98Sdjl 			    dbn);
298bf1e3beeSmichen 		} else {
299bf1e3beeSmichen 			s->be_constr[i] = be_info->be_constr;
300cb5caa98Sdjl 			be = (be_info->be_constr)(dbn,
301cb5caa98Sdjl 			    NSCD_NSW_SRC_NAME(srci), 0);
302bf1e3beeSmichen 			if (be == NULL)
303bf1e3beeSmichen 				s->recheck_be = nscd_true;
304bf1e3beeSmichen 		}
305cb5caa98Sdjl 
306cb5caa98Sdjl 		if (be == NULL) {
307cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
308cb5caa98Sdjl 			(me, "not able to init be for <%s : %s>\n",
309cb5caa98Sdjl 			    NSCD_NSW_SRC_NAME(srci), dbn);
310cb5caa98Sdjl 
311cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
312cb5caa98Sdjl 			(me, "releasing db be ptr %p\n", be_db_p);
313cb5caa98Sdjl 
314cb5caa98Sdjl 			_nscd_release((nscd_acc_data_t *)be_db_p);
315cb5caa98Sdjl 			s->be_db_pp[i] = NULL;
316cb5caa98Sdjl 
317cb5caa98Sdjl 			continue;
318cb5caa98Sdjl 		}
319cb5caa98Sdjl 
320cb5caa98Sdjl 		s->be[i] = be;
321*d2ba247cSmichen 		s->be_version_p[i] = be_info->be_version;
322*d2ba247cSmichen 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
323*d2ba247cSmichen 		(me, "backend version is %p\n", be_info->be_version);
324cb5caa98Sdjl 		nobe = 0;
325cb5caa98Sdjl 	}
326cb5caa98Sdjl 
327cb5caa98Sdjl 	if (nobe == 1) {
328cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
329cb5caa98Sdjl 		(me, "NO backend found, returning NULL\n");
330cb5caa98Sdjl 
331cb5caa98Sdjl 		_nscd_free_nsw_state(s);
332cb5caa98Sdjl 		return (NULL);
333cb5caa98Sdjl 	}
334cb5caa98Sdjl 
335cb5caa98Sdjl 	return (s);
336cb5caa98Sdjl }
337cb5caa98Sdjl 
338bf1e3beeSmichen /*
339bf1e3beeSmichen  * Try to initialize the backend instances one more time
340bf1e3beeSmichen  * in case the dependencies the backend libraries depend
341bf1e3beeSmichen  * on are now available
342bf1e3beeSmichen  */
343bf1e3beeSmichen static void
344bf1e3beeSmichen check_be_array(
345bf1e3beeSmichen 	nscd_nsw_state_t	*s)
346bf1e3beeSmichen {
347bf1e3beeSmichen 	int			i;
348bf1e3beeSmichen 	char			*dbn;
349bf1e3beeSmichen 	char			*srcn;
350bf1e3beeSmichen 	struct __nsw_lookup_v1	*lkp;
351bf1e3beeSmichen 
352bf1e3beeSmichen 	dbn = NSCD_NSW_DB_NAME(s->dbi);
353bf1e3beeSmichen 
354bf1e3beeSmichen 	s->recheck_be = nscd_false;
355bf1e3beeSmichen 	for (i = 0;  i < s->max_src;  i++) {
356bf1e3beeSmichen 
357bf1e3beeSmichen 		if (i == 0)
358bf1e3beeSmichen 			lkp = s->config->lookups;
359bf1e3beeSmichen 		else
360bf1e3beeSmichen 			lkp = lkp->next;
361bf1e3beeSmichen 		if (lkp == NULL)
362bf1e3beeSmichen 			return;
363bf1e3beeSmichen 
364bf1e3beeSmichen 		srcn = lkp->service_name;
365bf1e3beeSmichen 
366bf1e3beeSmichen 		/*
367bf1e3beeSmichen 		 * it is possible that 's->be[i]' could not be
368bf1e3beeSmichen 		 * initialized earlier due to a dependency not
369bf1e3beeSmichen 		 * yet available (e.g., nis on domain name),
370bf1e3beeSmichen 		 * try to initialize one more time
371bf1e3beeSmichen 		 */
372bf1e3beeSmichen 		if (s->be[i] == NULL && s->be_constr[i] != NULL) {
373bf1e3beeSmichen 			s->be[i] = (s->be_constr[i])(dbn, srcn, 0);
374bf1e3beeSmichen 			if (s->be[i] == NULL)
375bf1e3beeSmichen 				s->recheck_be = nscd_true;
376bf1e3beeSmichen 		}
377bf1e3beeSmichen 	}
378bf1e3beeSmichen }
379bf1e3beeSmichen 
380cb5caa98Sdjl static nscd_rc_t
381cb5caa98Sdjl _get_nsw_state_int(
382cb5caa98Sdjl 	nss_db_root_t		*rootp,
383cb5caa98Sdjl 	nscd_nsw_params_t	*params,
384cb5caa98Sdjl 	thread_t		*tid)
385cb5caa98Sdjl {
386cb5caa98Sdjl 
387cb5caa98Sdjl 	nscd_nsw_state_t	*ret = NULL;
388cb5caa98Sdjl 	nscd_nsw_config_t	**nswcfg;
389cb5caa98Sdjl 	nscd_nsw_state_base_t	*base;
390cb5caa98Sdjl 	nscd_state_ctrl_t	*ctrl_p;
391cb5caa98Sdjl 	int			thread_only = 0, wait_cond = 0;
392cb5caa98Sdjl 	char			*me = "_get_nsw_state_int";
393cb5caa98Sdjl 	int			dbi;
394cb5caa98Sdjl 	nscd_rc_t		rc;
395cb5caa98Sdjl 
396cb5caa98Sdjl 	dbi = params->dbi;
397cb5caa98Sdjl 
398cb5caa98Sdjl 	/*
399cb5caa98Sdjl 	 * no nsw state will be reused, if asked to use
400cb5caa98Sdjl 	 * default config. So create the new structures
401cb5caa98Sdjl 	 * used by the switch engine and the new nsw state
402cb5caa98Sdjl 	 */
403cb5caa98Sdjl 	if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
404ad0e80f7Smichen 		rc = _nscd_create_sw_struct(dbi, -1, (char *)params->p.name,
405cb5caa98Sdjl 		    (char *)params->p.default_config, NULL, params);
406cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
407cb5caa98Sdjl 			return (rc);
408cb5caa98Sdjl 
409cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
410cb5caa98Sdjl 		(me, "no base nsw config created for %s (sources: %s)\n",
411cb5caa98Sdjl 		    params->p.name, params->p.default_config);
412cb5caa98Sdjl 
413cb5caa98Sdjl 		ret = _nscd_create_nsw_state(params);
414cb5caa98Sdjl 		if (ret == NULL)
415cb5caa98Sdjl 			return (NSCD_CREATE_NSW_STATE_FAILED);
416cb5caa98Sdjl 		rootp->s = (struct nss_db_state *)ret;
417cb5caa98Sdjl 		return (NSCD_SUCCESS);
418cb5caa98Sdjl 	}
419cb5caa98Sdjl 
420cb5caa98Sdjl 	/*
421cb5caa98Sdjl 	 * if getting a nsw state for a request from the compat
422cb5caa98Sdjl 	 * backend, create the new switch structures if this
423cb5caa98Sdjl 	 * is the first time around for a passwd, shadow, group,
424cb5caa98Sdjl 	 * audit_user, or user_attr database
425cb5caa98Sdjl 	 */
426cb5caa98Sdjl 	if (params->compati != -1) {
427cb5caa98Sdjl 
428cb5caa98Sdjl 		nscd_nsw_config_t	**nswcfg1;
429cb5caa98Sdjl 		int			i = params->compati;
430cb5caa98Sdjl 
431ad0e80f7Smichen 		dbi = i;
432ad0e80f7Smichen 
433cb5caa98Sdjl 		nswcfg = (nscd_nsw_config_t **)_nscd_get(
434cb5caa98Sdjl 		    (nscd_acc_data_t *)nscd_nsw_config[i]);
435cb5caa98Sdjl 
436cb5caa98Sdjl 		/*
437cb5caa98Sdjl 		 * if nsw data structures not created yet, get the
438cb5caa98Sdjl 		 * config string from the passwd_compat or
439cb5caa98Sdjl 		 * group_compat DB and create the structures
440cb5caa98Sdjl 		 */
441cb5caa98Sdjl 		if (nswcfg == NULL) {
442cb5caa98Sdjl 			nswcfg1 = (nscd_nsw_config_t **)_nscd_get(
443cb5caa98Sdjl 			    (nscd_acc_data_t *)nscd_nsw_config[params->cfgdbi]);
444cb5caa98Sdjl 			if (nswcfg1 == NULL) {
445cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_NSW_STATE,
446cb5caa98Sdjl 				    NSCD_LOG_LEVEL_ERROR)
447cb5caa98Sdjl 				(me, "no nsw config for %s\n",
448cb5caa98Sdjl 				    params->p.name);
449cb5caa98Sdjl 				return (NSCD_CREATE_NSW_STATE_FAILED);
450cb5caa98Sdjl 			}
451cb5caa98Sdjl 
452ad0e80f7Smichen 			rc = _nscd_create_sw_struct(i, params->cfgdbi,
453ad0e80f7Smichen 			    params->p.name, (*nswcfg1)->nsw_cfg_str,
454ad0e80f7Smichen 			    NULL, params);
455cb5caa98Sdjl 			_nscd_release((nscd_acc_data_t *)nswcfg1);
456cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
457cb5caa98Sdjl 				return (rc);
458cb5caa98Sdjl 
459cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_NSW_STATE,
460cb5caa98Sdjl 			    NSCD_LOG_LEVEL_DEBUG)
461cb5caa98Sdjl 				(me, "nsw config created for %s (%s)\n",
462cb5caa98Sdjl 				    params->p.name, (*nswcfg1)->nsw_cfg_str);
463cb5caa98Sdjl 		} else
464cb5caa98Sdjl 			_nscd_release((nscd_acc_data_t *)nswcfg);
465cb5caa98Sdjl 	}
466cb5caa98Sdjl 
467cb5caa98Sdjl 	(void) rw_rdlock(&nscd_nsw_state_base_lock);
468cb5caa98Sdjl 	base = nscd_nsw_state_base[dbi];
469cb5caa98Sdjl 	(void) rw_unlock(&nscd_nsw_state_base_lock);
470cb5caa98Sdjl 	if (base == NULL)
471cb5caa98Sdjl 		assert(base != NULL);
472cb5caa98Sdjl 
473cb5caa98Sdjl 	/*
474cb5caa98Sdjl 	 * If list is not empty, return the first one on list.
475cb5caa98Sdjl 	 * Otherwise, create and return a new db state if the
476cb5caa98Sdjl 	 * limit is not reached. if reacehed, wait for the 'one
477cb5caa98Sdjl 	 * is available' signal.
478cb5caa98Sdjl 	 */
479cb5caa98Sdjl 	assert(base == (nscd_nsw_state_base_t *)_nscd_mutex_lock(
480cb5caa98Sdjl 	    (nscd_acc_data_t *)base));
481cb5caa98Sdjl 
482cb5caa98Sdjl 	if (tid == NULL) {
483cb5caa98Sdjl 		ctrl_p = &base->nsw_state;
484cb5caa98Sdjl 	} else {
485cb5caa98Sdjl 		thread_only = 1;
486cb5caa98Sdjl 		ctrl_p = &base->nsw_state_thr;
487cb5caa98Sdjl 
488cb5caa98Sdjl 		_NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
489cb5caa98Sdjl 			_nscd_logit(me, "per thread nsw state info: \n");
490cb5caa98Sdjl 			_nscd_logit(me, "tid = %d\n", *tid);
491cb5caa98Sdjl 			_nscd_logit(me, "tid in base = %d\n", base->tid);
492cb5caa98Sdjl 			_nscd_logit(me, "number of free nsw_state = %d\n",
493cb5caa98Sdjl 			    ctrl_p->free);
494cb5caa98Sdjl 			_nscd_logit(me, "number of nsw state allocated = %d\n",
495cb5caa98Sdjl 			    ctrl_p->allocated);
496cb5caa98Sdjl 			_nscd_logit(me, "first nsw state on list = %p\n",
497cb5caa98Sdjl 			    ctrl_p->first);
498cb5caa98Sdjl 			_nscd_logit(me, "number of waiter = %d\n",
499cb5caa98Sdjl 			    ctrl_p->waiter);
500bf1e3beeSmichen 
501cb5caa98Sdjl 		}
502cb5caa98Sdjl 	}
503cb5caa98Sdjl 
504cb5caa98Sdjl 	if (ctrl_p->first == NULL && ctrl_p->allocated == ctrl_p->max)
505cb5caa98Sdjl 		wait_cond = 1;
506cb5caa98Sdjl 	else if (thread_only && base->used_by_thr && base->tid != *tid)
507cb5caa98Sdjl 		wait_cond = 1;
508cb5caa98Sdjl 
509cb5caa98Sdjl 	if (wait_cond) {
510cb5caa98Sdjl 
511cb5caa98Sdjl 		ctrl_p->waiter++;
512cb5caa98Sdjl 
513cb5caa98Sdjl 		while (wait_cond) {
514cb5caa98Sdjl 			if (!thread_only)
515cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_NSW_STATE,
516cb5caa98Sdjl 				    NSCD_LOG_LEVEL_DEBUG)
517cb5caa98Sdjl 				(me, "waiting for nsw state signal\n");
518cb5caa98Sdjl 			else
519cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_NSW_STATE,
520cb5caa98Sdjl 				    NSCD_LOG_LEVEL_DEBUG)
521cb5caa98Sdjl 				(me, "waiting for per thread "
522cb5caa98Sdjl 				    "nsw state signal\n");
523cb5caa98Sdjl 
524cb5caa98Sdjl 			if (thread_only) {
525cb5caa98Sdjl 				_nscd_cond_wait((nscd_acc_data_t *)base,
526cb5caa98Sdjl 				    &base->thr_cond);
527cb5caa98Sdjl 
528cb5caa98Sdjl 				if (base->used_by_thr == 0 &&
529cb5caa98Sdjl 				    ctrl_p->first != NULL)
530cb5caa98Sdjl 					wait_cond = 0;
531cb5caa98Sdjl 			} else {
532cb5caa98Sdjl 				_nscd_cond_wait((nscd_acc_data_t *)base, NULL);
533cb5caa98Sdjl 
534cb5caa98Sdjl 				if (ctrl_p->first != NULL)
535cb5caa98Sdjl 					wait_cond = 0;
536cb5caa98Sdjl 			}
537cb5caa98Sdjl 
538cb5caa98Sdjl 			if (!thread_only)
539cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_NSW_STATE,
540cb5caa98Sdjl 				    NSCD_LOG_LEVEL_DEBUG)
541cb5caa98Sdjl 				(me, "woke from cond wait ...wait_cond = %d\n",
542cb5caa98Sdjl 				    wait_cond);
543cb5caa98Sdjl 			else
544cb5caa98Sdjl 
545cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_NSW_STATE,
546cb5caa98Sdjl 				    NSCD_LOG_LEVEL_DEBUG)
547cb5caa98Sdjl 				(me, "woke from cond wait (per thread) "
548cb5caa98Sdjl 				    "...wait_cond = %d\n", wait_cond);
549cb5caa98Sdjl 
550cb5caa98Sdjl 		}
551cb5caa98Sdjl 
552cb5caa98Sdjl 		ctrl_p->waiter--;
553cb5caa98Sdjl 	}
554cb5caa98Sdjl 
555cb5caa98Sdjl 	if (ctrl_p->first == NULL) {
556cb5caa98Sdjl 		int	geti;
557cb5caa98Sdjl 
558cb5caa98Sdjl 		/*
559cb5caa98Sdjl 		 * for lookup calls from the compat backend
560cb5caa98Sdjl 		 * uses the switch policy for passwd_compat
561cb5caa98Sdjl 		 * or group_compat
562cb5caa98Sdjl 		 */
563cb5caa98Sdjl 		if (params->compati != -1)
564cb5caa98Sdjl 			geti = params->compati;
565cb5caa98Sdjl 		else
566cb5caa98Sdjl 			geti = params->dbi;
567cb5caa98Sdjl 
568cb5caa98Sdjl 		params->nswcfg = (nscd_nsw_config_t **)_nscd_get(
569cb5caa98Sdjl 		    (nscd_acc_data_t *)nscd_nsw_config[geti]);
570cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
571cb5caa98Sdjl 		(me, "got a nsw config %p for index %d\n",
572cb5caa98Sdjl 		    params->nswcfg, geti);
573cb5caa98Sdjl 
574cb5caa98Sdjl 		ctrl_p->first = _nscd_create_nsw_state(params);
575cb5caa98Sdjl 		if (ctrl_p->first != NULL) {
576cb5caa98Sdjl 			ctrl_p->first->base = base;
577cb5caa98Sdjl 
578cb5caa98Sdjl 			if (tid == NULL) {
579cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_NSW_STATE,
580cb5caa98Sdjl 				    NSCD_LOG_LEVEL_DEBUG)
581cb5caa98Sdjl 				(me, "got a new nsw_state %p\n", ctrl_p->first);
582cb5caa98Sdjl 			} else {
583cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_NSW_STATE,
584cb5caa98Sdjl 				    NSCD_LOG_LEVEL_DEBUG)
585cb5caa98Sdjl 				(me, "got a new per thread nsw_state %p\n",
586cb5caa98Sdjl 				    ctrl_p->first);
587cb5caa98Sdjl 			}
588cb5caa98Sdjl 			ctrl_p->allocated++;
589cb5caa98Sdjl 			ctrl_p->free++;
590cb5caa98Sdjl 		} else {
591cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
592cb5caa98Sdjl 				(me, "error: unable to obtain a nsw state\n");
593cb5caa98Sdjl 			_nscd_mutex_unlock((nscd_acc_data_t *)base);
594cb5caa98Sdjl 			return (NSCD_CREATE_NSW_STATE_FAILED);
595cb5caa98Sdjl 		}
596cb5caa98Sdjl 	}
597cb5caa98Sdjl 
598cb5caa98Sdjl 	ret = ctrl_p->first;
599bf1e3beeSmichen 	if (ret->recheck_be == nscd_true)
600bf1e3beeSmichen 		check_be_array(ret);
601cb5caa98Sdjl 	ctrl_p->first = ret->next;
602cb5caa98Sdjl 	ret->next = NULL;
603cb5caa98Sdjl 	ctrl_p->free--;
604cb5caa98Sdjl 	if (thread_only) {
605cb5caa98Sdjl 		base->tid = *tid;
606cb5caa98Sdjl 		base->used_by_thr = 1;
607cb5caa98Sdjl 
608cb5caa98Sdjl 		_NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
609cb5caa98Sdjl 			_nscd_logit(me, "\t\t\tgot a per thread nsw "
610cb5caa98Sdjl 			    "state %p: \n", ret);
611cb5caa98Sdjl 			_nscd_logit(me, "tid = %d\n", *tid);
612cb5caa98Sdjl 			_nscd_logit(me, "tid in base = %d\n", base->tid);
613cb5caa98Sdjl 			_nscd_logit(me, "number of free nsw_state = %d\n",
614cb5caa98Sdjl 			    ctrl_p->free);
615cb5caa98Sdjl 			_nscd_logit(me, "number od nsw state allocated = %d\n",
616cb5caa98Sdjl 			    ctrl_p->allocated);
617cb5caa98Sdjl 			_nscd_logit(me, "first nsw state on list = %p\n",
618cb5caa98Sdjl 			    ctrl_p->first);
619cb5caa98Sdjl 			_nscd_logit(me, "number of waiter = %d\n",
620cb5caa98Sdjl 			    ctrl_p->waiter);
621cb5caa98Sdjl 		}
622cb5caa98Sdjl 	}
623cb5caa98Sdjl 	else
624cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
625cb5caa98Sdjl 		(me, "got old nsw state %p\n", ret);
626cb5caa98Sdjl 
627cb5caa98Sdjl 	_nscd_mutex_unlock((nscd_acc_data_t *)base);
628cb5caa98Sdjl 
629cb5caa98Sdjl 	rootp->s = (struct nss_db_state *)ret;
630cb5caa98Sdjl 
631cb5caa98Sdjl 	return (NSCD_SUCCESS);
632cb5caa98Sdjl }
633cb5caa98Sdjl 
634cb5caa98Sdjl nscd_rc_t
635cb5caa98Sdjl _nscd_get_nsw_state(
636cb5caa98Sdjl 	nss_db_root_t		*rootp,
637cb5caa98Sdjl 	nscd_nsw_params_t	*params)
638cb5caa98Sdjl {
639cb5caa98Sdjl 	return (_get_nsw_state_int(rootp, params, NULL));
640cb5caa98Sdjl }
641cb5caa98Sdjl 
642cb5caa98Sdjl nscd_rc_t
643cb5caa98Sdjl _nscd_get_nsw_state_thread(
644cb5caa98Sdjl 	nss_db_root_t		*rootp,
645cb5caa98Sdjl 	nscd_nsw_params_t	*params)
646cb5caa98Sdjl {
647cb5caa98Sdjl 	thread_t	tid = thr_self();
648cb5caa98Sdjl 	return (_get_nsw_state_int(rootp, params, &tid));
649cb5caa98Sdjl }
650cb5caa98Sdjl 
651cb5caa98Sdjl 
652cb5caa98Sdjl static void
653cb5caa98Sdjl _put_nsw_state_int(
654cb5caa98Sdjl 	nscd_nsw_state_t	*s,
655cb5caa98Sdjl 	thread_t		*tid)
656cb5caa98Sdjl {
657cb5caa98Sdjl 
658cb5caa98Sdjl 	nscd_nsw_state_base_t	*base;
659cb5caa98Sdjl 	nscd_state_ctrl_t	*ctrl_p;
660cb5caa98Sdjl 	int			thread_only = 0;
661cb5caa98Sdjl 	char			*me = "_put_nsw_state_int";
662cb5caa98Sdjl 
663cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
664cb5caa98Sdjl 	(me, "put back a nsw state\n");
665cb5caa98Sdjl 
666cb5caa98Sdjl 	if (s == NULL) {
667cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
668cb5caa98Sdjl 		(me, "nsw state is NULL, nothing to put back\n");
669cb5caa98Sdjl 		return;
670cb5caa98Sdjl 	}
671cb5caa98Sdjl 
672cb5caa98Sdjl 	/*
673cb5caa98Sdjl 	 * no need to put back if the nsw state is not on any base
674cb5caa98Sdjl 	 * but need to free the resources used
675cb5caa98Sdjl 	 */
676cb5caa98Sdjl 	if ((*s->nsw_cfg_p)->nobase  == 1) {
677cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
678cb5caa98Sdjl 		(me, "no base nsw state, freeing resources ...\n");
679cb5caa98Sdjl 
680cb5caa98Sdjl 		_nscd_free_nsw_state(s);
681cb5caa98Sdjl 		return;
682cb5caa98Sdjl 	}
683cb5caa98Sdjl 
684cb5caa98Sdjl 	if (tid != NULL)
685cb5caa98Sdjl 		thread_only = 1;
686cb5caa98Sdjl 
687cb5caa98Sdjl 	base = s->base;
688cb5caa98Sdjl 
689cb5caa98Sdjl 	if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) {
690cb5caa98Sdjl 		/* base has been freed, free this db state */
691cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
692cb5caa98Sdjl 		(me, "nsw state base has been freed, freeing %p\n", s);
693cb5caa98Sdjl 		_nscd_free_nsw_state(s);
694cb5caa98Sdjl 		return;
695cb5caa98Sdjl 	}
696cb5caa98Sdjl 
697cb5caa98Sdjl 	if (thread_only)
698cb5caa98Sdjl 		ctrl_p = &base->nsw_state_thr;
699cb5caa98Sdjl 	else
700cb5caa98Sdjl 		ctrl_p = &base->nsw_state;
701cb5caa98Sdjl 
702cb5caa98Sdjl 	_NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
703cb5caa98Sdjl 		_nscd_logit(me, "before returning the nsw state: \n");
704cb5caa98Sdjl 		_nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
705cb5caa98Sdjl 		_nscd_logit(me, "tid in base = %d\n", base->tid);
706cb5caa98Sdjl 		_nscd_logit(me, "number of free nsw_state = %d\n",
707cb5caa98Sdjl 		    ctrl_p->free);
708cb5caa98Sdjl 		_nscd_logit(me, "number od nsw state allocated = %d\n",
709cb5caa98Sdjl 		    ctrl_p->allocated);
710cb5caa98Sdjl 		_nscd_logit(me, "first nsw state on list = %p\n",
711cb5caa98Sdjl 		    ctrl_p->first);
712bf1e3beeSmichen 		_nscd_logit(me, "number of waiter = %d\n", ctrl_p->waiter);
713cb5caa98Sdjl 	}
714cb5caa98Sdjl 
715cb5caa98Sdjl 	if (ctrl_p->first != NULL) {
716cb5caa98Sdjl 		s->next = ctrl_p->first;
717cb5caa98Sdjl 		ctrl_p->first = s;
718cb5caa98Sdjl 	} else {
719cb5caa98Sdjl 		ctrl_p->first = s;
720cb5caa98Sdjl 		s->next = NULL;
721cb5caa98Sdjl 	}
722cb5caa98Sdjl 	ctrl_p->free++;
723cb5caa98Sdjl 
724cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
725cb5caa98Sdjl 	(me, "signaling waiter thread_only = %d..\n", thread_only);
726cb5caa98Sdjl 
727cb5caa98Sdjl 	if (thread_only && ctrl_p->free == ctrl_p->allocated) {
728cb5caa98Sdjl 		assert(ctrl_p->first != NULL);
729cb5caa98Sdjl 		base->used_by_thr = 0;
730cb5caa98Sdjl 		if (ctrl_p->waiter > 0) {
731cb5caa98Sdjl 			(void) cond_signal(&base->thr_cond);
732cb5caa98Sdjl 		}
733cb5caa98Sdjl 	}
734cb5caa98Sdjl 
735cb5caa98Sdjl 	if (!thread_only && ctrl_p->waiter > 0) {
736cb5caa98Sdjl 
737cb5caa98Sdjl 		_nscd_cond_signal((nscd_acc_data_t *)base);
738cb5caa98Sdjl 	}
739cb5caa98Sdjl 
740cb5caa98Sdjl 	_NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
741cb5caa98Sdjl 		_nscd_logit(me, "after the nsw state is returned: \n");
742cb5caa98Sdjl 		_nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
743cb5caa98Sdjl 		_nscd_logit(me, "tid in base = %d\n", base->tid);
744cb5caa98Sdjl 		_nscd_logit(me, "number of free nsw_state = %d\n",
745cb5caa98Sdjl 		    ctrl_p->free);
746cb5caa98Sdjl 		_nscd_logit(me, "number od nsw state allocated = %d\n",
747cb5caa98Sdjl 		    ctrl_p->allocated);
748cb5caa98Sdjl 		_nscd_logit(me, "first nsw state on list = %p\n",
749cb5caa98Sdjl 		    ctrl_p->first);
750bf1e3beeSmichen 		_nscd_logit(me, "tnumber of waiter = %d\n", ctrl_p->waiter);
751cb5caa98Sdjl 	}
752cb5caa98Sdjl 
753cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
754cb5caa98Sdjl 	(me, "done putting back nsw state %p, thread_only = %d\n",
755cb5caa98Sdjl 	    s, thread_only);
756cb5caa98Sdjl 
757cb5caa98Sdjl 	_nscd_mutex_unlock((nscd_acc_data_t *)base);
758cb5caa98Sdjl 
759cb5caa98Sdjl }
760cb5caa98Sdjl 
761cb5caa98Sdjl void
762cb5caa98Sdjl _nscd_put_nsw_state(
763cb5caa98Sdjl 	nscd_nsw_state_t	*s)
764cb5caa98Sdjl {
765cb5caa98Sdjl 	_put_nsw_state_int(s, NULL);
766cb5caa98Sdjl }
767cb5caa98Sdjl 
768cb5caa98Sdjl void
769cb5caa98Sdjl _nscd_put_nsw_state_thread(
770cb5caa98Sdjl 	nscd_nsw_state_t	*s)
771cb5caa98Sdjl {
772cb5caa98Sdjl 	thread_t		tid = thr_self();
773cb5caa98Sdjl 	_put_nsw_state_int(s, &tid);
774cb5caa98Sdjl }
775cb5caa98Sdjl 
776cb5caa98Sdjl nscd_rc_t
777cb5caa98Sdjl _nscd_init_nsw_state_base(
778cb5caa98Sdjl 	int			dbi,
779ad0e80f7Smichen 	int			compat_basei,
780cb5caa98Sdjl 	int			lock)
781cb5caa98Sdjl {
782ad0e80f7Smichen 	int			cfgdbi;
783cb5caa98Sdjl 	nscd_nsw_state_base_t	*base = NULL;
784cb5caa98Sdjl 	char			*me = "_nscd_init_nsw_state_base";
785cb5caa98Sdjl 
786cb5caa98Sdjl 	if (lock)
787cb5caa98Sdjl 		(void) rw_rdlock(&nscd_nsw_state_base_lock);
788cb5caa98Sdjl 
789cb5caa98Sdjl 	base = (nscd_nsw_state_base_t *)_nscd_alloc(
790cb5caa98Sdjl 	    NSCD_DATA_NSW_STATE_BASE,
791cb5caa98Sdjl 	    sizeof (nscd_nsw_state_base_t),
792cb5caa98Sdjl 	    _nscd_free_nsw_state_base,
793cb5caa98Sdjl 	    NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND);
794cb5caa98Sdjl 
795cb5caa98Sdjl 	if (base == NULL) {
796cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
797cb5caa98Sdjl 		    NSCD_LOG_LEVEL_ERROR)
798cb5caa98Sdjl 		(me, "not able to allocate a nsw state base\n");
799cb5caa98Sdjl 		if (lock)
800cb5caa98Sdjl 			(void) rw_unlock(&nscd_nsw_state_base_lock);
801cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
802cb5caa98Sdjl 	}
803bf1e3beeSmichen 	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
804cb5caa98Sdjl 		(me, "nsw state base %p allocated\n", base);
805cb5caa98Sdjl 
806cb5caa98Sdjl 	/*
807cb5caa98Sdjl 	 * initialize and activate the new nss_nsw_state base
808cb5caa98Sdjl 	 */
809cb5caa98Sdjl 	base->dbi = dbi;
810ad0e80f7Smichen 	if (compat_basei != -1)
811ad0e80f7Smichen 		cfgdbi = compat_basei;
812ad0e80f7Smichen 	else
813ad0e80f7Smichen 		cfgdbi = dbi;
814ad0e80f7Smichen 
815ad0e80f7Smichen 	base->nsw_state.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_db;
816ad0e80f7Smichen 	base->nsw_state_thr.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_thread;
817cb5caa98Sdjl 
818cb5caa98Sdjl 	nscd_nsw_state_base[dbi] = (nscd_nsw_state_base_t *)_nscd_set(
819cb5caa98Sdjl 	    (nscd_acc_data_t *)nscd_nsw_state_base[dbi],
820cb5caa98Sdjl 	    (nscd_acc_data_t *)base);
821cb5caa98Sdjl 
822cb5caa98Sdjl 	if (lock)
823cb5caa98Sdjl 		(void) rw_unlock(&nscd_nsw_state_base_lock);
824cb5caa98Sdjl 
825cb5caa98Sdjl 	return (NSCD_SUCCESS);
826cb5caa98Sdjl }
827cb5caa98Sdjl 
828cb5caa98Sdjl nscd_rc_t
829cb5caa98Sdjl _nscd_init_all_nsw_state_base()
830cb5caa98Sdjl {
831cb5caa98Sdjl 	int			i;
832cb5caa98Sdjl 	nscd_rc_t		rc;
833cb5caa98Sdjl 	char			*me = "_nscd_init_all_nsw_state_base";
834cb5caa98Sdjl 
835cb5caa98Sdjl 	(void) rw_rdlock(&nscd_nsw_state_base_lock);
836cb5caa98Sdjl 
837cb5caa98Sdjl 	for (i = 0; i < NSCD_NUM_DB; i++) {
838cb5caa98Sdjl 
839ad0e80f7Smichen 		rc = _nscd_init_nsw_state_base(i, -1, 0);
840cb5caa98Sdjl 
841cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
842cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
843cb5caa98Sdjl 			    NSCD_LOG_LEVEL_ERROR)
844cb5caa98Sdjl 			(me, "not able to initialize a nsw db state "
845cb5caa98Sdjl 			    "base (%d)\n", i);
846cb5caa98Sdjl 
847cb5caa98Sdjl 			(void) rw_unlock(&nscd_nsw_state_base_lock);
848cb5caa98Sdjl 			return (rc);
849cb5caa98Sdjl 		}
850cb5caa98Sdjl 	}
851bf1e3beeSmichen 	_NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
852cb5caa98Sdjl 	(me, "all nsw state base initialized\n");
853cb5caa98Sdjl 
854cb5caa98Sdjl 	(void) rw_unlock(&nscd_nsw_state_base_lock);
855cb5caa98Sdjl 
856cb5caa98Sdjl 	return (NSCD_SUCCESS);
857cb5caa98Sdjl }
858cb5caa98Sdjl 
859cb5caa98Sdjl nscd_rc_t
860cb5caa98Sdjl _nscd_alloc_nsw_state_base()
861cb5caa98Sdjl {
862cb5caa98Sdjl 
863cb5caa98Sdjl 	(void) rw_rdlock(&nscd_nsw_state_base_lock);
864cb5caa98Sdjl 
865cb5caa98Sdjl 	nscd_nsw_state_base = calloc(NSCD_NUM_DB,
866cb5caa98Sdjl 	    sizeof (nscd_nsw_state_base_t *));
867cb5caa98Sdjl 	if (nscd_nsw_state_base == NULL) {
868cb5caa98Sdjl 		(void) rw_unlock(&nscd_nsw_state_base_lock);
869cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
870cb5caa98Sdjl 	}
871cb5caa98Sdjl 
872cb5caa98Sdjl 	(void) rw_rdlock(&nscd_nsw_state_base_lock);
873cb5caa98Sdjl 
874cb5caa98Sdjl 	return (NSCD_SUCCESS);
875cb5caa98Sdjl }
876