Print this page
8158 Want named threads API
9857 proc manpages should have LIBRARY section
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/nscd/nscd_getentctx.c
+++ new/usr/src/cmd/nscd/nscd_getentctx.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + *
25 + * Copyright 2018 Joyent, Inc.
24 26 */
25 27
26 28 #include <sys/ccompile.h>
27 29
28 30 #include <stdlib.h>
29 31 #include <assert.h>
30 32 #include <string.h>
31 33 #include <errno.h>
32 34 #include <fcntl.h>
33 35
34 36 #include "nscd_db.h"
35 37 #include "nscd_log.h"
36 38 #include "nscd_switch.h"
37 39 #include "nscd_door.h"
38 40
39 41 extern int _whoami;
40 42 static mutex_t getent_monitor_mutex = DEFAULTMUTEX;
41 43 static int getent_monitor_started = 0;
42 44
43 45 static rwlock_t getent_ctxDB_rwlock = DEFAULTRWLOCK;
44 46 static nscd_db_t *getent_ctxDB = NULL;
45 47
46 48 /*
47 49 * internal structure representing a nscd getent context
48 50 */
49 51 typedef struct nscd_getent_ctx {
50 52 int to_delete; /* this ctx no longer valid */
51 53 nscd_getent_context_t *ptr;
52 54 nscd_cookie_num_t cookie_num;
53 55 } nscd_getent_ctx_t;
54 56
55 57 /*
56 58 * nscd_getent_context_t list for each nss database. Protected
57 59 * by the readers/writer lock nscd_getent_ctx_lock.
58 60 */
59 61 nscd_getent_ctx_base_t **nscd_getent_ctx_base;
60 62 static rwlock_t nscd_getent_ctx_base_lock = DEFAULTRWLOCK;
61 63
62 64 extern nscd_db_entry_t *_nscd_walk_db(nscd_db_t *db, void **cookie);
63 65
64 66 static nscd_rc_t _nscd_init_getent_ctx_monitor();
65 67
66 68 /*
67 69 * FUNCTION: _nscd_create_getent_ctxDB
68 70 *
69 71 * Create the internal getent context database to keep track of the
70 72 * getent contexts currently being used.
71 73 */
72 74 nscd_db_t *
73 75 _nscd_create_getent_ctxDB()
74 76 {
75 77
76 78 nscd_db_t *ret;
77 79
78 80 (void) rw_wrlock(&getent_ctxDB_rwlock);
79 81
80 82 if (getent_ctxDB != NULL) {
81 83 (void) rw_unlock(&getent_ctxDB_rwlock);
82 84 return (getent_ctxDB);
83 85 }
84 86
85 87 ret = _nscd_alloc_db(NSCD_DB_SIZE_LARGE);
86 88
87 89 if (ret != NULL)
88 90 getent_ctxDB = ret;
89 91
90 92 (void) rw_unlock(&getent_ctxDB_rwlock);
91 93
92 94 return (ret);
93 95 }
94 96
95 97 /*
96 98 * FUNCTION: _nscd_add_getent_ctx
97 99 *
98 100 * Add a getent context to the internal context database.
99 101 */
100 102 static nscd_rc_t
101 103 _nscd_add_getent_ctx(
102 104 nscd_getent_context_t *ptr,
103 105 nscd_cookie_num_t cookie_num)
104 106 {
105 107 int size;
106 108 char buf[32];
107 109 nscd_db_entry_t *db_entry;
108 110 nscd_getent_ctx_t *gnctx;
109 111
110 112 if (ptr == NULL)
111 113 return (NSCD_INVALID_ARGUMENT);
112 114
113 115 (void) snprintf(buf, sizeof (buf), "%lld", cookie_num);
114 116
115 117 size = sizeof (*gnctx);
116 118
117 119 db_entry = _nscd_alloc_db_entry(NSCD_DATA_CTX_ADDR,
118 120 (const char *)buf, size, 1, 1);
119 121 if (db_entry == NULL)
120 122 return (NSCD_NO_MEMORY);
121 123
122 124 gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array);
123 125 gnctx->ptr = ptr;
124 126 gnctx->cookie_num = cookie_num;
125 127
126 128 (void) rw_wrlock(&getent_ctxDB_rwlock);
127 129 (void) _nscd_add_db_entry(getent_ctxDB, buf, db_entry,
128 130 NSCD_ADD_DB_ENTRY_FIRST);
129 131 (void) rw_unlock(&getent_ctxDB_rwlock);
130 132
131 133 return (NSCD_SUCCESS);
132 134 }
133 135
134 136 /*
135 137 * FUNCTION: _nscd_is_getent_ctx
136 138 *
137 139 * Check to see if a getent context can be found in the internal
138 140 * getent context database.
139 141 */
140 142 nscd_getent_context_t *
141 143 _nscd_is_getent_ctx(
142 144 nscd_cookie_num_t cookie_num)
143 145 {
144 146 char ptrstr[32];
145 147 const nscd_db_entry_t *db_entry;
146 148 nscd_getent_context_t *ret = NULL;
147 149 char *me = "_nscd_is_getent_ctx";
148 150
149 151 (void) snprintf(ptrstr, sizeof (ptrstr), "%lld", cookie_num);
150 152
151 153 (void) rw_rdlock(&getent_ctxDB_rwlock);
152 154
153 155 db_entry = _nscd_get_db_entry(getent_ctxDB, NSCD_DATA_CTX_ADDR,
154 156 (const char *)ptrstr, NSCD_GET_FIRST_DB_ENTRY, 0);
155 157
156 158 if (db_entry != NULL) {
157 159 nscd_getent_ctx_t *gnctx;
158 160
159 161 gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array);
160 162 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
161 163 (me, "getent context %p, cookie# %lld, to_delete %d\n",
162 164 gnctx->ptr, gnctx->cookie_num, gnctx->to_delete);
163 165
164 166 /*
165 167 * If the ctx is not to be deleted and the cookie numbers
166 168 * match, return the ctx if not aborted and not in use.
167 169 * Otherwise return NULL.
168 170 */
169 171 if (gnctx->to_delete == 0 && gnctx->cookie_num == cookie_num) {
170 172 ret = gnctx->ptr;
171 173 (void) mutex_lock(&gnctx->ptr->getent_mutex);
172 174 if (ret->aborted == 1 || ret->in_use == 1)
173 175 ret = NULL;
174 176 else
175 177 ret->in_use = 1;
176 178 (void) mutex_unlock(&gnctx->ptr->getent_mutex);
177 179 }
178 180 }
179 181
180 182 (void) rw_unlock(&getent_ctxDB_rwlock);
181 183
182 184 return (ret);
183 185 }
184 186
185 187 int
186 188 _nscd_is_getent_ctx_in_use(
187 189 nscd_getent_context_t *ctx)
188 190 {
189 191 int in_use;
190 192 char *me = "_nscd_getent_ctx_in_use";
191 193
192 194 (void) mutex_lock(&ctx->getent_mutex);
193 195
194 196 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
195 197 (me, "in_use = %d, ctx->thr_id = %d, thread id = %d\n",
196 198 ctx->in_use, ctx->thr_id, thr_self());
197 199
198 200 in_use = ctx->in_use;
199 201 if (in_use == 1 && ctx->thr_id == thr_self())
200 202 in_use = 0;
201 203 (void) mutex_unlock(&ctx->getent_mutex);
202 204 return (in_use);
203 205 }
204 206
205 207 /*
206 208 * FUNCTION: _nscd_free_ctx_if_aborted
207 209 *
208 210 * Check to see if the getent session associated with a getent context had
209 211 * been aborted. If so, return the getent context back to the pool.
210 212 */
211 213 void
212 214 _nscd_free_ctx_if_aborted(
213 215 nscd_getent_context_t *ctx)
214 216 {
215 217 int aborted;
216 218 char *me = "_nscd_free_ctx_if_aborted";
217 219
218 220 (void) mutex_lock(&ctx->getent_mutex);
219 221
220 222 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
221 223 (me, "in_use = %d, aborted = %d\n", ctx->in_use, ctx->aborted);
222 224
223 225 if (ctx->in_use != 1) {
224 226 (void) mutex_unlock(&ctx->getent_mutex);
225 227 return;
226 228 }
227 229 aborted = ctx->aborted;
228 230 ctx->in_use = 0;
229 231 (void) mutex_unlock(&ctx->getent_mutex);
230 232
231 233 if (aborted == 1) {
232 234 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
233 235 (me, "getent session aborted, return the getent context\n");
234 236 _nscd_put_getent_ctx(ctx);
235 237 }
236 238 }
237 239
238 240 /*
239 241 * FUNCTION: _nscd_del_getent_ctx
240 242 *
241 243 * Delete a getent context from the internal getent context database.
242 244 */
243 245 static void
244 246 _nscd_del_getent_ctx(
245 247 nscd_getent_context_t *ptr,
246 248 nscd_cookie_num_t cookie_num)
247 249 {
248 250 char ptrstr[32];
249 251 nscd_getent_ctx_t *gnctx;
250 252 const nscd_db_entry_t *db_entry;
251 253
252 254 if (ptr == NULL)
253 255 return;
254 256
255 257 (void) snprintf(ptrstr, sizeof (ptrstr), "%lld", cookie_num);
256 258
257 259 (void) rw_rdlock(&getent_ctxDB_rwlock);
258 260 /*
259 261 * first find the db entry and make sure the
260 262 * sequence number matched, then delete it from
261 263 * the database.
262 264 */
263 265 db_entry = _nscd_get_db_entry(getent_ctxDB,
264 266 NSCD_DATA_CTX_ADDR,
265 267 (const char *)ptrstr,
266 268 NSCD_GET_FIRST_DB_ENTRY, 0);
267 269 if (db_entry != NULL) {
268 270 gnctx = (nscd_getent_ctx_t *)*(db_entry->data_array);
269 271 if (gnctx->ptr == ptr && gnctx->cookie_num == cookie_num) {
270 272
271 273 (void) rw_unlock(&getent_ctxDB_rwlock);
272 274 (void) rw_wrlock(&getent_ctxDB_rwlock);
273 275
274 276 (void) _nscd_delete_db_entry(getent_ctxDB,
275 277 NSCD_DATA_CTX_ADDR,
276 278 (const char *)ptrstr,
277 279 NSCD_DEL_FIRST_DB_ENTRY, 0);
278 280 }
279 281 }
280 282 (void) rw_unlock(&getent_ctxDB_rwlock);
281 283 }
282 284
283 285 static void
284 286 _nscd_free_getent_ctx(
285 287 nscd_getent_context_t *gnctx)
286 288 {
287 289
288 290 char *me = "_nscd_free_getent_ctx";
289 291
290 292 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
291 293 (me, "getent context %p\n", gnctx);
292 294
293 295 _nscd_put_nsw_state(gnctx->nsw_state);
294 296
295 297 if (gnctx->base != NULL) {
296 298 /* remove reference to the getent context base */
297 299 _nscd_release((nscd_acc_data_t *)gnctx->base);
298 300 gnctx->base = NULL;
299 301 }
300 302
301 303 _nscd_del_getent_ctx(gnctx, gnctx->cookie_num);
302 304 free(gnctx);
303 305 }
304 306
305 307
306 308 static void
307 309 _nscd_free_getent_ctx_base(
308 310 nscd_acc_data_t *data)
309 311 {
310 312 nscd_getent_ctx_base_t *base = (nscd_getent_ctx_base_t *)data;
311 313 nscd_getent_context_t *c, *tc;
312 314 char *me = "_nscd_free_getent_ctx_base";
313 315
314 316 _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
315 317 (me, "getent context base %p\n", base);
316 318
317 319 if (base == NULL)
318 320 return;
319 321
320 322 c = base->first;
321 323 while (c != NULL) {
322 324 tc = c->next;
323 325 _nscd_free_getent_ctx(c);
324 326 c = tc;
325 327 }
326 328 }
327 329
328 330 void
329 331 _nscd_free_all_getent_ctx_base()
330 332 {
331 333 nscd_getent_ctx_base_t *base;
332 334 int i;
333 335 char *me = "_nscd_free_all_getent_ctx_base";
334 336
335 337 _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
336 338 (me, "entering ..\n");
337 339
338 340 (void) rw_wrlock(&nscd_getent_ctx_base_lock);
339 341
340 342 for (i = 0; i < NSCD_NUM_DB; i++) {
341 343
342 344 base = nscd_getent_ctx_base[i];
343 345 if (base == NULL)
344 346 continue;
345 347
346 348 nscd_getent_ctx_base[i] = (nscd_getent_ctx_base_t *)
347 349 _nscd_set((nscd_acc_data_t *)base, NULL);
348 350 }
349 351 (void) rw_unlock(&nscd_getent_ctx_base_lock);
350 352 }
351 353
352 354 static nscd_getent_context_t *
353 355 _nscd_create_getent_ctx(
354 356 nscd_nsw_params_t *params)
355 357 {
356 358 nscd_getent_context_t *gnctx;
357 359 nss_db_root_t db_root;
358 360 char *me = "_nscd_create_getent_ctx";
359 361
360 362 gnctx = calloc(1, sizeof (nscd_getent_context_t));
361 363 if (gnctx == NULL)
362 364 return (NULL);
363 365 else {
364 366 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
365 367 (me, "getent context allocated %p\n", gnctx);
366 368 }
367 369
368 370 gnctx->dbi = params->dbi;
369 371 gnctx->cookie_num = _nscd_get_cookie_num();
370 372 gnctx->pid = -1;
371 373 (void) mutex_init(&gnctx->getent_mutex, USYNC_THREAD, NULL);
372 374
373 375 if (_nscd_get_nsw_state(&db_root, params) != NSCD_SUCCESS) {
374 376 free(gnctx);
375 377 return (NULL);
376 378 }
377 379 gnctx->nsw_state = (nscd_nsw_state_t *)db_root.s;
378 380 /* this is a nsw_state used for getent processing */
379 381 gnctx->nsw_state->getent = 1;
380 382
381 383 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
382 384 (me, "got nsw_state %p\n", gnctx->nsw_state);
383 385
384 386 return (gnctx);
385 387 }
386 388
387 389
388 390 nscd_rc_t
389 391 _nscd_get_getent_ctx(
390 392 nss_getent_t *contextpp,
391 393 nscd_nsw_params_t *params)
392 394 {
393 395
394 396 nscd_getent_context_t *c;
395 397 nscd_getent_ctx_base_t *base, *tmp;
396 398 nscd_rc_t rc;
397 399 char *me = "_nscd_get_getent_ctx";
398 400
399 401 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
400 402 (me, "entering ...\n");
401 403
402 404 (void) rw_rdlock(&nscd_getent_ctx_base_lock);
403 405 base = nscd_getent_ctx_base[params->dbi];
404 406 (void) rw_unlock(&nscd_getent_ctx_base_lock);
405 407 assert(base != NULL);
406 408
407 409 /*
408 410 * If the context list is not empty, return the first one
409 411 * on the list. Otherwise, create and return a new one if
410 412 * limit is not reached. If limit is reached return an error
411 413 * so that the client can perform the enumeration.
412 414 */
413 415 tmp = (nscd_getent_ctx_base_t *)_nscd_mutex_lock(
414 416 (nscd_acc_data_t *)base);
415 417 assert(base == tmp);
416 418 if (base->first == NULL) {
417 419 if (base->num_getent_ctx >= base->max_getent_ctx) {
418 420 /* run out of contexts */
419 421
420 422 _NSCD_LOG(NSCD_LOG_GETENT_CTX,
421 423 NSCD_LOG_LEVEL_DEBUG)
422 424 (me, "run out of getent ctxs\n");
423 425
424 426 _nscd_mutex_unlock((nscd_acc_data_t *)base);
425 427 return (NSCD_CREATE_GETENT_CTX_FAILED);
426 428 } else {
427 429 base->first = _nscd_create_getent_ctx(params);
428 430 if (base->first != NULL)
429 431 base->num_getent_ctx++;
430 432 else {
431 433 /* not able to create a getent ctx */
432 434
433 435 _NSCD_LOG(NSCD_LOG_GETENT_CTX,
434 436 NSCD_LOG_LEVEL_ERROR)
435 437 (me, "create getent ctx failed\n");
436 438
437 439 _nscd_mutex_unlock((nscd_acc_data_t *)base);
438 440 return (NSCD_CREATE_GETENT_CTX_FAILED);
439 441 }
440 442
441 443 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
442 444 (me, "got a new getent ctx %p\n", base->first);
443 445 }
444 446 }
445 447
446 448 assert(base->first != NULL);
447 449
448 450 c = base->first;
449 451 base->first = c->next;
450 452 c->next = NULL;
451 453 c->seq_num = 1;
452 454 c->cookie_num = _nscd_get_cookie_num();
453 455 c->in_use = 1;
454 456 c->thr_id = thr_self();
455 457
456 458 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
457 459 (me, "got a getent ctx %p\n", c);
458 460
459 461 /*
460 462 * reference count the getent context base bfore handing out
461 463 * the getent context
462 464 */
463 465 c->base = (nscd_getent_ctx_base_t *)
464 466 _nscd_get((nscd_acc_data_t *)base);
465 467
466 468 _nscd_mutex_unlock((nscd_acc_data_t *)base);
467 469
468 470 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
469 471 (me, "adding new ctx %p, cookie # = %lld\n", c, c->cookie_num);
470 472
471 473 if ((rc = _nscd_add_getent_ctx(c, c->cookie_num)) != NSCD_SUCCESS) {
472 474 _nscd_put_getent_ctx(c);
473 475 return (rc);
474 476 }
475 477 contextpp->ctx = (struct nss_getent_context *)c;
476 478
477 479 /* start monitor and reclaim orphan getent context */
478 480 if (getent_monitor_started == 0) {
479 481 (void) mutex_lock(&getent_monitor_mutex);
480 482 if (getent_monitor_started == 0) {
481 483 getent_monitor_started = 1;
482 484 (void) _nscd_init_getent_ctx_monitor();
483 485 }
484 486 (void) mutex_unlock(&getent_monitor_mutex);
485 487 }
486 488
487 489 return (NSCD_SUCCESS);
488 490 }
489 491
490 492 void
491 493 _nscd_put_getent_ctx(
492 494 nscd_getent_context_t *gnctx)
493 495 {
494 496
495 497 nscd_getent_ctx_base_t *base;
496 498 char *me = "_nscd_put_getent_ctx";
497 499
498 500 base = gnctx->base;
499 501
500 502 /* if context base is gone or no longer current, free this context */
501 503 if ((_nscd_mutex_lock((nscd_acc_data_t *)base)) == NULL) {
502 504 _nscd_free_getent_ctx(gnctx);
503 505 return;
504 506 }
505 507
506 508 if (base->first != NULL) {
507 509 gnctx->next = base->first;
508 510 base->first = gnctx;
509 511 } else
510 512 base->first = gnctx;
511 513
512 514 /* put back the db state */
513 515 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
514 516 (me, "putting back nsw state %p\n", gnctx->nsw_state);
515 517
516 518 /* this nsw_state is no longer used for getent processing */
517 519 if (gnctx->nsw_state != NULL) {
518 520 gnctx->nsw_state->getent = 0;
519 521 _nscd_put_nsw_state(gnctx->nsw_state);
520 522 gnctx->nsw_state = NULL;
521 523 }
522 524
523 525 gnctx->aborted = 0;
524 526 gnctx->in_use = 0;
525 527 gnctx->thr_id = (thread_t)-1;
526 528 _nscd_del_getent_ctx(gnctx, gnctx->cookie_num);
527 529
528 530 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
529 531 (me, "ctx (%p, cookie # = %lld) removed from getent ctx DB\n",
530 532 gnctx, gnctx->cookie_num);
531 533
532 534 gnctx->seq_num = 0;
533 535 gnctx->cookie_num = 0;
534 536 gnctx->pid = -1;
535 537 gnctx->thr_id = (thread_t)-1;
536 538 gnctx->n_src = 0;
537 539 gnctx->be = NULL;
538 540
539 541 /* remove reference to the getent context base */
540 542 _nscd_release((nscd_acc_data_t *)base);
541 543 gnctx->base = NULL;
542 544
543 545 _nscd_mutex_unlock((nscd_acc_data_t *)base);
544 546 }
545 547
546 548 nscd_rc_t
547 549 _nscd_init_getent_ctx_base(
548 550 int dbi,
549 551 int lock)
550 552 {
551 553 nscd_getent_ctx_base_t *base = NULL;
552 554 char *me = "_nscd_init_getent_ctx_base";
553 555
554 556 if (lock)
555 557 (void) rw_rdlock(&nscd_getent_ctx_base_lock);
556 558
557 559 base = (nscd_getent_ctx_base_t *)_nscd_alloc(
558 560 NSCD_DATA_GETENT_CTX_BASE,
559 561 sizeof (nscd_getent_ctx_base_t),
560 562 _nscd_free_getent_ctx_base,
561 563 NSCD_ALLOC_MUTEX | NSCD_ALLOC_COND);
562 564
563 565 if (base == NULL) {
564 566 if (lock)
565 567 (void) rw_unlock(&nscd_getent_ctx_base_lock);
566 568 return (NSCD_NO_MEMORY);
567 569 }
568 570 _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
569 571 (me, "base %p allocated\n", base);
570 572
571 573 /*
572 574 * initialize and activate the new getent_ctx base
573 575 */
574 576 base->dbi = dbi;
575 577 base->max_getent_ctx = NSCD_SW_CFG(dbi).max_getent_ctx_per_db;
576 578 nscd_getent_ctx_base[dbi] =
577 579 (nscd_getent_ctx_base_t *)_nscd_set(
578 580 (nscd_acc_data_t *)nscd_getent_ctx_base[dbi],
579 581 (nscd_acc_data_t *)base);
580 582
581 583 if (lock)
582 584 (void) rw_unlock(&nscd_getent_ctx_base_lock);
583 585
584 586 return (NSCD_SUCCESS);
585 587 }
586 588
587 589 nscd_rc_t
588 590 _nscd_init_all_getent_ctx_base()
589 591 {
590 592 int i;
591 593 nscd_rc_t rc;
592 594 char *me = "_nscd_init_all_getent_ctx_base";
593 595
594 596 (void) rw_wrlock(&nscd_getent_ctx_base_lock);
595 597
596 598 for (i = 0; i < NSCD_NUM_DB; i++) {
597 599
598 600 rc = _nscd_init_getent_ctx_base(i, 0);
599 601
600 602 if (rc != NSCD_SUCCESS) {
601 603 (void) rw_unlock(&nscd_getent_ctx_base_lock);
602 604 return (rc);
603 605 }
604 606 }
605 607
606 608 _NSCD_LOG(NSCD_LOG_GETENT_CTX | NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
607 609 (me, "all getent context base initialized\n");
608 610
609 611 (void) rw_unlock(&nscd_getent_ctx_base_lock);
610 612
611 613 return (NSCD_SUCCESS);
612 614 }
613 615 nscd_rc_t
614 616 _nscd_alloc_getent_ctx_base()
615 617 {
616 618
617 619 (void) rw_wrlock(&nscd_getent_ctx_base_lock);
618 620
619 621 nscd_getent_ctx_base = calloc(NSCD_NUM_DB,
620 622 sizeof (nscd_getent_ctx_base_t *));
621 623 if (nscd_getent_ctx_base == NULL) {
622 624 (void) rw_unlock(&nscd_getent_ctx_base_lock);
623 625 return (NSCD_NO_MEMORY);
624 626 }
625 627
626 628 (void) rw_unlock(&nscd_getent_ctx_base_lock);
627 629
628 630 return (NSCD_SUCCESS);
629 631 }
630 632
631 633 static int
632 634 process_exited(pid_t pid)
633 635 {
634 636 char pname[PATH_MAX];
635 637 int fd;
636 638
637 639 (void) snprintf(pname, sizeof (pname), "/proc/%d/psinfo", pid);
638 640 if ((fd = open(pname, O_RDONLY)) == -1)
639 641 return (1);
640 642 else {
641 643 (void) close(fd);
642 644 return (0);
643 645 }
644 646 }
645 647
646 648 /*
647 649 * FUNCTION: reclaim_getent_ctx
648 650 */
649 651 /*ARGSUSED*/
650 652 static void * __NORETURN
↓ open down ↓ |
617 lines elided |
↑ open up ↑ |
651 653 reclaim_getent_ctx(void *arg)
652 654 {
653 655 void *cookie = NULL;
654 656 nscd_db_entry_t *ep;
655 657 nscd_getent_ctx_t *ctx;
656 658 nscd_getent_context_t *gctx, *c;
657 659 nscd_getent_context_t *first = NULL, *last = NULL;
658 660 nss_getent_t nssctx = { 0 };
659 661 char *me = "reclaim_getent_ctx";
660 662
663 + (void) thr_setname(thr_self(), me);
664 +
661 665 /*CONSTCOND*/
662 666 while (1) {
663 667
664 668 (void) sleep(60);
665 669
666 670 (void) rw_rdlock(&getent_ctxDB_rwlock);
667 671
668 672 for (ep = _nscd_walk_db(getent_ctxDB, &cookie); ep != NULL;
669 673 ep = _nscd_walk_db(getent_ctxDB, &cookie)) {
670 674
671 675 ctx = (nscd_getent_ctx_t *)*(ep->data_array);
672 676
673 677 gctx = ctx->ptr;
674 678
675 679 /*
676 680 * if the client process, which did the setent,
677 681 * exited, add the context to the orphan list
678 682 */
679 683 if (gctx->pid != -1 && process_exited(gctx->pid)) {
680 684
681 685 _NSCD_LOG(NSCD_LOG_GETENT_CTX,
682 686 NSCD_LOG_LEVEL_DEBUG)
683 687 (me, "process %d exited, "
684 688 "getent context = %p, "
685 689 "db index = %d, cookie # = %lld, "
686 690 "sequence # = %lld\n",
687 691 gctx->pid, gctx, gctx->dbi,
688 692 gctx->cookie_num, gctx->seq_num);
689 693
690 694 if (first != NULL) {
691 695 /* add to list if not in already */
692 696 for (c = first; c != NULL;
693 697 c = c->next_to_reclaim) {
694 698 if (gctx == c)
695 699 break;
696 700 }
697 701 if (c == NULL) {
698 702 last->next_to_reclaim = gctx;
699 703 last = gctx;
700 704 }
701 705 } else {
702 706 first = gctx;
703 707 last = gctx;
704 708 }
705 709 }
706 710 }
707 711
708 712 (void) rw_unlock(&getent_ctxDB_rwlock);
709 713
710 714
711 715 /*
712 716 * return all the orphan getent contexts to the pool if not
713 717 * in use
714 718 */
715 719 for (gctx = first; gctx; ) {
716 720 int in_use, num_reclaim_check;
717 721
718 722 c = gctx->next_to_reclaim;
719 723 gctx->next_to_reclaim = NULL;
720 724 gctx->aborted = 1;
721 725
722 726 (void) mutex_lock(&gctx->getent_mutex);
723 727 num_reclaim_check = gctx->num_reclaim_check++;
724 728 if (num_reclaim_check > 1)
725 729 gctx->in_use = 0;
726 730 in_use = gctx->in_use;
727 731 (void) mutex_unlock(&gctx->getent_mutex);
728 732
729 733 if (in_use == 0) {
730 734 _NSCD_LOG(NSCD_LOG_GETENT_CTX,
731 735 NSCD_LOG_LEVEL_DEBUG)
732 736 (me, "process %d exited, "
733 737 "freeing getent context = %p\n",
734 738 gctx->pid, gctx);
735 739 nssctx.ctx = (struct nss_getent_context *)gctx;
736 740 nss_endent(NULL, NULL, &nssctx);
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
737 741 }
738 742 gctx = c;
739 743 }
740 744 first = last = NULL;
741 745 }
742 746 /*NOTREACHED*/
743 747 /*LINTED E_FUNC_HAS_NO_RETURN_STMT*/
744 748 }
745 749
746 750 static nscd_rc_t
747 -_nscd_init_getent_ctx_monitor() {
751 +_nscd_init_getent_ctx_monitor()
752 +{
748 753
749 754 int errnum;
750 755 char *me = "_nscd_init_getent_ctx_monitor";
751 756
752 757 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_DEBUG)
753 758 (me, "initializing the getent context monitor\n");
754 759
755 760 /*
756 761 * the forker nscd does not process getent requests
757 762 * so no need to monitor orphan getent contexts
758 763 */
759 764 if (_whoami == NSCD_FORKER)
760 765 return (NSCD_SUCCESS);
761 766
762 767 /*
763 768 * start a thread to reclaim unused getent contexts
764 769 */
765 770 if (thr_create(NULL, NULL, reclaim_getent_ctx,
766 - NULL, THR_DETACHED, NULL) != 0) {
771 + NULL, THR_DETACHED, NULL) != 0) {
767 772 errnum = errno;
768 773 _NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR)
769 774 (me, "thr_create: %s\n", strerror(errnum));
770 775 return (NSCD_THREAD_CREATE_ERROR);
771 776 }
772 777
773 778 return (NSCD_SUCCESS);
774 779 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX