Print this page
re #13613 rb4516 Tunables needs volatile keyword
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/nfs/nfs4_acache.c
+++ new/usr/src/uts/common/fs/nfs/nfs4_acache.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, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 +/*
27 + * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28 + */
26 29
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 30 #include <nfs/nfs.h>
30 31 #include <nfs/nfs4.h>
31 32 #include <nfs/rnode4.h>
32 33 #include <nfs/nfs4_clnt.h>
33 34 #include <sys/bitmap.h>
34 35
35 36 /*
36 37 * Access cache
37 38 */
38 39 static acache4_hash_t *acache4;
39 -static long nacache; /* used strictly to size the number of hash queues */
40 +extern volatile long nacache; /* used strictly to size the number of hash */
41 + /* queues */
40 42
41 43 static int acache4size;
42 44 static int acache4mask;
43 45 static struct kmem_cache *acache4_cache;
44 46 static int acache4_hashlen = 4;
45 47
46 48 /*
47 49 * This probably needs to be larger than or equal to
48 50 * log2(sizeof (struct rnode)) due to the way that rnodes are
49 51 * allocated.
50 52 */
51 53 #define ACACHE4_SHIFT_BITS 9
52 54
53 55 static int
54 56 acache4hash(rnode4_t *rp, cred_t *cred)
55 57 {
56 58 return ((((intptr_t)rp >> ACACHE4_SHIFT_BITS) + crgetuid(cred)) &
57 59 acache4mask);
58 60 }
59 61
60 62 #ifdef DEBUG
61 63 static long nfs4_access_cache_hits = 0;
62 64 static long nfs4_access_cache_misses = 0;
63 65 #endif
64 66
65 67 nfs4_access_type_t
66 68 nfs4_access_check(rnode4_t *rp, uint32_t acc, cred_t *cr)
67 69 {
68 70 acache4_t *ap;
69 71 acache4_hash_t *hp;
70 72 nfs4_access_type_t all;
71 73 vnode_t *vp;
72 74
73 75 vp = RTOV4(rp);
74 76 if (!ATTRCACHE4_VALID(vp) || nfs4_waitfor_purge_complete(vp))
75 77 return (NFS4_ACCESS_UNKNOWN);
76 78
77 79 if (rp->r_acache != NULL) {
78 80 hp = &acache4[acache4hash(rp, cr)];
79 81 rw_enter(&hp->lock, RW_READER);
80 82 ap = hp->next;
81 83 while (ap != (acache4_t *)hp) {
82 84 if (crcmp(ap->cred, cr) == 0 && ap->rnode == rp) {
83 85 if ((ap->known & acc) == acc) {
84 86 #ifdef DEBUG
85 87 nfs4_access_cache_hits++;
86 88 #endif
87 89 if ((ap->allowed & acc) == acc)
88 90 all = NFS4_ACCESS_ALLOWED;
89 91 else
90 92 all = NFS4_ACCESS_DENIED;
91 93 } else {
92 94 #ifdef DEBUG
93 95 nfs4_access_cache_misses++;
94 96 #endif
95 97 all = NFS4_ACCESS_UNKNOWN;
96 98 }
97 99 rw_exit(&hp->lock);
98 100 return (all);
99 101 }
100 102 ap = ap->next;
101 103 }
102 104 rw_exit(&hp->lock);
103 105 }
104 106
105 107 #ifdef DEBUG
106 108 nfs4_access_cache_misses++;
107 109 #endif
108 110 return (NFS4_ACCESS_UNKNOWN);
109 111 }
110 112
111 113 void
112 114 nfs4_access_cache(rnode4_t *rp, uint32_t acc, uint32_t resacc, cred_t *cr)
113 115 {
114 116 acache4_t *ap;
115 117 acache4_t *nap;
116 118 acache4_hash_t *hp;
117 119
118 120 hp = &acache4[acache4hash(rp, cr)];
119 121
120 122 /*
121 123 * Allocate now assuming that mostly an allocation will be
122 124 * required. This allows the allocation to happen without
123 125 * holding the hash bucket locked.
124 126 */
125 127 nap = kmem_cache_alloc(acache4_cache, KM_NOSLEEP);
126 128 if (nap != NULL) {
127 129 nap->known = acc;
128 130 nap->allowed = resacc;
129 131 nap->rnode = rp;
130 132 crhold(cr);
131 133 nap->cred = cr;
132 134 nap->hashq = hp;
133 135 }
134 136
135 137 rw_enter(&hp->lock, RW_WRITER);
136 138
137 139 if (rp->r_acache != NULL) {
138 140 ap = hp->next;
139 141 while (ap != (acache4_t *)hp) {
140 142 if (crcmp(ap->cred, cr) == 0 && ap->rnode == rp) {
141 143 ap->known |= acc;
142 144 ap->allowed &= ~acc;
143 145 ap->allowed |= resacc;
144 146 rw_exit(&hp->lock);
145 147 if (nap != NULL) {
146 148 crfree(nap->cred);
147 149 kmem_cache_free(acache4_cache, nap);
148 150 }
149 151 return;
150 152 }
151 153 ap = ap->next;
152 154 }
153 155 }
154 156
155 157 if (nap != NULL) {
156 158 #ifdef DEBUG
157 159 clstat4_debug.access.value.ui64++;
158 160 #endif
159 161 nap->next = hp->next;
160 162 hp->next = nap;
161 163 nap->next->prev = nap;
162 164 nap->prev = (acache4_t *)hp;
163 165
164 166 mutex_enter(&rp->r_statelock);
165 167 nap->list = rp->r_acache;
166 168 rp->r_acache = nap;
167 169 mutex_exit(&rp->r_statelock);
168 170 }
169 171
170 172 rw_exit(&hp->lock);
171 173 }
172 174
173 175 int
174 176 nfs4_access_purge_rp(rnode4_t *rp)
175 177 {
176 178 acache4_t *ap, *tmpap, *rplist;
177 179
178 180 /*
179 181 * If there aren't any cached entries, then there is nothing
180 182 * to free.
181 183 */
182 184 if (rp->r_acache == NULL)
183 185 return (0);
184 186
185 187 mutex_enter(&rp->r_statelock);
186 188 rplist = rp->r_acache;
187 189 rp->r_acache = NULL;
188 190 mutex_exit(&rp->r_statelock);
189 191
190 192 /*
191 193 * Loop through each entry in the list pointed to in the
192 194 * rnode. Remove each of these entries from the hash
193 195 * queue that it is on and remove it from the list in
194 196 * the rnode.
195 197 */
196 198 for (ap = rplist; ap != NULL; ap = tmpap) {
197 199 rw_enter(&ap->hashq->lock, RW_WRITER);
198 200 ap->prev->next = ap->next;
199 201 ap->next->prev = ap->prev;
200 202 rw_exit(&ap->hashq->lock);
201 203
202 204 tmpap = ap->list;
203 205 crfree(ap->cred);
204 206 kmem_cache_free(acache4_cache, ap);
205 207 #ifdef DEBUG
206 208 clstat4_debug.access.value.ui64--;
207 209 #endif
208 210 }
209 211
210 212 return (1);
211 213 }
212 214
213 215 int
214 216 nfs4_acache_init(void)
215 217 {
216 218 extern int rtable4size;
217 219 int i;
218 220
219 221 /*
220 222 * Initial guess is one access cache entry per rnode unless
221 223 * nacache is set to a non-zero value and then it is used to
222 224 * indicate a guess at the number of access cache entries.
223 225 */
224 226 if (nacache > 0)
225 227 acache4size = 1 << highbit(nacache / acache4_hashlen);
226 228 else
227 229 acache4size = rtable4size;
228 230 acache4mask = acache4size - 1;
229 231 acache4 = kmem_alloc(acache4size * sizeof (*acache4), KM_SLEEP);
230 232 for (i = 0; i < acache4size; i++) {
231 233 acache4[i].next = (acache4_t *)&acache4[i];
232 234 acache4[i].prev = (acache4_t *)&acache4[i];
233 235 rw_init(&acache4[i].lock, NULL, RW_DEFAULT, NULL);
234 236 }
235 237 acache4_cache = kmem_cache_create("nfs4_access_cache",
236 238 sizeof (acache4_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
237 239
238 240 return (0);
239 241 }
240 242
241 243 int
242 244 nfs4_acache_fini(void)
243 245 {
244 246 int i;
245 247
246 248 /*
247 249 * Deallocated the access cache
248 250 */
249 251 kmem_cache_destroy(acache4_cache);
250 252
251 253 for (i = 0; i < acache4size; i++)
252 254 rw_destroy(&acache4[i].lock);
253 255 kmem_free(acache4, acache4size * sizeof (*acache4));
254 256
255 257 return (0);
256 258 }
|
↓ open down ↓ |
207 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX