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