afsconfig-and-rcsid-all-around-20010705
[openafs.git] / src / afs / LINUX / osi_cred.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * osi_cred.c - Linux cred handling routines.
12  *
13  */
14 #include "../afs/param.h"
15 #include <afsconfig.h>
16
17 RCSID("$Header$");
18
19 #include "../afs/sysincludes.h"
20 #include "../afs/afsincludes.h"
21
22 /* Setup a pool for creds. Allocate several at a time. */
23 #define CRED_ALLOC_STEP 29 /* at 140 bytes/cred = 4060 bytes. */
24
25
26 static cred_t *cred_pool = NULL;
27 int cred_allocs = 0;
28 int ncreds_inuse = 0;
29
30 /* Cred locking assumes current single threaded non-preemptive kernel.
31  * Also assuming a fast path through both down and up if no waiters. Otherwise,
32  * test if no creds in pool before grabbing lock in crfree().
33  */
34 #if defined(AFS_LINUX24_ENV)
35 static DECLARE_MUTEX(linux_cred_pool_lock);
36 #else
37 static struct semaphore linux_cred_pool_lock = MUTEX;
38 #endif
39 #define CRED_LOCK() down(&linux_cred_pool_lock)
40 #define CRED_UNLOCK() up(&linux_cred_pool_lock)
41
42 cred_t *crget(void)
43 {
44     cred_t *tmp;
45     int i;
46
47     CRED_LOCK();
48     if (!cred_pool) {
49         cred_allocs++;
50         cred_pool = (cred_t*)osi_Alloc(CRED_ALLOC_STEP * sizeof(cred_t));
51         if (!cred_pool)
52             osi_Panic("crget: No more memory for creds!\n");
53         
54         for (i=0; i < CRED_ALLOC_STEP-1; i++)
55             cred_pool[i].cr_ref = (long)&cred_pool[i+1];
56         cred_pool[i].cr_ref = 0;
57     }
58     tmp = cred_pool;
59     cred_pool = (cred_t*)tmp->cr_ref;
60     ncreds_inuse++;
61     CRED_UNLOCK();
62
63     memset(tmp, 0, sizeof(cred_t));
64     tmp->cr_ref = 1;
65     return tmp;
66 }
67
68 void crfree(cred_t *cr)
69 {
70     if (cr->cr_ref > 1) {
71         cr->cr_ref--;
72         return;
73     }
74
75     CRED_LOCK();
76     cr->cr_ref = (long)cred_pool;
77     cred_pool = cr;
78     CRED_UNLOCK();
79     ncreds_inuse --;
80 }
81
82
83 /* Return a duplicate of the cred. */
84 cred_t *crdup(cred_t *cr)
85 {
86     cred_t *tmp = crget();
87     *tmp = *cr;
88     tmp->cr_ref = 1;
89     return tmp;
90 }
91
92 cred_t *crref(void)
93 {
94     cred_t *cr = crget();
95     cr->cr_uid = current->fsuid;
96     cr->cr_ruid = current->uid;
97     cr->cr_gid = current->fsgid;
98     cr->cr_rgid = current->gid;
99     memcpy(cr->cr_groups, current->groups, NGROUPS * sizeof(gid_t));
100     cr->cr_ngroups = current->ngroups;
101     return cr;
102 }
103
104
105 /* Set the cred info into the current task */
106 void crset(cred_t *cr)
107 {
108     current->fsuid = cr->cr_uid;
109     current->uid = cr->cr_ruid;
110     current->fsgid = cr->cr_gid;
111     current->gid = cr->cr_rgid;
112     memcpy(current->groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
113     current->ngroups = cr->cr_ngroups;
114 }