8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / nscd / nscd_nswstate.c
blob2e72e42c093e13adbd2da6e058d3998eb933b993
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <string.h>
29 #include "nscd_switch.h"
30 #include "nscd_log.h"
33 * nscd_nsw_state_t list for each nss database. Protected
34 * by the readers/writer lock nscd_nsw_state_base_lock.
36 nscd_nsw_state_base_t **nscd_nsw_state_base;
37 static rwlock_t nscd_nsw_state_base_lock = DEFAULTRWLOCK;
39 static void
40 _nscd_free_nsw_state(
41 nscd_nsw_state_t *s)
44 int i;
45 char *me = "_nscd_free_nsw_state";
47 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
48 (me, "freeing nsw state = %p\n", s);
50 if (s == NULL)
51 return;
53 if (s->nsw_cfg_p != NULL)
55 * an nsw state without base does not reference
56 * count the nsw config data (ie not using a
57 * shared one), so the one created for it should
58 * be freed
60 if ((*s->nsw_cfg_p)->nobase != 1)
61 _nscd_release((nscd_acc_data_t *)s->nsw_cfg_p);
62 else
63 (void) _nscd_set((nscd_acc_data_t *)s->nsw_cfg_p, NULL);
65 if (s->be_db_pp != NULL) {
66 for (i = 0; i < s->max_src; i++) {
67 if (s->be_db_pp[i] == NULL)
68 continue;
69 _nscd_release((nscd_acc_data_t *)s->be_db_pp[i]);
70 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
71 (me, "release db be ptr %p\n", s->be_db_pp[i]);
73 free(s->be_db_pp);
76 if (s->be != NULL) {
77 for (i = 0; i < s->max_src; i++) {
78 if (s->be[i] == NULL)
79 continue;
80 if (s->getent == 1)
81 (void) NSS_INVOKE_DBOP(s->be[i],
82 NSS_DBOP_ENDENT, 0);
83 (void) NSS_INVOKE_DBOP(s->be[i],
84 NSS_DBOP_DESTRUCTOR, 0);
86 free(s->be);
89 if (s->be_constr != NULL)
90 free(s->be_constr);
92 if (s->be_version_p != NULL)
93 free(s->be_version_p);
95 /* remove reference to the nsw state base */
96 if (s->base != NULL) {
97 _nscd_release((nscd_acc_data_t *)s->base);
98 s->base = NULL;
101 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
102 (me, "nsw state %p freed \n", s);
104 free(s);
107 static void
108 _nscd_free_nsw_state_base(
109 nscd_acc_data_t *data)
111 nscd_nsw_state_base_t *base = (nscd_nsw_state_base_t *)data;
112 nscd_nsw_state_t *s, *ts;
113 int i;
114 char *me = "_nscd_free_nsw_state_base";
116 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
117 (me, "freeing db state base %p\n", base);
119 if (base == NULL)
120 return;
122 for (i = 0; i < 2; i++) {
123 if (i == 1)
124 s = base->nsw_state.first;
125 else
126 s = base->nsw_state_thr.first;
128 while (s != NULL) {
129 ts = s->next;
130 _nscd_free_nsw_state(s);
131 s = ts;
135 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
136 (me, "nsw state base %p freed \n", base);
139 void
140 _nscd_free_all_nsw_state_base()
142 nscd_nsw_state_base_t *base;
143 int i;
144 char *me = "_nscd_free_all_nsw_state_base";
146 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
147 (me, "freeing all db state base\n");
149 (void) rw_wrlock(&nscd_nsw_state_base_lock);
150 for (i = 0; i < NSCD_NUM_DB; i++) {
152 base = nscd_nsw_state_base[i];
153 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
154 NSCD_LOG_LEVEL_DEBUG)
155 (me, "freeing db state base (%d) %p \n", i, base);
157 if (base == NULL)
158 continue;
160 nscd_nsw_state_base[i] = (nscd_nsw_state_base_t *)
161 _nscd_set((nscd_acc_data_t *)base, NULL);
163 (void) rw_unlock(&nscd_nsw_state_base_lock);
166 static nscd_nsw_state_t *
167 _nscd_create_nsw_state(
168 nscd_nsw_params_t *params)
170 nscd_nsw_state_t *s;
171 nscd_nsw_config_t *nsw_cfg;
172 nscd_db_t **be_db_p, *be_db;
173 int i, nobe = 1;
174 char *me = "_nscd_create_nsw_state";
177 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
178 (me, "creating nsw state...\n");
180 s = calloc(1, sizeof (nscd_nsw_state_t));
181 if (s == NULL) {
182 if ((*s->nsw_cfg_p)->nobase != 1)
183 _nscd_release((nscd_acc_data_t *)params->nswcfg);
184 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
185 (me, "not able to allocate a nsw state\n");
186 return (NULL);
187 } else
188 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
189 (me, "nsw state %p allocated\n", s);
191 s->dbi = params->dbi;
192 s->next = NULL;
194 nsw_cfg = *params->nswcfg;
196 s->nsw_cfg_p = params->nswcfg;
197 s->config = nsw_cfg->nsw_config;
198 s->max_src = nsw_cfg->max_src;
199 s->p = params->p;
201 s->be = calloc(s->max_src, sizeof (nss_backend_t **));
202 if (s->be == NULL) {
203 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
204 (me, "not able to allocate s->be\n");
206 _nscd_free_nsw_state(s);
207 return (NULL);
208 } else {
209 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
210 (me, "db be array %p allocated\n", s->be);
213 s->be_constr = (nss_backend_constr_t *)calloc(s->max_src,
214 sizeof (nss_backend_constr_t));
215 if (s->be_constr == NULL) {
216 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
217 (me, "not able to allocate s->be_constr\n");
219 _nscd_free_nsw_state(s);
220 return (NULL);
221 } else {
222 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
223 (me, "db be constructor array %p allocated\n", s->be_constr);
226 s->be_version_p = (void **)calloc(s->max_src, sizeof (void *));
227 if (s->be_version_p == NULL) {
228 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
229 (me, "not able to allocate s->be_version_p\n");
231 _nscd_free_nsw_state(s);
232 return (NULL);
233 } else {
234 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
235 (me, "db be version ptr array %p allocated\n", s->be_version_p);
238 s->be_db_pp = calloc(s->max_src, sizeof (nscd_db_t ***));
239 if (s->be_db_pp == NULL) {
240 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
241 (me, "not able to allocate s->be_db_pp\n");
242 _nscd_free_nsw_state(s);
243 return (NULL);
244 } else {
245 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
246 (me, "be_db_pp array %p allocated\n", s->be_db_pp);
249 /* create the source:database backends */
250 for (i = 0; i < s->max_src; i++) {
251 nss_backend_t *be;
252 int srci;
253 char *srcn;
254 const char *dbn;
255 struct __nsw_lookup_v1 *lkp;
256 const nscd_db_entry_t *dbe;
257 nscd_be_info_t *be_info;
259 if (i == 0)
260 lkp = s->config->lookups;
261 else
262 lkp = lkp->next;
263 if (lkp == NULL) {
264 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
265 (me, "error: lkp is NULL\n");
266 _nscd_free_nsw_state(s);
267 return (NULL);
270 srci = nsw_cfg->src_idx[i];
271 srcn = lkp->service_name;
272 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
273 (me, "source name = %s, index = %d\n", srcn, srci);
275 be_db_p = (nscd_db_t **)_nscd_get(
276 (nscd_acc_data_t *)nscd_src_backend_db[srci]);
277 if (be_db_p == NULL) {
278 _nscd_free_nsw_state(s);
279 return (NULL);
281 be_db = *be_db_p;
282 s->be_db_pp[i] = be_db_p;
283 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
284 (me, "be db ptr array %p referenced\n", be_db_p);
286 be_info = NULL;
287 be = NULL;
288 dbn = params->p.name;
289 dbe = _nscd_get_db_entry(be_db, NSCD_DATA_BACKEND_INFO,
290 (const char *)dbn, NSCD_GET_FIRST_DB_ENTRY, 0);
291 if (dbe != NULL)
292 be_info = (nscd_be_info_t *)*(dbe->data_array);
294 if (be_info == NULL || be_info->be_constr == NULL) {
295 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
296 (me, "no backend info or be_constr is NULL "
297 "for <%s : %s>\n", NSCD_NSW_SRC_NAME(srci),
298 dbn);
299 } else {
300 s->be_constr[i] = be_info->be_constr;
301 be = (be_info->be_constr)(dbn,
302 NSCD_NSW_SRC_NAME(srci), 0);
303 if (be == NULL)
304 s->recheck_be = nscd_true;
307 if (be == NULL) {
308 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
309 (me, "not able to init be for <%s : %s>\n",
310 NSCD_NSW_SRC_NAME(srci), dbn);
312 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
313 (me, "releasing db be ptr %p\n", be_db_p);
315 _nscd_release((nscd_acc_data_t *)be_db_p);
316 s->be_db_pp[i] = NULL;
318 continue;
321 s->be[i] = be;
322 s->be_version_p[i] = be_info->be_version;
323 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
324 (me, "backend version is %p\n", be_info->be_version);
325 nobe = 0;
328 if (nobe == 1) {
329 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
330 (me, "NO backend found, returning NULL\n");
332 _nscd_free_nsw_state(s);
333 return (NULL);
336 return (s);
340 * Try to initialize the backend instances one more time
341 * in case the dependencies the backend libraries depend
342 * on are now available
344 static void
345 check_be_array(
346 nscd_nsw_state_t *s)
348 int i;
349 char *dbn;
350 char *srcn;
351 struct __nsw_lookup_v1 *lkp;
353 dbn = NSCD_NSW_DB_NAME(s->dbi);
355 s->recheck_be = nscd_false;
356 for (i = 0; i < s->max_src; i++) {
358 if (i == 0)
359 lkp = s->config->lookups;
360 else
361 lkp = lkp->next;
362 if (lkp == NULL)
363 return;
365 srcn = lkp->service_name;
368 * it is possible that 's->be[i]' could not be
369 * initialized earlier due to a dependency not
370 * yet available (e.g., nis on domain name),
371 * try to initialize one more time
373 if (s->be[i] == NULL && s->be_constr[i] != NULL) {
374 s->be[i] = (s->be_constr[i])(dbn, srcn, 0);
375 if (s->be[i] == NULL)
376 s->recheck_be = nscd_true;
381 static nscd_rc_t
382 _get_nsw_state_int(
383 nss_db_root_t *rootp,
384 nscd_nsw_params_t *params,
385 thread_t *tid)
388 nscd_nsw_state_t *ret = NULL;
389 nscd_nsw_config_t **nswcfg;
390 nscd_nsw_state_base_t *base;
391 nscd_state_ctrl_t *ctrl_p;
392 int thread_only = 0, wait_cond = 0;
393 char *me = "_get_nsw_state_int";
394 int dbi;
395 nscd_rc_t rc;
397 dbi = params->dbi;
400 * no nsw state will be reused, if asked to use
401 * default config. So create the new structures
402 * used by the switch engine and the new nsw state
404 if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
405 rc = _nscd_create_sw_struct(dbi, -1, (char *)params->p.name,
406 (char *)params->p.default_config, NULL, params);
407 if (rc != NSCD_SUCCESS)
408 return (rc);
410 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
411 (me, "no base nsw config created for %s (sources: %s)\n",
412 params->p.name, params->p.default_config);
414 ret = _nscd_create_nsw_state(params);
415 if (ret == NULL)
416 return (NSCD_CREATE_NSW_STATE_FAILED);
417 rootp->s = (struct nss_db_state *)ret;
418 return (NSCD_SUCCESS);
422 * if getting a nsw state for a request from the compat
423 * backend, create the new switch structures if this
424 * is the first time around for a passwd, shadow, group,
425 * or user_attr database
427 if (params->compati != -1) {
429 nscd_nsw_config_t **nswcfg1, **nswcfg2;
430 int i = params->compati;
432 dbi = i;
435 * retrieve the pointer space which contains a
436 * pointer pointing to the nsswitch config
437 * structure for the compat backend
439 nswcfg = (nscd_nsw_config_t **)_nscd_get(
440 (nscd_acc_data_t *)nscd_nsw_config[i]);
443 * If nsswitch config structure not created yet,
444 * get the config string from the passwd_compat
445 * or group_compat DB and create the structure.
447 if (*nswcfg == NULL) {
448 /* Wait first if it's being created. */
449 nswcfg2 = (nscd_nsw_config_t **)_nscd_mutex_lock(
450 (nscd_acc_data_t *)nscd_nsw_config[i]);
452 /* still not created yet */
453 if (*nswcfg2 == NULL) {
455 * get the nsswitch config string specified
456 * for passwd_compat or group_compat
458 nswcfg1 = (nscd_nsw_config_t **)_nscd_get(
459 (nscd_acc_data_t *)
460 nscd_nsw_config[params->cfgdbi]);
461 if (nswcfg1 == NULL) {
462 _NSCD_LOG(NSCD_LOG_NSW_STATE,
463 NSCD_LOG_LEVEL_ERROR)
464 (me, "no nsw config for %s\n",
465 params->p.name);
467 (void) _nscd_mutex_unlock(
468 (nscd_acc_data_t *)nswcfg2);
469 _nscd_release((nscd_acc_data_t *)
470 nswcfg);
472 return (NSCD_CREATE_NSW_STATE_FAILED);
475 rc = _nscd_create_sw_struct(i, params->cfgdbi,
476 params->p.name, (*nswcfg1)->nsw_cfg_str,
477 NULL, params);
478 _nscd_release((nscd_acc_data_t *)nswcfg1);
480 if (rc == NSCD_SUCCESS) {
481 _NSCD_LOG(NSCD_LOG_NSW_STATE,
482 NSCD_LOG_LEVEL_DEBUG)
483 (me, "nsw config created for %s (%s)\n",
484 params->p.name,
485 (*nswcfg1)->nsw_cfg_str);
486 } else {
487 (void) _nscd_mutex_unlock(
488 (nscd_acc_data_t *)nswcfg2);
489 _nscd_release((nscd_acc_data_t *)
490 nswcfg);
491 return (rc);
494 (void) _nscd_mutex_unlock((nscd_acc_data_t *)nswcfg2);
496 _nscd_release((nscd_acc_data_t *)nswcfg);
499 (void) rw_rdlock(&nscd_nsw_state_base_lock);
500 base = nscd_nsw_state_base[dbi];
501 (void) rw_unlock(&nscd_nsw_state_base_lock);
502 if (base == NULL)
503 assert(base != NULL);
506 * If list is not empty, return the first one on list.
507 * Otherwise, create and return a new db state if the
508 * limit is not reached. if reacehed, wait for the 'one
509 * is available' signal.
511 assert(base == (nscd_nsw_state_base_t *)_nscd_mutex_lock(
512 (nscd_acc_data_t *)base));
514 if (tid == NULL) {
515 ctrl_p = &base->nsw_state;
516 } else {
517 thread_only = 1;
518 ctrl_p = &base->nsw_state_thr;
520 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
521 _nscd_logit(me, "per thread nsw state info: \n");
522 _nscd_logit(me, "tid = %d\n", *tid);
523 _nscd_logit(me, "tid in base = %d\n", base->tid);
524 _nscd_logit(me, "number of free nsw_state = %d\n",
525 ctrl_p->free);
526 _nscd_logit(me, "number of nsw state allocated = %d\n",
527 ctrl_p->allocated);
528 _nscd_logit(me, "first nsw state on list = %p\n",
529 ctrl_p->first);
530 _nscd_logit(me, "number of waiter = %d\n",
531 ctrl_p->waiter);
536 if (ctrl_p->first == NULL && ctrl_p->allocated == ctrl_p->max)
537 wait_cond = 1;
538 else if (thread_only && base->used_by_thr && base->tid != *tid)
539 wait_cond = 1;
541 if (wait_cond) {
543 ctrl_p->waiter++;
545 while (wait_cond) {
546 if (!thread_only)
547 _NSCD_LOG(NSCD_LOG_NSW_STATE,
548 NSCD_LOG_LEVEL_DEBUG)
549 (me, "waiting for nsw state signal\n");
550 else
551 _NSCD_LOG(NSCD_LOG_NSW_STATE,
552 NSCD_LOG_LEVEL_DEBUG)
553 (me, "waiting for per thread "
554 "nsw state signal\n");
556 if (thread_only) {
557 _nscd_cond_wait((nscd_acc_data_t *)base,
558 &base->thr_cond);
560 if (base->used_by_thr == 0 &&
561 ctrl_p->first != NULL)
562 wait_cond = 0;
563 } else {
564 _nscd_cond_wait((nscd_acc_data_t *)base, NULL);
566 if (ctrl_p->first != NULL)
567 wait_cond = 0;
570 if (!thread_only)
571 _NSCD_LOG(NSCD_LOG_NSW_STATE,
572 NSCD_LOG_LEVEL_DEBUG)
573 (me, "woke from cond wait ...wait_cond = %d\n",
574 wait_cond);
575 else
577 _NSCD_LOG(NSCD_LOG_NSW_STATE,
578 NSCD_LOG_LEVEL_DEBUG)
579 (me, "woke from cond wait (per thread) "
580 "...wait_cond = %d\n", wait_cond);
584 ctrl_p->waiter--;
587 if (ctrl_p->first == NULL) {
588 int geti;
591 * for lookup calls from the compat backend
592 * uses the switch policy for passwd_compat
593 * or group_compat
595 if (params->compati != -1)
596 geti = params->compati;
597 else
598 geti = params->dbi;
600 params->nswcfg = (nscd_nsw_config_t **)_nscd_get(
601 (nscd_acc_data_t *)nscd_nsw_config[geti]);
602 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
603 (me, "got a nsw config %p for index %d\n",
604 params->nswcfg, geti);
606 ctrl_p->first = _nscd_create_nsw_state(params);
607 if (ctrl_p->first != NULL) {
608 if (tid == NULL) {
609 _NSCD_LOG(NSCD_LOG_NSW_STATE,
610 NSCD_LOG_LEVEL_DEBUG)
611 (me, "got a new nsw_state %p\n", ctrl_p->first);
612 } else {
613 _NSCD_LOG(NSCD_LOG_NSW_STATE,
614 NSCD_LOG_LEVEL_DEBUG)
615 (me, "got a new per thread nsw_state %p\n",
616 ctrl_p->first);
618 ctrl_p->allocated++;
619 ctrl_p->free++;
620 } else {
621 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
622 (me, "error: unable to obtain a nsw state\n");
623 _nscd_mutex_unlock((nscd_acc_data_t *)base);
624 return (NSCD_CREATE_NSW_STATE_FAILED);
628 ret = ctrl_p->first;
629 if (ret->recheck_be == nscd_true)
630 check_be_array(ret);
631 ctrl_p->first = ret->next;
632 ret->next = NULL;
633 ctrl_p->free--;
634 if (thread_only) {
635 base->tid = *tid;
636 base->used_by_thr = 1;
638 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
639 _nscd_logit(me, "\t\t\tgot a per thread nsw "
640 "state %p: \n", ret);
641 _nscd_logit(me, "tid = %d\n", *tid);
642 _nscd_logit(me, "tid in base = %d\n", base->tid);
643 _nscd_logit(me, "number of free nsw_state = %d\n",
644 ctrl_p->free);
645 _nscd_logit(me, "number od nsw state allocated = %d\n",
646 ctrl_p->allocated);
647 _nscd_logit(me, "first nsw state on list = %p\n",
648 ctrl_p->first);
649 _nscd_logit(me, "number of waiter = %d\n",
650 ctrl_p->waiter);
653 else
654 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
655 (me, "got old nsw state %p\n", ret);
658 * reference count the nsswitch state base bfore handing out
659 * the nsswitch state
661 ret->base = (nscd_nsw_state_base_t *)
662 _nscd_get((nscd_acc_data_t *)base);
664 _nscd_mutex_unlock((nscd_acc_data_t *)base);
666 rootp->s = (struct nss_db_state *)ret;
668 return (NSCD_SUCCESS);
671 nscd_rc_t
672 _nscd_get_nsw_state(
673 nss_db_root_t *rootp,
674 nscd_nsw_params_t *params)
676 return (_get_nsw_state_int(rootp, params, NULL));
679 nscd_rc_t
680 _nscd_get_nsw_state_thread(
681 nss_db_root_t *rootp,
682 nscd_nsw_params_t *params)
684 thread_t tid = thr_self();
685 return (_get_nsw_state_int(rootp, params, &tid));
689 static void
690 _put_nsw_state_int(
691 nscd_nsw_state_t *s,
692 thread_t *tid)
695 nscd_nsw_state_base_t *base;
696 nscd_state_ctrl_t *ctrl_p;
697 int thread_only = 0;
698 char *me = "_put_nsw_state_int";
700 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
701 (me, "put back a nsw state\n");
703 if (s == NULL) {
704 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
705 (me, "nsw state is NULL, nothing to put back\n");
706 return;
710 * no need to put back if the nsw state is not on any base
711 * but need to free the resources used
713 if ((*s->nsw_cfg_p)->nobase == 1) {
714 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
715 (me, "no base nsw state, freeing resources ...\n");
717 _nscd_free_nsw_state(s);
718 return;
721 if (tid != NULL)
722 thread_only = 1;
724 base = s->base;
726 if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) {
727 /* base has been freed or no longer valid, free the nsw state */
728 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
729 (me, "nsw state base gone or no longer valid, freeing %p\n", s);
730 _nscd_free_nsw_state(s);
731 return;
734 if (thread_only)
735 ctrl_p = &base->nsw_state_thr;
736 else
737 ctrl_p = &base->nsw_state;
739 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
740 _nscd_logit(me, "before returning the nsw state: \n");
741 _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
742 _nscd_logit(me, "tid in base = %d\n", base->tid);
743 _nscd_logit(me, "number of free nsw_state = %d\n",
744 ctrl_p->free);
745 _nscd_logit(me, "number od nsw state allocated = %d\n",
746 ctrl_p->allocated);
747 _nscd_logit(me, "first nsw state on list = %p\n",
748 ctrl_p->first);
749 _nscd_logit(me, "number of waiter = %d\n", ctrl_p->waiter);
752 if (ctrl_p->first != NULL) {
753 s->next = ctrl_p->first;
754 ctrl_p->first = s;
755 } else {
756 ctrl_p->first = s;
757 s->next = NULL;
759 ctrl_p->free++;
762 * Remove reference to the nsswitch state base.
764 _nscd_release((nscd_acc_data_t *)base);
765 s->base = NULL;
767 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
768 (me, "signaling waiter thread_only = %d..\n", thread_only);
770 if (thread_only && ctrl_p->free == ctrl_p->allocated) {
771 assert(ctrl_p->first != NULL);
772 base->used_by_thr = 0;
773 if (ctrl_p->waiter > 0) {
774 (void) cond_signal(&base->thr_cond);
778 if (!thread_only && ctrl_p->waiter > 0) {
780 _nscd_cond_signal((nscd_acc_data_t *)base);
783 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
784 _nscd_logit(me, "after the nsw state is returned: \n");
785 _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
786 _nscd_logit(me, "tid in base = %d\n", base->tid);
787 _nscd_logit(me, "number of free nsw_state = %d\n",
788 ctrl_p->free);
789 _nscd_logit(me, "number od nsw state allocated = %d\n",
790 ctrl_p->allocated);
791 _nscd_logit(me, "first nsw state on list = %p\n",
792 ctrl_p->first);
793 _nscd_logit(me, "tnumber of waiter = %d\n", ctrl_p->waiter);
796 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
797 (me, "done putting back nsw state %p, thread_only = %d\n",
798 s, thread_only);
800 _nscd_mutex_unlock((nscd_acc_data_t *)base);
804 void
805 _nscd_put_nsw_state(
806 nscd_nsw_state_t *s)
808 _put_nsw_state_int(s, NULL);
811 void
812 _nscd_put_nsw_state_thread(
813 nscd_nsw_state_t *s)
815 thread_t tid = thr_self();
816 _put_nsw_state_int(s, &tid);
819 nscd_rc_t
820 _nscd_init_nsw_state_base(
821 int dbi,
822 int compat_basei,
823 int lock)
825 int cfgdbi;
826 nscd_nsw_state_base_t *base = NULL;
827 char *me = "_nscd_init_nsw_state_base";
829 if (lock)
830 (void) rw_rdlock(&nscd_nsw_state_base_lock);
832 base = (nscd_nsw_state_base_t *)_nscd_alloc(
833 NSCD_DATA_NSW_STATE_BASE,
834 sizeof (nscd_nsw_state_base_t),
835 _nscd_free_nsw_state_base,
836 NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND);
838 if (base == NULL) {
839 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
840 NSCD_LOG_LEVEL_ERROR)
841 (me, "not able to allocate a nsw state base\n");
842 if (lock)
843 (void) rw_unlock(&nscd_nsw_state_base_lock);
844 return (NSCD_NO_MEMORY);
846 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
847 (me, "nsw state base %p allocated\n", base);
850 * initialize and activate the new nss_nsw_state base
852 base->dbi = dbi;
853 if (compat_basei != -1)
854 cfgdbi = compat_basei;
855 else
856 cfgdbi = dbi;
858 base->nsw_state.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_db;
859 base->nsw_state_thr.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_thread;
861 nscd_nsw_state_base[dbi] = (nscd_nsw_state_base_t *)_nscd_set(
862 (nscd_acc_data_t *)nscd_nsw_state_base[dbi],
863 (nscd_acc_data_t *)base);
865 if (lock)
866 (void) rw_unlock(&nscd_nsw_state_base_lock);
868 return (NSCD_SUCCESS);
871 nscd_rc_t
872 _nscd_init_all_nsw_state_base()
874 int i;
875 nscd_rc_t rc;
876 char *me = "_nscd_init_all_nsw_state_base";
878 (void) rw_rdlock(&nscd_nsw_state_base_lock);
880 for (i = 0; i < NSCD_NUM_DB; i++) {
882 rc = _nscd_init_nsw_state_base(i, -1, 0);
884 if (rc != NSCD_SUCCESS) {
885 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
886 NSCD_LOG_LEVEL_ERROR)
887 (me, "not able to initialize a nsw db state "
888 "base (%d)\n", i);
890 (void) rw_unlock(&nscd_nsw_state_base_lock);
891 return (rc);
894 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
895 (me, "all nsw state base initialized\n");
897 (void) rw_unlock(&nscd_nsw_state_base_lock);
899 return (NSCD_SUCCESS);
902 nscd_rc_t
903 _nscd_alloc_nsw_state_base()
906 (void) rw_rdlock(&nscd_nsw_state_base_lock);
908 nscd_nsw_state_base = calloc(NSCD_NUM_DB,
909 sizeof (nscd_nsw_state_base_t *));
910 if (nscd_nsw_state_base == NULL) {
911 (void) rw_unlock(&nscd_nsw_state_base_lock);
912 return (NSCD_NO_MEMORY);
915 (void) rw_rdlock(&nscd_nsw_state_base_lock);
917 return (NSCD_SUCCESS);