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