/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include #include "nscd_switch.h" #include "nscd_log.h" /* * nscd_nsw_state_t list for each nss database. Protected * by the readers/writer lock nscd_nsw_state_base_lock. */ nscd_nsw_state_base_t **nscd_nsw_state_base; static rwlock_t nscd_nsw_state_base_lock = DEFAULTRWLOCK; static void _nscd_free_nsw_state( nscd_nsw_state_t *s) { int i; char *me = "_nscd_free_nsw_state"; _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "freeing nsw state = %p\n", s); if (s == NULL) return; if (s->nsw_cfg_p != NULL) /* * an nsw state without base does not reference * count the nsw config data (ie not using a * shared one), so the one created for it should * be freed */ if ((*s->nsw_cfg_p)->nobase != 1) _nscd_release((nscd_acc_data_t *)s->nsw_cfg_p); else (void) _nscd_set((nscd_acc_data_t *)s->nsw_cfg_p, NULL); if (s->be_db_pp != NULL) { for (i = 0; i < s->max_src; i++) { if (s->be_db_pp[i] == NULL) continue; _nscd_release((nscd_acc_data_t *)s->be_db_pp[i]); _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "release db be ptr %p\n", s->be_db_pp[i]); } free(s->be_db_pp); } if (s->be != NULL) { for (i = 0; i < s->max_src; i++) { if (s->be[i] == NULL) continue; if (s->getent == 1) (void) NSS_INVOKE_DBOP(s->be[i], NSS_DBOP_ENDENT, 0); (void) NSS_INVOKE_DBOP(s->be[i], NSS_DBOP_DESTRUCTOR, 0); } free(s->be); } if (s->be_constr != NULL) free(s->be_constr); if (s->be_version_p != NULL) free(s->be_version_p); /* remove reference to the nsw state base */ if (s->base != NULL) { _nscd_release((nscd_acc_data_t *)s->base); s->base = NULL; } _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "nsw state %p freed \n", s); free(s); } static void _nscd_free_nsw_state_base( nscd_acc_data_t *data) { nscd_nsw_state_base_t *base = (nscd_nsw_state_base_t *)data; nscd_nsw_state_t *s, *ts; int i; char *me = "_nscd_free_nsw_state_base"; _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) (me, "freeing db state base %p\n", base); if (base == NULL) return; for (i = 0; i < 2; i++) { if (i == 1) s = base->nsw_state.first; else s = base->nsw_state_thr.first; while (s != NULL) { ts = s->next; _nscd_free_nsw_state(s); s = ts; } } _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) (me, "nsw state base %p freed \n", base); } void _nscd_free_all_nsw_state_base() { nscd_nsw_state_base_t *base; int i; char *me = "_nscd_free_all_nsw_state_base"; _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) (me, "freeing all db state base\n"); (void) rw_wrlock(&nscd_nsw_state_base_lock); for (i = 0; i < NSCD_NUM_DB; i++) { base = nscd_nsw_state_base[i]; _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) (me, "freeing db state base (%d) %p \n", i, base); if (base == NULL) continue; nscd_nsw_state_base[i] = (nscd_nsw_state_base_t *) _nscd_set((nscd_acc_data_t *)base, NULL); } (void) rw_unlock(&nscd_nsw_state_base_lock); } static nscd_nsw_state_t * _nscd_create_nsw_state( nscd_nsw_params_t *params) { nscd_nsw_state_t *s; nscd_nsw_config_t *nsw_cfg; nscd_db_t **be_db_p, *be_db; int i, nobe = 1; char *me = "_nscd_create_nsw_state"; _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "creating nsw state...\n"); s = calloc(1, sizeof (nscd_nsw_state_t)); if (s == NULL) { if ((*s->nsw_cfg_p)->nobase != 1) _nscd_release((nscd_acc_data_t *)params->nswcfg); _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "not able to allocate a nsw state\n"); return (NULL); } else _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "nsw state %p allocated\n", s); s->dbi = params->dbi; s->next = NULL; nsw_cfg = *params->nswcfg; s->nsw_cfg_p = params->nswcfg; s->config = nsw_cfg->nsw_config; s->max_src = nsw_cfg->max_src; s->p = params->p; s->be = calloc(s->max_src, sizeof (nss_backend_t **)); if (s->be == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "not able to allocate s->be\n"); _nscd_free_nsw_state(s); return (NULL); } else { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "db be array %p allocated\n", s->be); } s->be_constr = (nss_backend_constr_t *)calloc(s->max_src, sizeof (nss_backend_constr_t)); if (s->be_constr == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "not able to allocate s->be_constr\n"); _nscd_free_nsw_state(s); return (NULL); } else { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "db be constructor array %p allocated\n", s->be_constr); } s->be_version_p = (void **)calloc(s->max_src, sizeof (void *)); if (s->be_version_p == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "not able to allocate s->be_version_p\n"); _nscd_free_nsw_state(s); return (NULL); } else { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "db be version ptr array %p allocated\n", s->be_version_p); } s->be_db_pp = calloc(s->max_src, sizeof (nscd_db_t ***)); if (s->be_db_pp == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "not able to allocate s->be_db_pp\n"); _nscd_free_nsw_state(s); return (NULL); } else { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "be_db_pp array %p allocated\n", s->be_db_pp); } /* create the source:database backends */ for (i = 0; i < s->max_src; i++) { nss_backend_t *be; int srci; char *srcn; const char *dbn; struct __nsw_lookup_v1 *lkp; const nscd_db_entry_t *dbe; nscd_be_info_t *be_info; if (i == 0) lkp = s->config->lookups; else lkp = lkp->next; if (lkp == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "error: lkp is NULL\n"); _nscd_free_nsw_state(s); return (NULL); } srci = nsw_cfg->src_idx[i]; srcn = lkp->service_name; _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "source name = %s, index = %d\n", srcn, srci); be_db_p = (nscd_db_t **)_nscd_get( (nscd_acc_data_t *)nscd_src_backend_db[srci]); if (be_db_p == NULL) { _nscd_free_nsw_state(s); return (NULL); } be_db = *be_db_p; s->be_db_pp[i] = be_db_p; _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "be db ptr array %p referenced\n", be_db_p); be_info = NULL; be = NULL; dbn = params->p.name; dbe = _nscd_get_db_entry(be_db, NSCD_DATA_BACKEND_INFO, (const char *)dbn, NSCD_GET_FIRST_DB_ENTRY, 0); if (dbe != NULL) be_info = (nscd_be_info_t *)*(dbe->data_array); if (be_info == NULL || be_info->be_constr == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "no backend info or be_constr is NULL " "for <%s : %s>\n", NSCD_NSW_SRC_NAME(srci), dbn); } else { s->be_constr[i] = be_info->be_constr; be = (be_info->be_constr)(dbn, NSCD_NSW_SRC_NAME(srci), 0); if (be == NULL) s->recheck_be = nscd_true; } if (be == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "not able to init be for <%s : %s>\n", NSCD_NSW_SRC_NAME(srci), dbn); _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "releasing db be ptr %p\n", be_db_p); _nscd_release((nscd_acc_data_t *)be_db_p); s->be_db_pp[i] = NULL; continue; } s->be[i] = be; s->be_version_p[i] = be_info->be_version; _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "backend version is %p\n", be_info->be_version); nobe = 0; } if (nobe == 1) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "NO backend found, returning NULL\n"); _nscd_free_nsw_state(s); return (NULL); } return (s); } /* * Try to initialize the backend instances one more time * in case the dependencies the backend libraries depend * on are now available */ static void check_be_array( nscd_nsw_state_t *s) { int i; char *dbn; char *srcn; struct __nsw_lookup_v1 *lkp; dbn = NSCD_NSW_DB_NAME(s->dbi); s->recheck_be = nscd_false; for (i = 0; i < s->max_src; i++) { if (i == 0) lkp = s->config->lookups; else lkp = lkp->next; if (lkp == NULL) return; srcn = lkp->service_name; /* * it is possible that 's->be[i]' could not be * initialized earlier due to a dependency not * yet available (e.g., nis on domain name), * try to initialize one more time */ if (s->be[i] == NULL && s->be_constr[i] != NULL) { s->be[i] = (s->be_constr[i])(dbn, srcn, 0); if (s->be[i] == NULL) s->recheck_be = nscd_true; } } } static nscd_rc_t _get_nsw_state_int( nss_db_root_t *rootp, nscd_nsw_params_t *params, thread_t *tid) { nscd_nsw_state_t *ret = NULL; nscd_nsw_config_t **nswcfg; nscd_nsw_state_base_t *base; nscd_state_ctrl_t *ctrl_p; int thread_only = 0, wait_cond = 0; char *me = "_get_nsw_state_int"; int dbi; nscd_rc_t rc; dbi = params->dbi; /* * no nsw state will be reused, if asked to use * default config. So create the new structures * used by the switch engine and the new nsw state */ if (params->p.flags & NSS_USE_DEFAULT_CONFIG) { rc = _nscd_create_sw_struct(dbi, -1, (char *)params->p.name, (char *)params->p.default_config, NULL, params); if (rc != NSCD_SUCCESS) return (rc); _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "no base nsw config created for %s (sources: %s)\n", params->p.name, params->p.default_config); ret = _nscd_create_nsw_state(params); if (ret == NULL) return (NSCD_CREATE_NSW_STATE_FAILED); rootp->s = (struct nss_db_state *)ret; return (NSCD_SUCCESS); } /* * if getting a nsw state for a request from the compat * backend, create the new switch structures if this * is the first time around for a passwd, shadow, group, * or user_attr database */ if (params->compati != -1) { nscd_nsw_config_t **nswcfg1, **nswcfg2; int i = params->compati; dbi = i; /* * retrieve the pointer space which contains a * pointer pointing to the nsswitch config * structure for the compat backend */ nswcfg = (nscd_nsw_config_t **)_nscd_get( (nscd_acc_data_t *)nscd_nsw_config[i]); /* * If nsswitch config structure not created yet, * get the config string from the passwd_compat * or group_compat DB and create the structure. */ if (*nswcfg == NULL) { /* Wait first if it's being created. */ nswcfg2 = (nscd_nsw_config_t **)_nscd_mutex_lock( (nscd_acc_data_t *)nscd_nsw_config[i]); /* still not created yet */ if (*nswcfg2 == NULL) { /* * get the nsswitch config string specified * for passwd_compat or group_compat */ nswcfg1 = (nscd_nsw_config_t **)_nscd_get( (nscd_acc_data_t *) nscd_nsw_config[params->cfgdbi]); if (nswcfg1 == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "no nsw config for %s\n", params->p.name); (void) _nscd_mutex_unlock( (nscd_acc_data_t *)nswcfg2); _nscd_release((nscd_acc_data_t *) nswcfg); return (NSCD_CREATE_NSW_STATE_FAILED); } rc = _nscd_create_sw_struct(i, params->cfgdbi, params->p.name, (*nswcfg1)->nsw_cfg_str, NULL, params); _nscd_release((nscd_acc_data_t *)nswcfg1); if (rc == NSCD_SUCCESS) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "nsw config created for %s (%s)\n", params->p.name, (*nswcfg1)->nsw_cfg_str); } else { (void) _nscd_mutex_unlock( (nscd_acc_data_t *)nswcfg2); _nscd_release((nscd_acc_data_t *) nswcfg); return (rc); } } (void) _nscd_mutex_unlock((nscd_acc_data_t *)nswcfg2); } _nscd_release((nscd_acc_data_t *)nswcfg); } (void) rw_rdlock(&nscd_nsw_state_base_lock); base = nscd_nsw_state_base[dbi]; (void) rw_unlock(&nscd_nsw_state_base_lock); if (base == NULL) assert(base != NULL); /* * If list is not empty, return the first one on list. * Otherwise, create and return a new db state if the * limit is not reached. if reacehed, wait for the 'one * is available' signal. */ assert(base == (nscd_nsw_state_base_t *)_nscd_mutex_lock( (nscd_acc_data_t *)base)); if (tid == NULL) { ctrl_p = &base->nsw_state; } else { thread_only = 1; ctrl_p = &base->nsw_state_thr; _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { _nscd_logit(me, "per thread nsw state info: \n"); _nscd_logit(me, "tid = %d\n", *tid); _nscd_logit(me, "tid in base = %d\n", base->tid); _nscd_logit(me, "number of free nsw_state = %d\n", ctrl_p->free); _nscd_logit(me, "number of nsw state allocated = %d\n", ctrl_p->allocated); _nscd_logit(me, "first nsw state on list = %p\n", ctrl_p->first); _nscd_logit(me, "number of waiter = %d\n", ctrl_p->waiter); } } if (ctrl_p->first == NULL && ctrl_p->allocated == ctrl_p->max) wait_cond = 1; else if (thread_only && base->used_by_thr && base->tid != *tid) wait_cond = 1; if (wait_cond) { ctrl_p->waiter++; while (wait_cond) { if (!thread_only) _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "waiting for nsw state signal\n"); else _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "waiting for per thread " "nsw state signal\n"); if (thread_only) { _nscd_cond_wait((nscd_acc_data_t *)base, &base->thr_cond); if (base->used_by_thr == 0 && ctrl_p->first != NULL) wait_cond = 0; } else { _nscd_cond_wait((nscd_acc_data_t *)base, NULL); if (ctrl_p->first != NULL) wait_cond = 0; } if (!thread_only) _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "woke from cond wait ...wait_cond = %d\n", wait_cond); else _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "woke from cond wait (per thread) " "...wait_cond = %d\n", wait_cond); } ctrl_p->waiter--; } if (ctrl_p->first == NULL) { int geti; /* * for lookup calls from the compat backend * uses the switch policy for passwd_compat * or group_compat */ if (params->compati != -1) geti = params->compati; else geti = params->dbi; params->nswcfg = (nscd_nsw_config_t **)_nscd_get( (nscd_acc_data_t *)nscd_nsw_config[geti]); _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "got a nsw config %p for index %d\n", params->nswcfg, geti); ctrl_p->first = _nscd_create_nsw_state(params); if (ctrl_p->first != NULL) { if (tid == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "got a new nsw_state %p\n", ctrl_p->first); } else { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "got a new per thread nsw_state %p\n", ctrl_p->first); } ctrl_p->allocated++; ctrl_p->free++; } else { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR) (me, "error: unable to obtain a nsw state\n"); _nscd_mutex_unlock((nscd_acc_data_t *)base); return (NSCD_CREATE_NSW_STATE_FAILED); } } ret = ctrl_p->first; if (ret->recheck_be == nscd_true) check_be_array(ret); ctrl_p->first = ret->next; ret->next = NULL; ctrl_p->free--; if (thread_only) { base->tid = *tid; base->used_by_thr = 1; _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { _nscd_logit(me, "\t\t\tgot a per thread nsw " "state %p: \n", ret); _nscd_logit(me, "tid = %d\n", *tid); _nscd_logit(me, "tid in base = %d\n", base->tid); _nscd_logit(me, "number of free nsw_state = %d\n", ctrl_p->free); _nscd_logit(me, "number od nsw state allocated = %d\n", ctrl_p->allocated); _nscd_logit(me, "first nsw state on list = %p\n", ctrl_p->first); _nscd_logit(me, "number of waiter = %d\n", ctrl_p->waiter); } } else _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "got old nsw state %p\n", ret); /* * reference count the nsswitch state base bfore handing out * the nsswitch state */ ret->base = (nscd_nsw_state_base_t *) _nscd_get((nscd_acc_data_t *)base); _nscd_mutex_unlock((nscd_acc_data_t *)base); rootp->s = (struct nss_db_state *)ret; return (NSCD_SUCCESS); } nscd_rc_t _nscd_get_nsw_state( nss_db_root_t *rootp, nscd_nsw_params_t *params) { return (_get_nsw_state_int(rootp, params, NULL)); } nscd_rc_t _nscd_get_nsw_state_thread( nss_db_root_t *rootp, nscd_nsw_params_t *params) { thread_t tid = thr_self(); return (_get_nsw_state_int(rootp, params, &tid)); } static void _put_nsw_state_int( nscd_nsw_state_t *s, thread_t *tid) { nscd_nsw_state_base_t *base; nscd_state_ctrl_t *ctrl_p; int thread_only = 0; char *me = "_put_nsw_state_int"; _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "put back a nsw state\n"); if (s == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "nsw state is NULL, nothing to put back\n"); return; } /* * no need to put back if the nsw state is not on any base * but need to free the resources used */ if ((*s->nsw_cfg_p)->nobase == 1) { _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "no base nsw state, freeing resources ...\n"); _nscd_free_nsw_state(s); return; } if (tid != NULL) thread_only = 1; base = s->base; if (_nscd_mutex_lock((nscd_acc_data_t *)base) == NULL) { /* base has been freed or no longer valid, free the nsw state */ _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "nsw state base gone or no longer valid, freeing %p\n", s); _nscd_free_nsw_state(s); return; } if (thread_only) ctrl_p = &base->nsw_state_thr; else ctrl_p = &base->nsw_state; _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { _nscd_logit(me, "before returning the nsw state: \n"); _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid); _nscd_logit(me, "tid in base = %d\n", base->tid); _nscd_logit(me, "number of free nsw_state = %d\n", ctrl_p->free); _nscd_logit(me, "number od nsw state allocated = %d\n", ctrl_p->allocated); _nscd_logit(me, "first nsw state on list = %p\n", ctrl_p->first); _nscd_logit(me, "number of waiter = %d\n", ctrl_p->waiter); } if (ctrl_p->first != NULL) { s->next = ctrl_p->first; ctrl_p->first = s; } else { ctrl_p->first = s; s->next = NULL; } ctrl_p->free++; /* * Remove reference to the nsswitch state base. */ _nscd_release((nscd_acc_data_t *)base); s->base = NULL; _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "signaling waiter thread_only = %d..\n", thread_only); if (thread_only && ctrl_p->free == ctrl_p->allocated) { assert(ctrl_p->first != NULL); base->used_by_thr = 0; if (ctrl_p->waiter > 0) { (void) cond_signal(&base->thr_cond); } } if (!thread_only && ctrl_p->waiter > 0) { _nscd_cond_signal((nscd_acc_data_t *)base); } _NSCD_LOG_IF(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) { _nscd_logit(me, "after the nsw state is returned: \n"); _nscd_logit(me, "tid = %d\n", (tid == NULL) ? -1 : *tid); _nscd_logit(me, "tid in base = %d\n", base->tid); _nscd_logit(me, "number of free nsw_state = %d\n", ctrl_p->free); _nscd_logit(me, "number od nsw state allocated = %d\n", ctrl_p->allocated); _nscd_logit(me, "first nsw state on list = %p\n", ctrl_p->first); _nscd_logit(me, "tnumber of waiter = %d\n", ctrl_p->waiter); } _NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_DEBUG) (me, "done putting back nsw state %p, thread_only = %d\n", s, thread_only); _nscd_mutex_unlock((nscd_acc_data_t *)base); } void _nscd_put_nsw_state( nscd_nsw_state_t *s) { _put_nsw_state_int(s, NULL); } void _nscd_put_nsw_state_thread( nscd_nsw_state_t *s) { thread_t tid = thr_self(); _put_nsw_state_int(s, &tid); } nscd_rc_t _nscd_init_nsw_state_base( int dbi, int compat_basei, int lock) { int cfgdbi; nscd_nsw_state_base_t *base = NULL; char *me = "_nscd_init_nsw_state_base"; if (lock) (void) rw_rdlock(&nscd_nsw_state_base_lock); base = (nscd_nsw_state_base_t *)_nscd_alloc( NSCD_DATA_NSW_STATE_BASE, sizeof (nscd_nsw_state_base_t), _nscd_free_nsw_state_base, NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND); if (base == NULL) { _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) (me, "not able to allocate a nsw state base\n"); if (lock) (void) rw_unlock(&nscd_nsw_state_base_lock); return (NSCD_NO_MEMORY); } _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) (me, "nsw state base %p allocated\n", base); /* * initialize and activate the new nss_nsw_state base */ base->dbi = dbi; if (compat_basei != -1) cfgdbi = compat_basei; else cfgdbi = dbi; base->nsw_state.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_db; base->nsw_state_thr.max = NSCD_SW_CFG(cfgdbi).max_nsw_state_per_thread; nscd_nsw_state_base[dbi] = (nscd_nsw_state_base_t *)_nscd_set( (nscd_acc_data_t *)nscd_nsw_state_base[dbi], (nscd_acc_data_t *)base); if (lock) (void) rw_unlock(&nscd_nsw_state_base_lock); return (NSCD_SUCCESS); } nscd_rc_t _nscd_init_all_nsw_state_base() { int i; nscd_rc_t rc; char *me = "_nscd_init_all_nsw_state_base"; (void) rw_rdlock(&nscd_nsw_state_base_lock); for (i = 0; i < NSCD_NUM_DB; i++) { rc = _nscd_init_nsw_state_base(i, -1, 0); if (rc != NSCD_SUCCESS) { _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR) (me, "not able to initialize a nsw db state " "base (%d)\n", i); (void) rw_unlock(&nscd_nsw_state_base_lock); return (rc); } } _NSCD_LOG(NSCD_LOG_NSW_STATE | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG) (me, "all nsw state base initialized\n"); (void) rw_unlock(&nscd_nsw_state_base_lock); return (NSCD_SUCCESS); } nscd_rc_t _nscd_alloc_nsw_state_base() { (void) rw_rdlock(&nscd_nsw_state_base_lock); nscd_nsw_state_base = calloc(NSCD_NUM_DB, sizeof (nscd_nsw_state_base_t *)); if (nscd_nsw_state_base == NULL) { (void) rw_unlock(&nscd_nsw_state_base_lock); return (NSCD_NO_MEMORY); } (void) rw_rdlock(&nscd_nsw_state_base_lock); return (NSCD_SUCCESS); }