comm: add -Wall
[unleashed.git] / usr / src / cmd / nscd / nscd_nswstate.c
blob516eb0cf1bbd08c1aa430f6e4ed55794af1a83ce
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 free(s->be_constr);
91 free(s->be_version_p);
93 /* remove reference to the nsw state base */
94 if (s->base != NULL) {
95 _nscd_release((nscd_acc_data_t *)s->base);
96 s->base = NULL;
99 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
100 (me, "nsw state %p freed \n", s);
102 free(s);
105 static void
106 _nscd_free_nsw_state_base(
107 nscd_acc_data_t *data)
109 nscd_nsw_state_base_t *base = (nscd_nsw_state_base_t *)data;
110 nscd_nsw_state_t *s, *ts;
111 int i;
112 char *me = "_nscd_free_nsw_state_base";
114 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
115 (me, "freeing db state base %p\n", base);
117 if (base == NULL)
118 return;
120 for (i = 0; i < 2; i++) {
121 if (i == 1)
122 s = base->nsw_state.first;
123 else
124 s = base->nsw_state_thr.first;
126 while (s != NULL) {
127 ts = s->next;
128 _nscd_free_nsw_state(s);
129 s = ts;
133 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
134 (me, "nsw state base %p freed \n", base);
137 void
138 _nscd_free_all_nsw_state_base()
140 nscd_nsw_state_base_t *base;
141 int i;
142 char *me = "_nscd_free_all_nsw_state_base";
144 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
145 (me, "freeing all db state base\n");
147 (void) rw_wrlock(&nscd_nsw_state_base_lock);
148 for (i = 0; i < NSCD_NUM_DB; i++) {
150 base = nscd_nsw_state_base[i];
151 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
152 NSCD_LOG_LEVEL_DEBUG)
153 (me, "freeing db state base (%d) %p \n", i, base);
155 if (base == NULL)
156 continue;
158 nscd_nsw_state_base[i] = (nscd_nsw_state_base_t *)
159 _nscd_set((nscd_acc_data_t *)base, NULL);
161 (void) rw_unlock(&nscd_nsw_state_base_lock);
164 static nscd_nsw_state_t *
165 _nscd_create_nsw_state(
166 nscd_nsw_params_t *params)
168 nscd_nsw_state_t *s;
169 nscd_nsw_config_t *nsw_cfg;
170 nscd_db_t **be_db_p, *be_db;
171 int i, nobe = 1;
172 char *me = "_nscd_create_nsw_state";
175 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
176 (me, "creating nsw state...\n");
178 s = calloc(1, sizeof (nscd_nsw_state_t));
179 if (s == NULL) {
180 if ((*s->nsw_cfg_p)->nobase != 1)
181 _nscd_release((nscd_acc_data_t *)params->nswcfg);
182 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
183 (me, "not able to allocate a nsw state\n");
184 return (NULL);
185 } else
186 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
187 (me, "nsw state %p allocated\n", s);
189 s->dbi = params->dbi;
190 s->next = NULL;
192 nsw_cfg = *params->nswcfg;
194 s->nsw_cfg_p = params->nswcfg;
195 s->config = nsw_cfg->nsw_config;
196 s->max_src = nsw_cfg->max_src;
197 s->p = params->p;
199 s->be = calloc(s->max_src, sizeof (nss_backend_t **));
200 if (s->be == NULL) {
201 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
202 (me, "not able to allocate s->be\n");
204 _nscd_free_nsw_state(s);
205 return (NULL);
206 } else {
207 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
208 (me, "db be array %p allocated\n", s->be);
211 s->be_constr = (nss_backend_constr_t *)calloc(s->max_src,
212 sizeof (nss_backend_constr_t));
213 if (s->be_constr == NULL) {
214 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
215 (me, "not able to allocate s->be_constr\n");
217 _nscd_free_nsw_state(s);
218 return (NULL);
219 } else {
220 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
221 (me, "db be constructor array %p allocated\n", s->be_constr);
224 s->be_version_p = (void **)calloc(s->max_src, sizeof (void *));
225 if (s->be_version_p == NULL) {
226 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
227 (me, "not able to allocate s->be_version_p\n");
229 _nscd_free_nsw_state(s);
230 return (NULL);
231 } else {
232 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
233 (me, "db be version ptr array %p allocated\n", s->be_version_p);
236 s->be_db_pp = calloc(s->max_src, sizeof (nscd_db_t ***));
237 if (s->be_db_pp == NULL) {
238 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
239 (me, "not able to allocate s->be_db_pp\n");
240 _nscd_free_nsw_state(s);
241 return (NULL);
242 } else {
243 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
244 (me, "be_db_pp array %p allocated\n", s->be_db_pp);
247 /* create the source:database backends */
248 for (i = 0; i < s->max_src; i++) {
249 nss_backend_t *be;
250 int srci;
251 char *srcn;
252 const char *dbn;
253 struct __nsw_lookup_v1 *lkp;
254 const nscd_db_entry_t *dbe;
255 nscd_be_info_t *be_info;
257 if (i == 0)
258 lkp = s->config->lookups;
259 else
260 lkp = lkp->next;
261 if (lkp == NULL) {
262 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
263 (me, "error: lkp is NULL\n");
264 _nscd_free_nsw_state(s);
265 return (NULL);
268 srci = nsw_cfg->src_idx[i];
269 srcn = lkp->service_name;
270 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
271 (me, "source name = %s, index = %d\n", srcn, srci);
273 be_db_p = (nscd_db_t **)_nscd_get(
274 (nscd_acc_data_t *)nscd_src_backend_db[srci]);
275 if (be_db_p == NULL) {
276 _nscd_free_nsw_state(s);
277 return (NULL);
279 be_db = *be_db_p;
280 s->be_db_pp[i] = be_db_p;
281 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
282 (me, "be db ptr array %p referenced\n", be_db_p);
284 be_info = NULL;
285 be = NULL;
286 dbn = params->p.name;
287 dbe = _nscd_get_db_entry(be_db, NSCD_DATA_BACKEND_INFO,
288 (const char *)dbn, NSCD_GET_FIRST_DB_ENTRY, 0);
289 if (dbe != NULL)
290 be_info = (nscd_be_info_t *)*(dbe->data_array);
292 if (be_info == NULL || be_info->be_constr == NULL) {
293 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
294 (me, "no backend info or be_constr is NULL "
295 "for <%s : %s>\n", NSCD_NSW_SRC_NAME(srci),
296 dbn);
297 } else {
298 s->be_constr[i] = be_info->be_constr;
299 be = (be_info->be_constr)(dbn,
300 NSCD_NSW_SRC_NAME(srci), 0);
301 if (be == NULL)
302 s->recheck_be = nscd_true;
305 if (be == NULL) {
306 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
307 (me, "not able to init be for <%s : %s>\n",
308 NSCD_NSW_SRC_NAME(srci), dbn);
310 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
311 (me, "releasing db be ptr %p\n", be_db_p);
313 _nscd_release((nscd_acc_data_t *)be_db_p);
314 s->be_db_pp[i] = NULL;
316 continue;
319 s->be[i] = be;
320 s->be_version_p[i] = be_info->be_version;
321 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
322 (me, "backend version is %p\n", be_info->be_version);
323 nobe = 0;
326 if (nobe == 1) {
327 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
328 (me, "NO backend found, returning NULL\n");
330 _nscd_free_nsw_state(s);
331 return (NULL);
334 return (s);
338 * Try to initialize the backend instances one more time
339 * in case the dependencies the backend libraries depend
340 * on are now available
342 static void
343 check_be_array(
344 nscd_nsw_state_t *s)
346 int i;
347 char *dbn;
348 char *srcn;
349 struct __nsw_lookup_v1 *lkp;
351 dbn = NSCD_NSW_DB_NAME(s->dbi);
353 s->recheck_be = nscd_false;
354 for (i = 0; i < s->max_src; i++) {
356 if (i == 0)
357 lkp = s->config->lookups;
358 else
359 lkp = lkp->next;
360 if (lkp == NULL)
361 return;
363 srcn = lkp->service_name;
366 * it is possible that 's->be[i]' could not be
367 * initialized earlier due to a dependency not
368 * yet available (e.g., nis on domain name),
369 * try to initialize one more time
371 if (s->be[i] == NULL && s->be_constr[i] != NULL) {
372 s->be[i] = (s->be_constr[i])(dbn, srcn, 0);
373 if (s->be[i] == NULL)
374 s->recheck_be = nscd_true;
379 static nscd_rc_t
380 _get_nsw_state_int(
381 nss_db_root_t *rootp,
382 nscd_nsw_params_t *params,
383 thread_t *tid)
386 nscd_nsw_state_t *ret = NULL;
387 nscd_nsw_config_t **nswcfg;
388 nscd_nsw_state_base_t *base;
389 nscd_state_ctrl_t *ctrl_p;
390 int thread_only = 0, wait_cond = 0;
391 char *me = "_get_nsw_state_int";
392 int dbi;
393 nscd_rc_t rc;
395 dbi = params->dbi;
398 * no nsw state will be reused, if asked to use
399 * default config. So create the new structures
400 * used by the switch engine and the new nsw state
402 if (params->p.flags & NSS_USE_DEFAULT_CONFIG) {
403 rc = _nscd_create_sw_struct(dbi, -1, (char *)params->p.name,
404 (char *)params->p.default_config, NULL, params);
405 if (rc != NSCD_SUCCESS)
406 return (rc);
408 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
409 (me, "no base nsw config created for %s (sources: %s)\n",
410 params->p.name, params->p.default_config);
412 ret = _nscd_create_nsw_state(params);
413 if (ret == NULL)
414 return (NSCD_CREATE_NSW_STATE_FAILED);
415 rootp->s = (struct nss_db_state *)ret;
416 return (NSCD_SUCCESS);
420 * if getting a nsw state for a request from the compat
421 * backend, create the new switch structures if this
422 * is the first time around for a passwd, shadow, group,
423 * or user_attr database
425 if (params->compati != -1) {
427 nscd_nsw_config_t **nswcfg1, **nswcfg2;
428 int i = params->compati;
430 dbi = i;
433 * retrieve the pointer space which contains a
434 * pointer pointing to the nsswitch config
435 * structure for the compat backend
437 nswcfg = (nscd_nsw_config_t **)_nscd_get(
438 (nscd_acc_data_t *)nscd_nsw_config[i]);
441 * If nsswitch config structure not created yet,
442 * get the config string from the passwd_compat
443 * or group_compat DB and create the structure.
445 if (*nswcfg == NULL) {
446 /* Wait first if it's being created. */
447 nswcfg2 = (nscd_nsw_config_t **)_nscd_mutex_lock(
448 (nscd_acc_data_t *)nscd_nsw_config[i]);
450 /* still not created yet */
451 if (*nswcfg2 == NULL) {
453 * get the nsswitch config string specified
454 * for passwd_compat or group_compat
456 nswcfg1 = (nscd_nsw_config_t **)_nscd_get(
457 (nscd_acc_data_t *)
458 nscd_nsw_config[params->cfgdbi]);
459 if (nswcfg1 == NULL) {
460 _NSCD_LOG(NSCD_LOG_NSW_STATE,
461 NSCD_LOG_LEVEL_ERROR)
462 (me, "no nsw config for %s\n",
463 params->p.name);
465 (void) _nscd_mutex_unlock(
466 (nscd_acc_data_t *)nswcfg2);
467 _nscd_release((nscd_acc_data_t *)
468 nswcfg);
470 return (NSCD_CREATE_NSW_STATE_FAILED);
473 rc = _nscd_create_sw_struct(i, params->cfgdbi,
474 params->p.name, (*nswcfg1)->nsw_cfg_str,
475 NULL, params);
476 _nscd_release((nscd_acc_data_t *)nswcfg1);
478 if (rc == NSCD_SUCCESS) {
479 _NSCD_LOG(NSCD_LOG_NSW_STATE,
480 NSCD_LOG_LEVEL_DEBUG)
481 (me, "nsw config created for %s (%s)\n",
482 params->p.name,
483 (*nswcfg1)->nsw_cfg_str);
484 } else {
485 (void) _nscd_mutex_unlock(
486 (nscd_acc_data_t *)nswcfg2);
487 _nscd_release((nscd_acc_data_t *)
488 nswcfg);
489 return (rc);
492 (void) _nscd_mutex_unlock((nscd_acc_data_t *)nswcfg2);
494 _nscd_release((nscd_acc_data_t *)nswcfg);
497 (void) rw_rdlock(&nscd_nsw_state_base_lock);
498 base = nscd_nsw_state_base[dbi];
499 (void) rw_unlock(&nscd_nsw_state_base_lock);
500 if (base == NULL)
501 assert(base != NULL);
504 * If list is not empty, return the first one on list.
505 * Otherwise, create and return a new db state if the
506 * limit is not reached. if reacehed, wait for the 'one
507 * is available' signal.
509 assert(base == (nscd_nsw_state_base_t *)_nscd_mutex_lock(
510 (nscd_acc_data_t *)base));
512 if (tid == NULL) {
513 ctrl_p = &base->nsw_state;
514 } else {
515 thread_only = 1;
516 ctrl_p = &base->nsw_state_thr;
518 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
519 _nscd_logit(me, "per thread nsw state info: \n");
520 _nscd_logit(me, "tid = %d\n", *tid);
521 _nscd_logit(me, "tid in base = %d\n", base->tid);
522 _nscd_logit(me, "number of free nsw_state = %d\n",
523 ctrl_p->free);
524 _nscd_logit(me, "number of nsw state allocated = %d\n",
525 ctrl_p->allocated);
526 _nscd_logit(me, "first nsw state on list = %p\n",
527 ctrl_p->first);
528 _nscd_logit(me, "number of waiter = %d\n",
529 ctrl_p->waiter);
534 if (ctrl_p->first == NULL && ctrl_p->allocated == ctrl_p->max)
535 wait_cond = 1;
536 else if (thread_only && base->used_by_thr && base->tid != *tid)
537 wait_cond = 1;
539 if (wait_cond) {
541 ctrl_p->waiter++;
543 while (wait_cond) {
544 if (!thread_only)
545 _NSCD_LOG(NSCD_LOG_NSW_STATE,
546 NSCD_LOG_LEVEL_DEBUG)
547 (me, "waiting for nsw state signal\n");
548 else
549 _NSCD_LOG(NSCD_LOG_NSW_STATE,
550 NSCD_LOG_LEVEL_DEBUG)
551 (me, "waiting for per thread "
552 "nsw state signal\n");
554 if (thread_only) {
555 _nscd_cond_wait((nscd_acc_data_t *)base,
556 &base->thr_cond);
558 if (base->used_by_thr == 0 &&
559 ctrl_p->first != NULL)
560 wait_cond = 0;
561 } else {
562 _nscd_cond_wait((nscd_acc_data_t *)base, NULL);
564 if (ctrl_p->first != NULL)
565 wait_cond = 0;
568 if (!thread_only)
569 _NSCD_LOG(NSCD_LOG_NSW_STATE,
570 NSCD_LOG_LEVEL_DEBUG)
571 (me, "woke from cond wait ...wait_cond = %d\n",
572 wait_cond);
573 else
575 _NSCD_LOG(NSCD_LOG_NSW_STATE,
576 NSCD_LOG_LEVEL_DEBUG)
577 (me, "woke from cond wait (per thread) "
578 "...wait_cond = %d\n", wait_cond);
582 ctrl_p->waiter--;
585 if (ctrl_p->first == NULL) {
586 int geti;
589 * for lookup calls from the compat backend
590 * uses the switch policy for passwd_compat
591 * or group_compat
593 if (params->compati != -1)
594 geti = params->compati;
595 else
596 geti = params->dbi;
598 params->nswcfg = (nscd_nsw_config_t **)_nscd_get(
599 (nscd_acc_data_t *)nscd_nsw_config[geti]);
600 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
601 (me, "got a nsw config %p for index %d\n",
602 params->nswcfg, geti);
604 ctrl_p->first = _nscd_create_nsw_state(params);
605 if (ctrl_p->first != NULL) {
606 if (tid == NULL) {
607 _NSCD_LOG(NSCD_LOG_NSW_STATE,
608 NSCD_LOG_LEVEL_DEBUG)
609 (me, "got a new nsw_state %p\n", ctrl_p->first);
610 } else {
611 _NSCD_LOG(NSCD_LOG_NSW_STATE,
612 NSCD_LOG_LEVEL_DEBUG)
613 (me, "got a new per thread nsw_state %p\n",
614 ctrl_p->first);
616 ctrl_p->allocated++;
617 ctrl_p->free++;
618 } else {
619 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
620 (me, "error: unable to obtain a nsw state\n");
621 _nscd_mutex_unlock((nscd_acc_data_t *)base);
622 return (NSCD_CREATE_NSW_STATE_FAILED);
626 ret = ctrl_p->first;
627 if (ret->recheck_be == nscd_true)
628 check_be_array(ret);
629 ctrl_p->first = ret->next;
630 ret->next = NULL;
631 ctrl_p->free--;
632 if (thread_only) {
633 base->tid = *tid;
634 base->used_by_thr = 1;
636 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
637 _nscd_logit(me, "\t\t\tgot a per thread nsw "
638 "state %p: \n", ret);
639 _nscd_logit(me, "tid = %d\n", *tid);
640 _nscd_logit(me, "tid in base = %d\n", base->tid);
641 _nscd_logit(me, "number of free nsw_state = %d\n",
642 ctrl_p->free);
643 _nscd_logit(me, "number od nsw state allocated = %d\n",
644 ctrl_p->allocated);
645 _nscd_logit(me, "first nsw state on list = %p\n",
646 ctrl_p->first);
647 _nscd_logit(me, "number of waiter = %d\n",
648 ctrl_p->waiter);
651 else
652 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
653 (me, "got old nsw state %p\n", ret);
656 * reference count the nsswitch state base bfore handing out
657 * the nsswitch state
659 ret->base = (nscd_nsw_state_base_t *)
660 _nscd_get((nscd_acc_data_t *)base);
662 _nscd_mutex_unlock((nscd_acc_data_t *)base);
664 rootp->s = (struct nss_db_state *)ret;
666 return (NSCD_SUCCESS);
669 nscd_rc_t
670 _nscd_get_nsw_state(
671 nss_db_root_t *rootp,
672 nscd_nsw_params_t *params)
674 return (_get_nsw_state_int(rootp, params, NULL));
677 nscd_rc_t
678 _nscd_get_nsw_state_thread(
679 nss_db_root_t *rootp,
680 nscd_nsw_params_t *params)
682 thread_t tid = thr_self();
683 return (_get_nsw_state_int(rootp, params, &tid));
687 static void
688 _put_nsw_state_int(
689 nscd_nsw_state_t *s,
690 thread_t *tid)
693 nscd_nsw_state_base_t *base;
694 nscd_state_ctrl_t *ctrl_p;
695 int thread_only = 0;
696 char *me = "_put_nsw_state_int";
698 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
699 (me, "put back a nsw state\n");
701 if (s == NULL) {
702 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
703 (me, "nsw state is NULL, nothing to put back\n");
704 return;
708 * no need to put back if the nsw state is not on any base
709 * but need to free the resources used
711 if ((*s->nsw_cfg_p)->nobase == 1) {
712 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
713 (me, "no base nsw state, freeing resources ...\n");
715 _nscd_free_nsw_state(s);
716 return;
719 if (tid != NULL)
720 thread_only = 1;
722 base = s->base;
724 if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) {
725 /* base has been freed or no longer valid, free the nsw state */
726 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
727 (me, "nsw state base gone or no longer valid, freeing %p\n", s);
728 _nscd_free_nsw_state(s);
729 return;
732 if (thread_only)
733 ctrl_p = &base->nsw_state_thr;
734 else
735 ctrl_p = &base->nsw_state;
737 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
738 _nscd_logit(me, "before returning the nsw state: \n");
739 _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
740 _nscd_logit(me, "tid in base = %d\n", base->tid);
741 _nscd_logit(me, "number of free nsw_state = %d\n",
742 ctrl_p->free);
743 _nscd_logit(me, "number od nsw state allocated = %d\n",
744 ctrl_p->allocated);
745 _nscd_logit(me, "first nsw state on list = %p\n",
746 ctrl_p->first);
747 _nscd_logit(me, "number of waiter = %d\n", ctrl_p->waiter);
750 if (ctrl_p->first != NULL) {
751 s->next = ctrl_p->first;
752 ctrl_p->first = s;
753 } else {
754 ctrl_p->first = s;
755 s->next = NULL;
757 ctrl_p->free++;
760 * Remove reference to the nsswitch state base.
762 _nscd_release((nscd_acc_data_t *)base);
763 s->base = NULL;
765 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
766 (me, "signaling waiter thread_only = %d..\n", thread_only);
768 if (thread_only && ctrl_p->free == ctrl_p->allocated) {
769 assert(ctrl_p->first != NULL);
770 base->used_by_thr = 0;
771 if (ctrl_p->waiter > 0) {
772 (void) cond_signal(&base->thr_cond);
776 if (!thread_only && ctrl_p->waiter > 0) {
778 _nscd_cond_signal((nscd_acc_data_t *)base);
781 _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) {
782 _nscd_logit(me, "after the nsw state is returned: \n");
783 _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid);
784 _nscd_logit(me, "tid in base = %d\n", base->tid);
785 _nscd_logit(me, "number of free nsw_state = %d\n",
786 ctrl_p->free);
787 _nscd_logit(me, "number od nsw state allocated = %d\n",
788 ctrl_p->allocated);
789 _nscd_logit(me, "first nsw state on list = %p\n",
790 ctrl_p->first);
791 _nscd_logit(me, "tnumber of waiter = %d\n", ctrl_p->waiter);
794 _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG)
795 (me, "done putting back nsw state %p, thread_only = %d\n",
796 s, thread_only);
798 _nscd_mutex_unlock((nscd_acc_data_t *)base);
802 void
803 _nscd_put_nsw_state(
804 nscd_nsw_state_t *s)
806 _put_nsw_state_int(s, NULL);
809 void
810 _nscd_put_nsw_state_thread(
811 nscd_nsw_state_t *s)
813 thread_t tid = thr_self();
814 _put_nsw_state_int(s, &tid);
817 nscd_rc_t
818 _nscd_init_nsw_state_base(
819 int dbi,
820 int compat_basei,
821 int lock)
823 int cfgdbi;
824 nscd_nsw_state_base_t *base = NULL;
825 char *me = "_nscd_init_nsw_state_base";
827 if (lock)
828 (void) rw_rdlock(&nscd_nsw_state_base_lock);
830 base = (nscd_nsw_state_base_t *)_nscd_alloc(
831 NSCD_DATA_NSW_STATE_BASE,
832 sizeof (nscd_nsw_state_base_t),
833 _nscd_free_nsw_state_base,
834 NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND);
836 if (base == NULL) {
837 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
838 NSCD_LOG_LEVEL_ERROR)
839 (me, "not able to allocate a nsw state base\n");
840 if (lock)
841 (void) rw_unlock(&nscd_nsw_state_base_lock);
842 return (NSCD_NO_MEMORY);
844 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
845 (me, "nsw state base %p allocated\n", base);
848 * initialize and activate the new nss_nsw_state base
850 base->dbi = dbi;
851 if (compat_basei != -1)
852 cfgdbi = compat_basei;
853 else
854 cfgdbi = dbi;
856 base->nsw_state.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_db;
857 base->nsw_state_thr.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_thread;
859 nscd_nsw_state_base[dbi] = (nscd_nsw_state_base_t *)_nscd_set(
860 (nscd_acc_data_t *)nscd_nsw_state_base[dbi],
861 (nscd_acc_data_t *)base);
863 if (lock)
864 (void) rw_unlock(&nscd_nsw_state_base_lock);
866 return (NSCD_SUCCESS);
869 nscd_rc_t
870 _nscd_init_all_nsw_state_base()
872 int i;
873 nscd_rc_t rc;
874 char *me = "_nscd_init_all_nsw_state_base";
876 (void) rw_rdlock(&nscd_nsw_state_base_lock);
878 for (i = 0; i < NSCD_NUM_DB; i++) {
880 rc = _nscd_init_nsw_state_base(i, -1, 0);
882 if (rc != NSCD_SUCCESS) {
883 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG,
884 NSCD_LOG_LEVEL_ERROR)
885 (me, "not able to initialize a nsw db state "
886 "base (%d)\n", i);
888 (void) rw_unlock(&nscd_nsw_state_base_lock);
889 return (rc);
892 _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
893 (me, "all nsw state base initialized\n");
895 (void) rw_unlock(&nscd_nsw_state_base_lock);
897 return (NSCD_SUCCESS);
900 nscd_rc_t
901 _nscd_alloc_nsw_state_base()
904 (void) rw_rdlock(&nscd_nsw_state_base_lock);
906 nscd_nsw_state_base = calloc(NSCD_NUM_DB,
907 sizeof (nscd_nsw_state_base_t *));
908 if (nscd_nsw_state_base == NULL) {
909 (void) rw_unlock(&nscd_nsw_state_base_lock);
910 return (NSCD_NO_MEMORY);
913 (void) rw_rdlock(&nscd_nsw_state_base_lock);
915 return (NSCD_SUCCESS);