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 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Windows to Solaris Identity Mapping kernel API 29 * This module provides the kernel cache. 30 */ 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 35 #include <sys/types.h> 36 #include <sys/avl.h> 37 #include <sys/systm.h> 38 #include <sys/sysmacros.h> 39 #include <sys/ksynch.h> 40 #include <sys/kidmap.h> 41 #include "idmap_prot.h" 42 #include "kidmap_priv.h" 43 44 45 /* 46 * External functions 47 */ 48 extern uintptr_t space_fetch(char *key); 49 extern int space_store(char *key, uintptr_t ptr); 50 51 52 /* 53 * Internal definitions and functions 54 */ 55 56 #define CACHE_TRIGGER_SIZE 4096 57 #define CACHE_PURGE_INTERVAL (60 * 3) 58 #define CACHE_TTL (60 * 10) 59 60 typedef struct sid_prefix_node { 61 avl_node_t avl_link; 62 const char *sid_prefix; 63 } sid_prefix_node_t; 64 65 66 typedef struct entry { 67 avl_node_t avl_link; 68 const char *sid_prefix; 69 uint32_t rid; 70 uid_t pid; 71 int is_user; 72 time_t ttl; 73 } entry_t; 74 75 typedef int (*avl_comp_fn)(const void*, const void*); 76 77 78 struct sid_prefix_store { 79 struct avl_tree tree; 80 krwlock_t lock; 81 }; 82 83 struct sid_prefix_store *kidmap_sid_prefix_store = NULL; 84 85 86 87 static void 88 kidmap_cache_purge_avl(idmap_avl_cache_t *cache); 89 90 /* 91 * kidmap_strdup() copied from uts/common/fs/sockfs/nl7c.c 92 */ 93 static char * 94 kidmap_strdup(const char *s) 95 { 96 int len = strlen(s) + 1; 97 char *ret = kmem_alloc(len, KM_SLEEP); 98 99 bcopy(s, ret, len); 100 return (ret); 101 } 102 103 104 static int 105 kidmap_compare_sid(const entry_t *entry1, const entry_t *entry2) 106 { 107 int64_t comp = ((int64_t)entry2->rid) - ((int64_t)entry1->rid); 108 109 if (comp == 0) 110 comp = strcmp(entry2->sid_prefix, entry1->sid_prefix); 111 112 if (comp < 0) 113 comp = -1; 114 else if (comp > 0) 115 comp = 1; 116 117 return ((int)comp); 118 } 119 120 121 static int 122 kidmap_compare_pid(const entry_t *entry1, const entry_t *entry2) 123 { 124 if (entry2->pid > entry1->pid) 125 return (1); 126 if (entry2->pid < entry1->pid) 127 return (-1); 128 return (0); 129 } 130 131 132 static int 133 kidmap_compare_sid_prefix(const sid_prefix_node_t *entry1, 134 const sid_prefix_node_t *entry2) 135 { 136 int comp; 137 138 comp = strcmp(entry2->sid_prefix, entry1->sid_prefix); 139 140 if (comp < 0) 141 comp = -1; 142 else if (comp > 0) 143 comp = 1; 144 145 return (comp); 146 } 147 148 149 void 150 kidmap_cache_create(idmap_cache_t *cache) 151 { 152 avl_create(&cache->uidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 153 sizeof (entry_t), offsetof(entry_t, avl_link)); 154 mutex_init(&cache->uidbysid.mutex, NULL, MUTEX_DEFAULT, NULL); 155 cache->uidbysid.purge_time = 0; 156 157 avl_create(&cache->gidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 158 sizeof (entry_t), offsetof(entry_t, avl_link)); 159 mutex_init(&cache->gidbysid.mutex, NULL, MUTEX_DEFAULT, NULL); 160 cache->gidbysid.purge_time = 0; 161 162 avl_create(&cache->pidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 163 sizeof (entry_t), offsetof(entry_t, avl_link)); 164 mutex_init(&cache->pidbysid.mutex, NULL, MUTEX_DEFAULT, NULL); 165 cache->pidbysid.purge_time = 0; 166 167 avl_create(&cache->sidbyuid.tree, (avl_comp_fn)kidmap_compare_pid, 168 sizeof (entry_t), offsetof(entry_t, avl_link)); 169 mutex_init(&cache->sidbyuid.mutex, NULL, MUTEX_DEFAULT, NULL); 170 cache->sidbyuid.purge_time = 0; 171 172 avl_create(&cache->sidbygid.tree, (avl_comp_fn)kidmap_compare_pid, 173 sizeof (entry_t), offsetof(entry_t, avl_link)); 174 mutex_init(&cache->sidbygid.mutex, NULL, MUTEX_DEFAULT, NULL); 175 cache->sidbygid.purge_time = 0; 176 } 177 178 179 void 180 kidmap_cache_delete(idmap_cache_t *cache) 181 { 182 entry_t *entry; 183 void *cookie; 184 185 cookie = NULL; 186 while ((entry = avl_destroy_nodes(&cache->uidbysid.tree, &cookie)) 187 != NULL) { 188 kmem_free(entry, sizeof (entry_t)); 189 } 190 avl_destroy(&cache->uidbysid.tree); 191 mutex_destroy(&cache->uidbysid.mutex); 192 193 cookie = NULL; 194 while ((entry = avl_destroy_nodes(&cache->gidbysid.tree, &cookie)) 195 != NULL) { 196 kmem_free(entry, sizeof (entry_t)); 197 } 198 avl_destroy(&cache->gidbysid.tree); 199 mutex_destroy(&cache->gidbysid.mutex); 200 201 cookie = NULL; 202 while ((entry = avl_destroy_nodes(&cache->pidbysid.tree, &cookie)) 203 != NULL) { 204 kmem_free(entry, sizeof (entry_t)); 205 } 206 avl_destroy(&cache->pidbysid.tree); 207 mutex_destroy(&cache->pidbysid.mutex); 208 209 cookie = NULL; 210 while ((entry = avl_destroy_nodes(&cache->sidbyuid.tree, &cookie)) 211 != NULL) { 212 kmem_free(entry, sizeof (entry_t)); 213 } 214 avl_destroy(&cache->sidbyuid.tree); 215 mutex_destroy(&cache->sidbyuid.mutex); 216 217 cookie = NULL; 218 while ((entry = avl_destroy_nodes(&cache->sidbygid.tree, &cookie)) 219 != NULL) { 220 kmem_free(entry, sizeof (entry_t)); 221 } 222 avl_destroy(&cache->sidbygid.tree); 223 mutex_destroy(&cache->sidbygid.mutex); 224 } 225 226 227 void 228 kidmap_cache_purge(idmap_cache_t *cache) 229 { 230 entry_t *entry; 231 void *cookie; 232 233 mutex_enter(&cache->uidbysid.mutex); 234 cookie = NULL; 235 while ((entry = avl_destroy_nodes(&cache->uidbysid.tree, &cookie)) 236 != NULL) { 237 kmem_free(entry, sizeof (entry_t)); 238 } 239 avl_destroy(&cache->uidbysid.tree); 240 avl_create(&cache->uidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 241 sizeof (entry_t), offsetof(entry_t, avl_link)); 242 mutex_exit(&cache->uidbysid.mutex); 243 244 mutex_enter(&cache->gidbysid.mutex); 245 cookie = NULL; 246 while ((entry = avl_destroy_nodes(&cache->gidbysid.tree, &cookie)) 247 != NULL) { 248 kmem_free(entry, sizeof (entry_t)); 249 } 250 avl_destroy(&cache->gidbysid.tree); 251 avl_create(&cache->gidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 252 sizeof (entry_t), offsetof(entry_t, avl_link)); 253 mutex_exit(&cache->gidbysid.mutex); 254 255 mutex_enter(&cache->pidbysid.mutex); 256 cookie = NULL; 257 while ((entry = avl_destroy_nodes(&cache->pidbysid.tree, &cookie)) 258 != NULL) { 259 kmem_free(entry, sizeof (entry_t)); 260 } 261 avl_destroy(&cache->pidbysid.tree); 262 avl_create(&cache->pidbysid.tree, (avl_comp_fn)kidmap_compare_sid, 263 sizeof (entry_t), offsetof(entry_t, avl_link)); 264 mutex_exit(&cache->pidbysid.mutex); 265 266 mutex_enter(&cache->sidbyuid.mutex); 267 cookie = NULL; 268 while ((entry = avl_destroy_nodes(&cache->sidbyuid.tree, &cookie)) 269 != NULL) { 270 kmem_free(entry, sizeof (entry_t)); 271 } 272 avl_destroy(&cache->sidbyuid.tree); 273 avl_create(&cache->sidbyuid.tree, (avl_comp_fn)kidmap_compare_pid, 274 sizeof (entry_t), offsetof(entry_t, avl_link)); 275 mutex_exit(&cache->sidbyuid.mutex); 276 277 mutex_enter(&cache->sidbygid.mutex); 278 cookie = NULL; 279 while ((entry = avl_destroy_nodes(&cache->sidbygid.tree, &cookie)) 280 != NULL) { 281 kmem_free(entry, sizeof (entry_t)); 282 } 283 avl_destroy(&cache->sidbygid.tree); 284 avl_create(&cache->sidbygid.tree, (avl_comp_fn)kidmap_compare_pid, 285 sizeof (entry_t), offsetof(entry_t, avl_link)); 286 mutex_exit(&cache->sidbygid.mutex); 287 } 288 289 290 int 291 kidmap_cache_lookup_uidbysid(idmap_cache_t *cache, const char *sid_prefix, 292 uint32_t rid, uid_t *uid) 293 { 294 entry_t entry; 295 entry_t *result; 296 avl_index_t where; 297 int status; 298 time_t now = gethrestime_sec(); 299 300 entry.sid_prefix = sid_prefix; 301 entry.rid = rid; 302 303 mutex_enter(&cache->uidbysid.mutex); 304 305 result = avl_find(&cache->uidbysid.tree, &entry, &where); 306 307 if (result && result->ttl > now) { 308 *uid = result->pid; 309 status = IDMAP_SUCCESS; 310 } else 311 status = IDMAP_ERR_NOMAPPING; 312 313 mutex_exit(&cache->uidbysid.mutex); 314 315 return (status); 316 } 317 318 319 320 int 321 kidmap_cache_lookup_gidbysid(idmap_cache_t *cache, const char *sid_prefix, 322 uint32_t rid, gid_t *gid) 323 { 324 entry_t entry; 325 entry_t *result; 326 avl_index_t where; 327 int status; 328 time_t now = gethrestime_sec(); 329 330 entry.sid_prefix = sid_prefix; 331 entry.rid = rid; 332 333 mutex_enter(&cache->gidbysid.mutex); 334 335 result = avl_find(&cache->gidbysid.tree, &entry, &where); 336 337 if (result && result->ttl > now) { 338 *gid = result->pid; 339 status = IDMAP_SUCCESS; 340 } else 341 status = IDMAP_ERR_NOMAPPING; 342 343 mutex_exit(&cache->gidbysid.mutex); 344 345 return (status); 346 } 347 348 349 350 351 int 352 kidmap_cache_lookup_pidbysid(idmap_cache_t *cache, const char *sid_prefix, 353 uint32_t rid, uid_t *pid, int *is_user) 354 { 355 entry_t entry; 356 entry_t *result; 357 avl_index_t where; 358 int status; 359 time_t now = gethrestime_sec(); 360 361 entry.sid_prefix = sid_prefix; 362 entry.rid = rid; 363 364 mutex_enter(&cache->pidbysid.mutex); 365 366 result = avl_find(&cache->pidbysid.tree, &entry, &where); 367 368 if (result && result->ttl > now) { 369 *pid = result->pid; 370 *is_user = result->is_user; 371 status = IDMAP_SUCCESS; 372 } else 373 status = IDMAP_ERR_NOMAPPING; 374 375 mutex_exit(&cache->pidbysid.mutex); 376 377 return (status); 378 } 379 380 381 382 int 383 kidmap_cache_lookup_sidbyuid(idmap_cache_t *cache, const char **sid_prefix, 384 uint32_t *rid, uid_t uid) 385 { 386 entry_t entry; 387 entry_t *result; 388 avl_index_t where; 389 int status; 390 time_t now = gethrestime_sec(); 391 392 entry.pid = uid; 393 394 mutex_enter(&cache->sidbyuid.mutex); 395 396 result = avl_find(&cache->sidbyuid.tree, &entry, &where); 397 398 if (result && result->ttl > now) { 399 *sid_prefix = result->sid_prefix; 400 *rid = result->rid; 401 status = IDMAP_SUCCESS; 402 } else 403 status = IDMAP_ERR_NOMAPPING; 404 405 mutex_exit(&cache->sidbyuid.mutex); 406 407 return (status); 408 } 409 410 int 411 kidmap_cache_lookup_sidbygid(idmap_cache_t *cache, const char **sid_prefix, 412 uint32_t *rid, gid_t gid) 413 { 414 entry_t entry; 415 entry_t *result; 416 avl_index_t where; 417 int status; 418 time_t now = gethrestime_sec(); 419 420 entry.pid = gid; 421 422 mutex_enter(&cache->sidbygid.mutex); 423 424 result = avl_find(&cache->sidbygid.tree, &entry, &where); 425 426 if (result && result->ttl > now) { 427 *sid_prefix = result->sid_prefix; 428 *rid = result->rid; 429 status = IDMAP_SUCCESS; 430 } else 431 status = IDMAP_ERR_NOMAPPING; 432 433 mutex_exit(&cache->sidbygid.mutex); 434 435 return (status); 436 } 437 438 439 440 441 void 442 kidmap_cache_add_uidbysid(idmap_cache_t *cache, const char *sid_prefix, 443 uint32_t rid, uid_t uid) 444 445 { 446 entry_t find; 447 entry_t *result; 448 entry_t *new; 449 avl_index_t where; 450 int purge_required = FALSE; 451 time_t ttl = CACHE_TTL + gethrestime_sec(); 452 453 find.sid_prefix = sid_prefix; 454 find.rid = rid; 455 456 mutex_enter(&cache->uidbysid.mutex); 457 result = avl_find(&cache->uidbysid.tree, &find, &where); 458 459 if (result) { 460 result->pid = uid; 461 result->ttl = ttl; 462 } else { 463 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 464 new->pid = uid; 465 new->sid_prefix = sid_prefix; 466 new->rid = rid; 467 new->ttl = ttl; 468 469 avl_insert(&cache->uidbysid.tree, new, where); 470 471 if ((avl_numnodes(&cache->uidbysid.tree) > 472 CACHE_TRIGGER_SIZE) && 473 (cache->uidbysid.purge_time + CACHE_PURGE_INTERVAL < 474 gethrestime_sec())) 475 purge_required = TRUE; 476 } 477 478 mutex_exit(&cache->uidbysid.mutex); 479 480 if (purge_required) 481 kidmap_cache_purge_avl(&cache->uidbysid); 482 } 483 484 485 void 486 kidmap_cache_add_gidbysid(idmap_cache_t *cache, const char *sid_prefix, 487 uint32_t rid, gid_t gid) 488 489 { 490 entry_t find; 491 entry_t *result; 492 entry_t *new; 493 avl_index_t where; 494 int purge_required = FALSE; 495 time_t ttl = CACHE_TTL + gethrestime_sec(); 496 497 find.sid_prefix = sid_prefix; 498 find.rid = rid; 499 500 mutex_enter(&cache->gidbysid.mutex); 501 result = avl_find(&cache->gidbysid.tree, &find, &where); 502 503 if (result) { 504 result->pid = gid; 505 result->ttl = ttl; 506 } else { 507 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 508 new->pid = gid; 509 new->sid_prefix = sid_prefix; 510 new->rid = rid; 511 new->ttl = ttl; 512 513 avl_insert(&cache->gidbysid.tree, new, where); 514 515 if ((avl_numnodes(&cache->gidbysid.tree) > 516 CACHE_TRIGGER_SIZE) && 517 (cache->gidbysid.purge_time + CACHE_PURGE_INTERVAL < 518 gethrestime_sec())) 519 purge_required = TRUE; 520 } 521 522 mutex_exit(&cache->gidbysid.mutex); 523 524 if (purge_required) 525 kidmap_cache_purge_avl(&cache->gidbysid); 526 } 527 528 void 529 kidmap_cache_add_pidbysid(idmap_cache_t *cache, const char *sid_prefix, 530 uint32_t rid, uid_t pid, int is_user) 531 532 { 533 entry_t find; 534 entry_t *result; 535 entry_t *new; 536 avl_index_t where; 537 int purge_required = FALSE; 538 time_t ttl = CACHE_TTL + gethrestime_sec(); 539 540 find.sid_prefix = sid_prefix; 541 find.rid = rid; 542 543 mutex_enter(&cache->pidbysid.mutex); 544 result = avl_find(&cache->pidbysid.tree, &find, &where); 545 546 if (result) { 547 result->pid = pid; 548 result->is_user = is_user; 549 result->ttl = ttl; 550 } else { 551 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 552 new->pid = pid; 553 new->is_user = is_user; 554 new->sid_prefix = sid_prefix; 555 new->rid = rid; 556 new->ttl = ttl; 557 558 avl_insert(&cache->pidbysid.tree, new, where); 559 560 if ((avl_numnodes(&cache->pidbysid.tree) > 561 CACHE_TRIGGER_SIZE) && 562 (cache->pidbysid.purge_time + CACHE_PURGE_INTERVAL < 563 gethrestime_sec())) 564 purge_required = TRUE; 565 } 566 567 mutex_exit(&cache->pidbysid.mutex); 568 569 if (purge_required) 570 kidmap_cache_purge_avl(&cache->pidbysid); 571 } 572 573 574 575 void 576 kidmap_cache_add_sidbyuid(idmap_cache_t *cache, const char *sid_prefix, 577 uint32_t rid, uid_t uid) 578 { 579 entry_t find; 580 entry_t *result; 581 entry_t *new; 582 avl_index_t where; 583 int purge_required = FALSE; 584 time_t ttl = CACHE_TTL + gethrestime_sec(); 585 586 find.pid = uid; 587 588 mutex_enter(&cache->sidbyuid.mutex); 589 result = avl_find(&cache->sidbyuid.tree, &find, &where); 590 591 if (result) { 592 result->sid_prefix = sid_prefix; 593 result->rid = rid; 594 result->ttl = ttl; 595 } else { 596 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 597 new->pid = uid; 598 new->sid_prefix = sid_prefix; 599 new->rid = rid; 600 new->ttl = ttl; 601 602 avl_insert(&cache->sidbyuid.tree, new, where); 603 if ((avl_numnodes(&cache->sidbyuid.tree) > 604 CACHE_TRIGGER_SIZE) && 605 (cache->sidbyuid.purge_time + CACHE_PURGE_INTERVAL < 606 gethrestime_sec())) 607 purge_required = TRUE; 608 } 609 610 mutex_exit(&cache->sidbyuid.mutex); 611 612 if (purge_required) 613 kidmap_cache_purge_avl(&cache->sidbyuid); 614 } 615 616 617 void 618 kidmap_cache_add_sidbygid(idmap_cache_t *cache, const char *sid_prefix, 619 uint32_t rid, gid_t gid) 620 { 621 entry_t find; 622 entry_t *result; 623 entry_t *new; 624 avl_index_t where; 625 int purge_required = FALSE; 626 time_t ttl = CACHE_TTL + gethrestime_sec(); 627 628 find.pid = gid; 629 630 mutex_enter(&cache->sidbygid.mutex); 631 result = avl_find(&cache->sidbygid.tree, &find, &where); 632 633 if (result) { 634 result->sid_prefix = sid_prefix; 635 result->rid = rid; 636 result->ttl = ttl; 637 } else { 638 new = kmem_alloc(sizeof (entry_t), KM_SLEEP); 639 new->pid = gid; 640 new->sid_prefix = sid_prefix; 641 new->rid = rid; 642 new->ttl = ttl; 643 644 avl_insert(&cache->sidbygid.tree, new, where); 645 if ((avl_numnodes(&cache->sidbygid.tree) > 646 CACHE_TRIGGER_SIZE) && 647 (cache->sidbygid.purge_time + CACHE_PURGE_INTERVAL < 648 gethrestime_sec())) 649 purge_required = TRUE; 650 } 651 652 mutex_exit(&cache->sidbygid.mutex); 653 654 if (purge_required) 655 kidmap_cache_purge_avl(&cache->sidbygid); 656 } 657 658 659 static void 660 kidmap_cache_purge_avl(idmap_avl_cache_t *cache) 661 { 662 time_t now = gethrestime_sec(); 663 entry_t *curr; 664 entry_t *prev = NULL; 665 666 mutex_enter(&cache->mutex); 667 668 curr = avl_first(&cache->tree); 669 while (curr != NULL) { 670 if (curr->ttl < now) { 671 /* Old entry to remove */ 672 avl_remove(&cache->tree, curr); 673 curr = prev; 674 if (curr == NULL) { 675 /* We removed the first entery */ 676 curr = avl_first(&cache->tree); 677 continue; 678 } 679 } 680 prev = curr; 681 curr = AVL_NEXT(&cache->tree, curr); 682 } 683 cache->purge_time = now; 684 685 mutex_exit(&cache->mutex); 686 } 687 688 689 void 690 kidmap_sid_prefix_store_init(void) 691 { 692 kidmap_sid_prefix_store = (struct sid_prefix_store *) 693 space_fetch("SUNW,idmap_sid_prefix"); 694 if (kidmap_sid_prefix_store == NULL) { 695 kidmap_sid_prefix_store = kmem_alloc( 696 sizeof (struct sid_prefix_store), KM_SLEEP); 697 rw_init(&kidmap_sid_prefix_store->lock, NULL, RW_DRIVER, NULL); 698 avl_create(&kidmap_sid_prefix_store->tree, 699 (avl_comp_fn)kidmap_compare_sid_prefix, 700 sizeof (sid_prefix_node_t), 701 offsetof(sid_prefix_node_t, avl_link)); 702 (void) space_store("SUNW,idmap_sid_prefix", 703 (uintptr_t)kidmap_sid_prefix_store); 704 } else { 705 /* 706 * The AVL comparison function must be re-initialised on 707 * re-load because may not be loaded into the same 708 * address space. 709 */ 710 kidmap_sid_prefix_store->tree.avl_compar = 711 (avl_comp_fn)kidmap_compare_sid_prefix; 712 } 713 } 714 715 716 const char * 717 kidmap_find_sid_prefix(const char *sid_prefix) { 718 sid_prefix_node_t find; 719 sid_prefix_node_t *result; 720 sid_prefix_node_t *new; 721 avl_index_t where; 722 723 if (sid_prefix == NULL || *sid_prefix == '\0') 724 return (NULL); 725 726 find.sid_prefix = sid_prefix; 727 728 729 rw_enter(&kidmap_sid_prefix_store->lock, RW_READER); 730 731 result = avl_find(&kidmap_sid_prefix_store->tree, &find, &where); 732 733 if (result) { 734 rw_exit(&kidmap_sid_prefix_store->lock); 735 return (result->sid_prefix); 736 } 737 738 if (rw_tryupgrade(&kidmap_sid_prefix_store->lock) == 0) { 739 /* 740 * Could not upgrade lock so release lock 741 * and acquire the write lock 742 */ 743 rw_exit(&kidmap_sid_prefix_store->lock); 744 rw_enter(&kidmap_sid_prefix_store->lock, RW_WRITER); 745 746 result = avl_find(&kidmap_sid_prefix_store->tree, 747 &find, &where); 748 if (result) { 749 rw_exit(&kidmap_sid_prefix_store->lock); 750 return (result->sid_prefix); 751 } 752 } 753 754 new = kmem_alloc(sizeof (sid_prefix_node_t), KM_SLEEP); 755 new->sid_prefix = kidmap_strdup(sid_prefix); 756 avl_insert(&kidmap_sid_prefix_store->tree, new, where); 757 rw_exit(&kidmap_sid_prefix_store->lock); 758 759 return (new->sid_prefix); 760 } 761