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