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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Windows to Solaris Identity Mapping kernel API
29 * This module provides the kernel cache.
33 #include <sys/types.h>
35 #include <sys/systm.h>
36 #include <sys/sysmacros.h>
37 #include <sys/ksynch.h>
38 #include <sys/kidmap.h>
39 #include <rpcsvc/idmap_prot.h>
40 #include "kidmap_priv.h"
46 extern uintptr_t space_fetch(char *key
);
47 extern int space_store(char *key
, uintptr_t ptr
);
51 * Internal definitions and functions
54 #define CACHE_UID_TRIGGER_SIZE 4096
55 #define CACHE_GID_TRIGGER_SIZE 2048
56 #define CACHE_PID_TRIGGER_SIZE \
57 (CACHE_UID_TRIGGER_SIZE + CACHE_GID_TRIGGER_SIZE)
60 #define UNDEF_UID ((uid_t)-1)
61 #define UNDEF_GID ((gid_t)-1)
62 #define UNDEF_ISUSER (-1)
64 #define CACHE_PURGE_INTERVAL (60 * 3)
65 #define CACHE_TTL (60 * 10)
69 #define list_insert(head, ele)\
71 (ele)->flink = (head)->flink;\
72 (head)->flink = (ele);\
73 (ele)->blink = (ele)->flink->blink;\
74 (ele)->flink->blink = (ele);\
79 #define list_remove(ele)\
81 (ele)->flink->blink = (ele)->blink;\
82 (ele)->blink->flink = (ele)->flink;\
86 #define list_move(head, ele) \
88 if ((head)->flink != (ele)) {\
90 list_insert(head, ele);\
95 typedef struct sid_prefix_node
{
97 const char *sid_prefix
;
101 typedef int (*avl_comp_fn
)(const void*, const void*);
104 struct sid_prefix_store
{
105 struct avl_tree tree
;
109 struct sid_prefix_store
*kidmap_sid_prefix_store
= NULL
;
114 kidmap_purge_sid2pid_cache(idmap_sid2pid_cache_t
*cache
, size_t limit
);
117 kidmap_purge_pid2sid_cache(idmap_pid2sid_cache_t
*cache
, size_t limit
);
121 * kidmap_strdup() copied from uts/common/fs/sockfs/nl7c.c
124 kidmap_strdup(const char *s
)
126 int len
= strlen(s
) + 1;
127 char *ret
= kmem_alloc(len
, KM_SLEEP
);
135 kidmap_compare_sid(const sid2pid_t
*entry1
, const sid2pid_t
*entry2
)
137 int64_t comp
= ((int64_t)entry2
->rid
) - ((int64_t)entry1
->rid
);
140 comp
= strcmp(entry2
->sid_prefix
, entry1
->sid_prefix
);
152 kidmap_compare_pid(const pid2sid_t
*entry1
, const pid2sid_t
*entry2
)
154 if (entry2
->pid
> entry1
->pid
)
156 if (entry2
->pid
< entry1
->pid
)
163 kidmap_compare_sid_prefix(const sid_prefix_node_t
*entry1
,
164 const sid_prefix_node_t
*entry2
)
168 comp
= strcmp(entry2
->sid_prefix
, entry1
->sid_prefix
);
180 kidmap_cache_create(idmap_cache_t
*cache
)
182 avl_create(&cache
->sid2pid
.tree
, (avl_comp_fn
)kidmap_compare_sid
,
183 sizeof (sid2pid_t
), offsetof(sid2pid_t
, avl_link
));
184 mutex_init(&cache
->sid2pid
.mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
185 cache
->sid2pid
.purge_time
= 0;
186 cache
->sid2pid
.head
.flink
= &cache
->sid2pid
.head
;
187 cache
->sid2pid
.head
.blink
= &cache
->sid2pid
.head
;
188 cache
->sid2pid
.uid_num
= 0;
189 cache
->sid2pid
.gid_num
= 0;
190 cache
->sid2pid
.pid_num
= 0;
192 avl_create(&cache
->uid2sid
.tree
, (avl_comp_fn
)kidmap_compare_pid
,
193 sizeof (pid2sid_t
), offsetof(pid2sid_t
, avl_link
));
194 mutex_init(&cache
->uid2sid
.mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
195 cache
->uid2sid
.purge_time
= 0;
196 cache
->uid2sid
.head
.flink
= &cache
->uid2sid
.head
;
197 cache
->uid2sid
.head
.blink
= &cache
->uid2sid
.head
;
199 avl_create(&cache
->gid2sid
.tree
, (avl_comp_fn
)kidmap_compare_pid
,
200 sizeof (pid2sid_t
), offsetof(pid2sid_t
, avl_link
));
201 mutex_init(&cache
->gid2sid
.mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
202 cache
->gid2sid
.purge_time
= 0;
203 cache
->gid2sid
.head
.flink
= &cache
->gid2sid
.head
;
204 cache
->gid2sid
.head
.blink
= &cache
->gid2sid
.head
;
209 kidmap_cache_delete(idmap_cache_t
*cache
)
216 while ((sid2pid
= avl_destroy_nodes(&cache
->sid2pid
.tree
, &cookie
))
218 kmem_free(sid2pid
, sizeof (sid2pid_t
));
220 avl_destroy(&cache
->sid2pid
.tree
);
221 mutex_destroy(&cache
->sid2pid
.mutex
);
225 while ((pid2sid
= avl_destroy_nodes(&cache
->uid2sid
.tree
, &cookie
))
227 kmem_free(pid2sid
, sizeof (pid2sid_t
));
229 avl_destroy(&cache
->uid2sid
.tree
);
230 mutex_destroy(&cache
->uid2sid
.mutex
);
234 while ((pid2sid
= avl_destroy_nodes(&cache
->gid2sid
.tree
, &cookie
))
236 kmem_free(pid2sid
, sizeof (pid2sid_t
));
238 avl_destroy(&cache
->gid2sid
.tree
);
239 mutex_destroy(&cache
->gid2sid
.mutex
);
244 kidmap_cache_get_data(idmap_cache_t
*cache
, size_t *uidbysid
, size_t *gidbysid
,
245 size_t *pidbysid
, size_t *sidbyuid
, size_t *sidbygid
)
247 mutex_enter(&cache
->sid2pid
.mutex
);
248 *uidbysid
= cache
->sid2pid
.uid_num
;
249 *gidbysid
= cache
->sid2pid
.gid_num
;
250 *pidbysid
= cache
->sid2pid
.pid_num
;
251 mutex_exit(&cache
->sid2pid
.mutex
);
253 mutex_enter(&cache
->uid2sid
.mutex
);
254 *sidbyuid
= avl_numnodes(&cache
->uid2sid
.tree
);
255 mutex_exit(&cache
->uid2sid
.mutex
);
257 mutex_enter(&cache
->gid2sid
.mutex
);
258 *sidbygid
= avl_numnodes(&cache
->gid2sid
.tree
);
259 mutex_exit(&cache
->gid2sid
.mutex
);
264 kidmap_cache_purge(idmap_cache_t
*cache
)
270 mutex_enter(&cache
->sid2pid
.mutex
);
272 while ((sid2pid
= avl_destroy_nodes(&cache
->sid2pid
.tree
, &cookie
))
274 kmem_free(sid2pid
, sizeof (sid2pid_t
));
276 avl_destroy(&cache
->sid2pid
.tree
);
277 avl_create(&cache
->sid2pid
.tree
, (avl_comp_fn
)kidmap_compare_sid
,
278 sizeof (sid2pid_t
), offsetof(sid2pid_t
, avl_link
));
279 cache
->sid2pid
.purge_time
= 0;
280 cache
->sid2pid
.head
.flink
= &cache
->sid2pid
.head
;
281 cache
->sid2pid
.head
.blink
= &cache
->sid2pid
.head
;
282 cache
->sid2pid
.uid_num
= 0;
283 cache
->sid2pid
.gid_num
= 0;
284 cache
->sid2pid
.pid_num
= 0;
285 mutex_exit(&cache
->sid2pid
.mutex
);
288 mutex_enter(&cache
->uid2sid
.mutex
);
290 while ((pid2sid
= avl_destroy_nodes(&cache
->uid2sid
.tree
, &cookie
))
292 kmem_free(pid2sid
, sizeof (pid2sid_t
));
294 avl_destroy(&cache
->uid2sid
.tree
);
295 avl_create(&cache
->uid2sid
.tree
, (avl_comp_fn
)kidmap_compare_pid
,
296 sizeof (pid2sid_t
), offsetof(pid2sid_t
, avl_link
));
297 cache
->uid2sid
.purge_time
= 0;
298 cache
->uid2sid
.head
.flink
= &cache
->uid2sid
.head
;
299 cache
->uid2sid
.head
.blink
= &cache
->uid2sid
.head
;
300 mutex_exit(&cache
->uid2sid
.mutex
);
303 mutex_enter(&cache
->gid2sid
.mutex
);
305 while ((pid2sid
= avl_destroy_nodes(&cache
->gid2sid
.tree
, &cookie
))
307 kmem_free(pid2sid
, sizeof (pid2sid_t
));
309 avl_destroy(&cache
->gid2sid
.tree
);
310 avl_create(&cache
->gid2sid
.tree
, (avl_comp_fn
)kidmap_compare_pid
,
311 sizeof (pid2sid_t
), offsetof(pid2sid_t
, avl_link
));
312 cache
->gid2sid
.purge_time
= 0;
313 cache
->gid2sid
.head
.flink
= &cache
->gid2sid
.head
;
314 cache
->gid2sid
.head
.blink
= &cache
->gid2sid
.head
;
315 mutex_exit(&cache
->gid2sid
.mutex
);
320 kidmap_cache_lookup_uidbysid(idmap_cache_t
*cache
, const char *sid_prefix
,
321 uint32_t rid
, uid_t
*uid
)
326 int status
= IDMAP_ERR_NOMAPPING
;
327 time_t now
= gethrestime_sec();
329 entry
.sid_prefix
= sid_prefix
;
332 mutex_enter(&cache
->sid2pid
.mutex
);
334 result
= avl_find(&cache
->sid2pid
.tree
, &entry
, &where
);
335 if (result
!= NULL
) {
336 list_move(&cache
->sid2pid
.head
, result
);
337 if (result
->uid
!= UNDEF_UID
&& result
->uid_ttl
> now
) {
339 status
= IDMAP_SUCCESS
;
343 mutex_exit(&cache
->sid2pid
.mutex
);
350 kidmap_cache_lookup_gidbysid(idmap_cache_t
*cache
, const char *sid_prefix
,
351 uint32_t rid
, gid_t
*gid
)
356 int status
= IDMAP_ERR_NOMAPPING
;
357 time_t now
= gethrestime_sec();
359 entry
.sid_prefix
= sid_prefix
;
362 mutex_enter(&cache
->sid2pid
.mutex
);
364 result
= avl_find(&cache
->sid2pid
.tree
, &entry
, &where
);
365 if (result
!= NULL
) {
366 list_move(&cache
->sid2pid
.head
, result
);
367 if (result
->gid
!= UNDEF_GID
&& result
->gid_ttl
> now
) {
369 status
= IDMAP_SUCCESS
;
373 mutex_exit(&cache
->sid2pid
.mutex
);
380 kidmap_cache_lookup_pidbysid(idmap_cache_t
*cache
, const char *sid_prefix
,
381 uint32_t rid
, uid_t
*pid
, int *is_user
)
386 int status
= IDMAP_ERR_NOMAPPING
;
387 time_t now
= gethrestime_sec();
389 entry
.sid_prefix
= sid_prefix
;
392 mutex_enter(&cache
->sid2pid
.mutex
);
394 result
= avl_find(&cache
->sid2pid
.tree
, &entry
, &where
);
395 if (result
!= NULL
) {
396 list_move(&cache
->sid2pid
.head
, result
);
397 if (result
->is_user
!= UNDEF_ISUSER
) {
398 if (result
->is_user
&& result
->uid_ttl
> now
) {
400 *is_user
= result
->is_user
;
401 status
= IDMAP_SUCCESS
;
402 } else if (!result
->is_user
&& result
->gid_ttl
> now
) {
404 *is_user
= result
->is_user
;
405 status
= IDMAP_SUCCESS
;
410 mutex_exit(&cache
->sid2pid
.mutex
);
418 kidmap_cache_lookup_sidbyuid(idmap_cache_t
*cache
, const char **sid_prefix
,
419 uint32_t *rid
, uid_t uid
)
424 int status
= IDMAP_ERR_NOMAPPING
;
425 time_t now
= gethrestime_sec();
429 mutex_enter(&cache
->uid2sid
.mutex
);
431 result
= avl_find(&cache
->uid2sid
.tree
, &entry
, &where
);
432 if (result
!= NULL
) {
433 list_move(&cache
->uid2sid
.head
, result
);
434 if (result
->ttl
> now
) {
435 *sid_prefix
= result
->sid_prefix
;
437 status
= IDMAP_SUCCESS
;
441 mutex_exit(&cache
->uid2sid
.mutex
);
448 kidmap_cache_lookup_sidbygid(idmap_cache_t
*cache
, const char **sid_prefix
,
449 uint32_t *rid
, gid_t gid
)
454 int status
= IDMAP_ERR_NOMAPPING
;
455 time_t now
= gethrestime_sec();
459 mutex_enter(&cache
->gid2sid
.mutex
);
461 result
= avl_find(&cache
->gid2sid
.tree
, &entry
, &where
);
462 if (result
!= NULL
) {
463 list_move(&cache
->gid2sid
.head
, result
);
464 if (result
->ttl
> now
) {
465 *sid_prefix
= result
->sid_prefix
;
467 status
= IDMAP_SUCCESS
;
471 mutex_exit(&cache
->gid2sid
.mutex
);
478 kidmap_cache_add_sid2uid(idmap_cache_t
*cache
, const char *sid_prefix
,
479 uint32_t rid
, uid_t uid
, int direction
)
483 time_t ttl
= CACHE_TTL
+ gethrestime_sec();
486 if (direction
== IDMAP_DIRECTION_BI
||
487 direction
== IDMAP_DIRECTION_W2U
) {
492 find
.sid_prefix
= sid_prefix
;
495 mutex_enter(&cache
->sid2pid
.mutex
);
497 result
= avl_find(&cache
->sid2pid
.tree
, &find
, &where
);
499 if (result
->uid
== UNDEF_UID
)
500 cache
->sid2pid
.uid_num
++;
502 result
->uid_ttl
= ttl
;
504 new = kmem_alloc(sizeof (sid2pid_t
), KM_SLEEP
);
505 new->sid_prefix
= sid_prefix
;
509 new->gid
= UNDEF_GID
;
511 new->is_user
= UNDEF_ISUSER
; /* Unknown */
512 cache
->sid2pid
.uid_num
++;
514 list_insert(&cache
->sid2pid
.head
, new);
515 avl_insert(&cache
->sid2pid
.tree
, new, where
);
518 if ((avl_numnodes(&cache
->sid2pid
.tree
) >
519 CACHE_PID_TRIGGER_SIZE
) &&
520 (cache
->sid2pid
.purge_time
+ CACHE_PURGE_INTERVAL
<
522 kidmap_purge_sid2pid_cache(&cache
->sid2pid
,
523 CACHE_PID_TRIGGER_SIZE
);
525 mutex_exit(&cache
->sid2pid
.mutex
);
528 if (direction
== IDMAP_DIRECTION_BI
||
529 direction
== IDMAP_DIRECTION_U2W
) {
536 mutex_enter(&cache
->uid2sid
.mutex
);
538 result
= avl_find(&cache
->uid2sid
.tree
, &find
, &where
);
540 result
->sid_prefix
= sid_prefix
;
544 new = kmem_alloc(sizeof (pid2sid_t
), KM_SLEEP
);
545 new->sid_prefix
= sid_prefix
;
550 list_insert(&cache
->uid2sid
.head
, new);
551 avl_insert(&cache
->uid2sid
.tree
, new, where
);
554 if ((avl_numnodes(&cache
->uid2sid
.tree
) >
555 CACHE_UID_TRIGGER_SIZE
) &&
556 (cache
->uid2sid
.purge_time
+ CACHE_PURGE_INTERVAL
<
558 kidmap_purge_pid2sid_cache(&cache
->uid2sid
,
559 CACHE_UID_TRIGGER_SIZE
);
561 mutex_exit(&cache
->uid2sid
.mutex
);
568 kidmap_cache_add_sid2gid(idmap_cache_t
*cache
, const char *sid_prefix
,
569 uint32_t rid
, gid_t gid
, int direction
)
572 time_t ttl
= CACHE_TTL
+ gethrestime_sec();
575 if (direction
== IDMAP_DIRECTION_BI
||
576 direction
== IDMAP_DIRECTION_W2U
) {
581 find
.sid_prefix
= sid_prefix
;
584 mutex_enter(&cache
->sid2pid
.mutex
);
586 result
= avl_find(&cache
->sid2pid
.tree
, &find
, &where
);
588 if (result
->gid
== UNDEF_GID
)
589 cache
->sid2pid
.gid_num
++;
591 result
->gid_ttl
= ttl
;
593 new = kmem_alloc(sizeof (sid2pid_t
), KM_SLEEP
);
594 new->sid_prefix
= sid_prefix
;
596 new->uid
= UNDEF_UID
;
600 new->is_user
= UNDEF_ISUSER
; /* Unknown */
601 cache
->sid2pid
.gid_num
++;
603 list_insert(&cache
->sid2pid
.head
, new);
604 avl_insert(&cache
->sid2pid
.tree
, new, where
);
607 if ((avl_numnodes(&cache
->sid2pid
.tree
) >
608 CACHE_PID_TRIGGER_SIZE
) &&
609 (cache
->sid2pid
.purge_time
+ CACHE_PURGE_INTERVAL
<
611 kidmap_purge_sid2pid_cache(&cache
->sid2pid
,
612 CACHE_PID_TRIGGER_SIZE
);
614 mutex_exit(&cache
->sid2pid
.mutex
);
617 if (direction
== IDMAP_DIRECTION_BI
||
618 direction
== IDMAP_DIRECTION_U2W
) {
625 mutex_enter(&cache
->gid2sid
.mutex
);
627 result
= avl_find(&cache
->gid2sid
.tree
, &find
, &where
);
629 result
->sid_prefix
= sid_prefix
;
633 new = kmem_alloc(sizeof (pid2sid_t
), KM_SLEEP
);
634 new->sid_prefix
= sid_prefix
;
639 list_insert(&cache
->gid2sid
.head
, new);
640 avl_insert(&cache
->gid2sid
.tree
, new, where
);
643 if ((avl_numnodes(&cache
->gid2sid
.tree
) >
644 CACHE_GID_TRIGGER_SIZE
) &&
645 (cache
->gid2sid
.purge_time
+ CACHE_PURGE_INTERVAL
<
647 kidmap_purge_pid2sid_cache(&cache
->gid2sid
,
648 CACHE_GID_TRIGGER_SIZE
);
650 mutex_exit(&cache
->gid2sid
.mutex
);
656 kidmap_cache_add_sid2pid(idmap_cache_t
*cache
, const char *sid_prefix
,
657 uint32_t rid
, uid_t pid
, int is_user
, int direction
)
660 time_t ttl
= CACHE_TTL
+ gethrestime_sec();
663 if (direction
== IDMAP_DIRECTION_BI
||
664 direction
== IDMAP_DIRECTION_W2U
) {
669 find
.sid_prefix
= sid_prefix
;
672 mutex_enter(&cache
->sid2pid
.mutex
);
674 result
= avl_find(&cache
->sid2pid
.tree
, &find
, &where
);
676 if (result
->is_user
== UNDEF_ISUSER
)
677 cache
->sid2pid
.pid_num
++;
678 result
->is_user
= is_user
;
680 if (result
->uid
== UNDEF_UID
)
681 cache
->sid2pid
.uid_num
++;
683 result
->uid_ttl
= ttl
;
685 if (result
->gid
== UNDEF_GID
)
686 cache
->sid2pid
.gid_num
++;
688 result
->gid_ttl
= ttl
;
691 new = kmem_alloc(sizeof (sid2pid_t
), KM_SLEEP
);
692 new->sid_prefix
= sid_prefix
;
694 new->is_user
= is_user
;
698 new->gid
= UNDEF_GID
;
700 cache
->sid2pid
.uid_num
++;
702 new->uid
= UNDEF_UID
;
706 cache
->sid2pid
.gid_num
++;
708 cache
->sid2pid
.pid_num
++;
710 list_insert(&cache
->sid2pid
.head
, new);
711 avl_insert(&cache
->sid2pid
.tree
, new, where
);
714 if ((avl_numnodes(&cache
->sid2pid
.tree
) >
715 CACHE_PID_TRIGGER_SIZE
) &&
716 (cache
->sid2pid
.purge_time
+ CACHE_PURGE_INTERVAL
<
718 kidmap_purge_sid2pid_cache(&cache
->sid2pid
,
719 CACHE_PID_TRIGGER_SIZE
);
721 mutex_exit(&cache
->sid2pid
.mutex
);
724 if (direction
== IDMAP_DIRECTION_BI
||
725 direction
== IDMAP_DIRECTION_U2W
) {
732 mutex_enter(&cache
->uid2sid
.mutex
);
734 result
= avl_find(&cache
->uid2sid
.tree
, &find
, &where
);
736 result
->sid_prefix
= sid_prefix
;
740 new = kmem_alloc(sizeof (pid2sid_t
), KM_SLEEP
);
741 new->sid_prefix
= sid_prefix
;
746 list_insert(&cache
->uid2sid
.head
, new);
747 avl_insert(&cache
->uid2sid
.tree
, new, where
);
750 if ((avl_numnodes(&cache
->uid2sid
.tree
) >
751 CACHE_UID_TRIGGER_SIZE
) &&
752 (cache
->uid2sid
.purge_time
+
753 CACHE_PURGE_INTERVAL
<
755 kidmap_purge_pid2sid_cache(&cache
->uid2sid
,
756 CACHE_UID_TRIGGER_SIZE
);
758 mutex_exit(&cache
->uid2sid
.mutex
);
760 mutex_enter(&cache
->gid2sid
.mutex
);
762 result
= avl_find(&cache
->gid2sid
.tree
, &find
, &where
);
764 result
->sid_prefix
= sid_prefix
;
768 new = kmem_alloc(sizeof (pid2sid_t
), KM_SLEEP
);
769 new->sid_prefix
= sid_prefix
;
774 list_insert(&cache
->gid2sid
.head
, new);
775 avl_insert(&cache
->gid2sid
.tree
, new, where
);
778 if ((avl_numnodes(&cache
->gid2sid
.tree
) >
779 CACHE_GID_TRIGGER_SIZE
) &&
780 (cache
->gid2sid
.purge_time
+
781 CACHE_PURGE_INTERVAL
< gethrestime_sec()))
782 kidmap_purge_pid2sid_cache(&cache
->gid2sid
,
783 CACHE_GID_TRIGGER_SIZE
);
785 mutex_exit(&cache
->gid2sid
.mutex
);
795 kidmap_purge_sid2pid_cache(idmap_sid2pid_cache_t
*cache
, size_t limit
)
797 time_t now
= gethrestime_sec();
800 while (avl_numnodes(&cache
->tree
) > limit
) {
801 /* Remove least recently used */
802 item
= cache
->head
.blink
;
804 avl_remove(&cache
->tree
, item
);
805 if (item
->uid
!= UNDEF_UID
)
807 if (item
->gid
!= UNDEF_GID
)
809 if (item
->is_user
!= UNDEF_ISUSER
)
811 kmem_free(item
, sizeof (sid2pid_t
));
813 cache
->purge_time
= now
;
818 kidmap_purge_pid2sid_cache(idmap_pid2sid_cache_t
*cache
, size_t limit
)
820 time_t now
= gethrestime_sec();
823 while (avl_numnodes(&cache
->tree
) > limit
) {
824 /* Remove least recently used */
825 item
= cache
->head
.blink
;
827 avl_remove(&cache
->tree
, item
);
828 kmem_free(item
, sizeof (pid2sid_t
));
830 cache
->purge_time
= now
;
835 kidmap_sid_prefix_store_init(void)
837 kidmap_sid_prefix_store
= (struct sid_prefix_store
*)
838 space_fetch("SUNW,idmap_sid_prefix");
839 if (kidmap_sid_prefix_store
== NULL
) {
840 kidmap_sid_prefix_store
= kmem_alloc(
841 sizeof (struct sid_prefix_store
), KM_SLEEP
);
842 rw_init(&kidmap_sid_prefix_store
->lock
, NULL
, RW_DRIVER
, NULL
);
843 avl_create(&kidmap_sid_prefix_store
->tree
,
844 (avl_comp_fn
)kidmap_compare_sid_prefix
,
845 sizeof (sid_prefix_node_t
),
846 offsetof(sid_prefix_node_t
, avl_link
));
847 (void) space_store("SUNW,idmap_sid_prefix",
848 (uintptr_t)kidmap_sid_prefix_store
);
851 * The AVL comparison function must be re-initialised on
852 * re-load because may not be loaded into the same
855 kidmap_sid_prefix_store
->tree
.avl_compar
=
856 (avl_comp_fn
)kidmap_compare_sid_prefix
;
862 kidmap_find_sid_prefix(const char *sid_prefix
) {
863 sid_prefix_node_t find
;
864 sid_prefix_node_t
*result
;
865 sid_prefix_node_t
*new;
868 if (sid_prefix
== NULL
|| *sid_prefix
== '\0')
871 find
.sid_prefix
= sid_prefix
;
873 rw_enter(&kidmap_sid_prefix_store
->lock
, RW_READER
);
875 result
= avl_find(&kidmap_sid_prefix_store
->tree
, &find
, &where
);
878 rw_exit(&kidmap_sid_prefix_store
->lock
);
879 return (result
->sid_prefix
);
882 if (rw_tryupgrade(&kidmap_sid_prefix_store
->lock
) == 0) {
884 * Could not upgrade lock so release lock
885 * and acquire the write lock
887 rw_exit(&kidmap_sid_prefix_store
->lock
);
888 rw_enter(&kidmap_sid_prefix_store
->lock
, RW_WRITER
);
890 result
= avl_find(&kidmap_sid_prefix_store
->tree
,
893 rw_exit(&kidmap_sid_prefix_store
->lock
);
894 return (result
->sid_prefix
);
898 new = kmem_alloc(sizeof (sid_prefix_node_t
), KM_SLEEP
);
899 new->sid_prefix
= kidmap_strdup(sid_prefix
);
900 avl_insert(&kidmap_sid_prefix_store
->tree
, new, where
);
901 rw_exit(&kidmap_sid_prefix_store
->lock
);
903 return (new->sid_prefix
);