Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/sharefs/sharetab.c
+++ new/usr/src/uts/common/fs/sharefs/sharetab.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
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 /*
23 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/types32.h>
28 28 #include <sys/param.h>
29 29 #include <sys/systm.h>
30 30 #include <rpc/types.h>
31 31 #include <sys/vfs.h>
32 32 #include <sys/siginfo.h>
33 33 #include <sys/proc.h> /* for exit() declaration */
34 34 #include <sys/kmem.h>
35 35 #include <sys/pathname.h>
36 36 #include <sys/debug.h>
37 37 #include <sys/vtrace.h>
38 38 #include <sys/cmn_err.h>
39 39 #include <sys/atomic.h>
40 40 #include <sys/policy.h>
41 41
42 42 #include <sharefs/sharefs.h>
43 43
44 44 /*
45 45 * A macro to avoid cut-and-paste errors on getting a string field
46 46 * from user-land.
47 47 */
48 48 #define SHARETAB_COPYIN(field) \
49 49 if (copyinstr(STRUCT_FGETP(u_sh, sh_##field), \
50 50 buf, \
51 51 bufsz + 1, /* Add one for extra NUL */ \
52 52 &len)) { \
53 53 error = EFAULT; \
54 54 goto cleanup; \
55 55 } \
56 56 /* \
57 57 * Need to remove 1 because copyinstr() counts the NUL. \
58 58 */ \
59 59 len--; \
60 60 sh->sh_##field = kmem_alloc(len + 1, KM_SLEEP); \
61 61 bcopy(buf, sh->sh_##field, len); \
62 62 sh->sh_##field[len] = '\0'; \
63 63 shl.shl_##field = (int)len; \
64 64 sh->sh_size += shl.shl_##field; /* Debug counting */
65 65
66 66 #define SHARETAB_DELETE_FIELD(field) \
67 67 if (sh->sh_##field) { \
68 68 kmem_free(sh->sh_##field, \
69 69 shl ? shl->shl_##field + 1 : \
70 70 strlen(sh->sh_##field) + 1); \
71 71 }
72 72
73 73 sharetab_t *sharefs_sharetab = NULL; /* The incore sharetab. */
74 74 size_t sharetab_size;
75 75 uint_t sharetab_count;
76 76
77 77 krwlock_t sharetab_lock; /* lock to protect the cached sharetab */
78 78
79 79 krwlock_t sharefs_lock; /* lock to protect the vnode ops */
80 80
81 81 timestruc_t sharetab_mtime;
82 82 timestruc_t sharetab_snap_time;
83 83
84 84 uint_t sharetab_generation; /* Only increments and wraps! */
85 85
86 86 /*
87 87 * Take care of cleaning up a share.
88 88 * If passed in a length array, use it to determine how much
89 89 * space to clean up. Else, figure that out.
90 90 */
91 91 static void
92 92 sharefree(share_t *sh, sharefs_lens_t *shl)
93 93 {
94 94 if (!sh)
95 95 return;
96 96
97 97 SHARETAB_DELETE_FIELD(path);
98 98 SHARETAB_DELETE_FIELD(res);
99 99 SHARETAB_DELETE_FIELD(fstype);
100 100 SHARETAB_DELETE_FIELD(opts);
101 101 SHARETAB_DELETE_FIELD(descr);
102 102
103 103 kmem_free(sh, sizeof (share_t));
104 104 }
105 105
106 106 /*
107 107 * If there is no error, then this function is responsible for
108 108 * cleaning up the memory associated with the share argument.
109 109 */
110 110 static int
111 111 sharefs_remove(share_t *sh, sharefs_lens_t *shl)
112 112 {
113 113 int iHash;
114 114 sharetab_t *sht;
115 115 share_t *s, *p;
116 116 int iPath;
117 117
118 118 if (!sh)
119 119 return (ENOENT);
120 120
121 121 rw_enter(&sharetab_lock, RW_WRITER);
122 122 for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
123 123 if (strcmp(sh->sh_fstype, sht->s_fstype) == 0) {
124 124 break;
125 125 }
126 126 }
127 127
128 128 /*
129 129 * There does not exist a fstype in memory which
130 130 * matches the share passed in.
131 131 */
132 132 if (!sht) {
133 133 rw_exit(&sharetab_lock);
134 134 return (ENOENT);
135 135 }
136 136
137 137 iPath = shl ? shl->shl_path : strlen(sh->sh_path);
138 138 iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
139 139
140 140 /*
141 141 * Now walk down the hash table and find the entry to free!
142 142 */
143 143 for (p = NULL, s = sht->s_buckets[iHash].ssh_sh;
144 144 s != NULL; s = s->sh_next) {
145 145 /*
146 146 * We need exact matches.
↓ open down ↓ |
146 lines elided |
↑ open up ↑ |
147 147 */
148 148 if (strcmp(sh->sh_path, s->sh_path) == 0 &&
149 149 strlen(s->sh_path) == iPath) {
150 150 if (p) {
151 151 p->sh_next = s->sh_next;
152 152 } else {
153 153 sht->s_buckets[iHash].ssh_sh = s->sh_next;
154 154 }
155 155
156 156 ASSERT(sht->s_buckets[iHash].ssh_count != 0);
157 - atomic_add_32(&sht->s_buckets[iHash].ssh_count, -1);
158 - atomic_add_32(&sht->s_count, -1);
159 - atomic_add_32(&sharetab_count, -1);
157 + atomic_dec_32(&sht->s_buckets[iHash].ssh_count);
158 + atomic_dec_32(&sht->s_count);
159 + atomic_dec_32(&sharetab_count);
160 160
161 161 ASSERT(sharetab_size >= s->sh_size);
162 162 sharetab_size -= s->sh_size;
163 163
164 164 gethrestime(&sharetab_mtime);
165 - atomic_add_32(&sharetab_generation, 1);
165 + atomic_inc_32(&sharetab_generation);
166 166
167 167 break;
168 168 }
169 169
170 170 p = s;
171 171 }
172 172
173 173 rw_exit(&sharetab_lock);
174 174
175 175 if (!s) {
176 176 return (ENOENT);
177 177 }
178 178
179 179 s->sh_next = NULL;
180 180 sharefree(s, NULL);
181 181
182 182 /*
183 183 * We need to free the share for the caller.
184 184 */
185 185 sharefree(sh, shl);
186 186
187 187 return (0);
188 188 }
189 189
190 190 /*
191 191 * The caller must have allocated memory for us to use.
192 192 */
193 193 static int
194 194 sharefs_add(share_t *sh, sharefs_lens_t *shl)
195 195 {
196 196 int iHash;
197 197 sharetab_t *sht;
198 198 share_t *s, *p;
199 199 int iPath;
200 200 int n;
201 201
202 202 if (!sh) {
203 203 return (ENOENT);
204 204 }
205 205
206 206 /*
207 207 * We need to find the hash buckets for the fstype.
208 208 */
209 209 rw_enter(&sharetab_lock, RW_WRITER);
210 210 for (sht = sharefs_sharetab; sht != NULL; sht = sht->s_next) {
211 211 if (strcmp(sh->sh_fstype, sht->s_fstype) == 0) {
212 212 break;
213 213 }
214 214 }
215 215
216 216 /*
217 217 * Did not exist, so allocate one and add it to the
218 218 * sharetab.
219 219 */
220 220 if (!sht) {
221 221 sht = kmem_zalloc(sizeof (*sht), KM_SLEEP);
222 222 n = strlen(sh->sh_fstype);
223 223 sht->s_fstype = kmem_zalloc(n + 1, KM_SLEEP);
224 224 (void) strncpy(sht->s_fstype, sh->sh_fstype, n);
225 225
226 226 sht->s_next = sharefs_sharetab;
227 227 sharefs_sharetab = sht;
228 228 }
229 229
230 230 /*
231 231 * Now we need to find where we have to add the entry.
232 232 */
233 233 iHash = pkp_tab_hash(sh->sh_path, strlen(sh->sh_path));
234 234
235 235 iPath = shl ? shl->shl_path : strlen(sh->sh_path);
236 236
237 237 if (shl) {
238 238 sh->sh_size = shl->shl_path + shl->shl_res +
239 239 shl->shl_fstype + shl->shl_opts + shl->shl_descr;
240 240 } else {
241 241 sh->sh_size = strlen(sh->sh_path) +
242 242 strlen(sh->sh_res) + strlen(sh->sh_fstype) +
243 243 strlen(sh->sh_opts) + strlen(sh->sh_descr);
244 244 }
245 245
246 246 /*
247 247 * We need to account for field seperators and
248 248 * the EOL.
249 249 */
250 250 sh->sh_size += 5;
251 251
252 252 /*
253 253 * Now walk down the hash table and add the new entry!
254 254 */
255 255 for (p = NULL, s = sht->s_buckets[iHash].ssh_sh;
256 256 s != NULL; s = s->sh_next) {
257 257 /*
258 258 * We need exact matches.
259 259 *
260 260 * We found a matching path. Either we have a
261 261 * duplicate path in a share command or we are
262 262 * being asked to replace an existing entry.
263 263 */
264 264 if (strcmp(sh->sh_path, s->sh_path) == 0 &&
265 265 strlen(s->sh_path) == iPath) {
266 266 if (p) {
267 267 p->sh_next = sh;
268 268 } else {
269 269 sht->s_buckets[iHash].ssh_sh = sh;
270 270 }
271 271
272 272 sh->sh_next = s->sh_next;
273 273
↓ open down ↓ |
98 lines elided |
↑ open up ↑ |
274 274 ASSERT(sharetab_size >= s->sh_size);
275 275 sharetab_size -= s->sh_size;
276 276 sharetab_size += sh->sh_size;
277 277
278 278 /*
279 279 * Get rid of the old node.
280 280 */
281 281 sharefree(s, NULL);
282 282
283 283 gethrestime(&sharetab_mtime);
284 - atomic_add_32(&sharetab_generation, 1);
284 + atomic_inc_32(&sharetab_generation);
285 285
286 286 ASSERT(sht->s_buckets[iHash].ssh_count != 0);
287 287 rw_exit(&sharetab_lock);
288 288
289 289 return (0);
290 290 }
291 291
292 292 p = s;
293 293 }
294 294
295 295 /*
296 296 * Okay, we have gone through the entire hash chain and not
297 297 * found a match. We just need to add this node.
298 298 */
299 299 sh->sh_next = sht->s_buckets[iHash].ssh_sh;
300 300 sht->s_buckets[iHash].ssh_sh = sh;
301 - atomic_add_32(&sht->s_buckets[iHash].ssh_count, 1);
302 - atomic_add_32(&sht->s_count, 1);
303 - atomic_add_32(&sharetab_count, 1);
301 + atomic_inc_32(&sht->s_buckets[iHash].ssh_count);
302 + atomic_inc_32(&sht->s_count);
303 + atomic_inc_32(&sharetab_count);
304 304 sharetab_size += sh->sh_size;
305 305
306 306 gethrestime(&sharetab_mtime);
307 - atomic_add_32(&sharetab_generation, 1);
307 + atomic_inc_32(&sharetab_generation);
308 308
309 309 rw_exit(&sharetab_lock);
310 310
311 311 return (0);
312 312 }
313 313
314 314 void
315 315 sharefs_sharetab_init(void)
316 316 {
317 317 rw_init(&sharetab_lock, NULL, RW_DEFAULT, NULL);
318 318 rw_init(&sharefs_lock, NULL, RW_DEFAULT, NULL);
319 319
320 320 sharetab_size = 0;
321 321 sharetab_count = 0;
322 322 sharetab_generation = 1;
323 323
324 324 gethrestime(&sharetab_mtime);
325 325 gethrestime(&sharetab_snap_time);
326 326 }
327 327
328 328 int
329 329 sharefs_impl(enum sharefs_sys_op opcode, share_t *sh_in, uint32_t iMaxLen)
330 330 {
331 331 int error = 0;
332 332 size_t len;
333 333 size_t bufsz;
334 334 share_t *sh;
335 335
336 336 sharefs_lens_t shl;
337 337
338 338 model_t model;
339 339
340 340 char *buf = NULL;
341 341
342 342 STRUCT_DECL(share, u_sh);
343 343
344 344 bufsz = iMaxLen;
345 345
346 346 /*
347 347 * Before we do anything, lets make sure we have
348 348 * a sharetab in memory if we need one.
349 349 */
350 350 rw_enter(&sharetab_lock, RW_READER);
351 351 switch (opcode) {
352 352 case (SHAREFS_REMOVE) :
353 353 case (SHAREFS_REPLACE) :
354 354 if (!sharefs_sharetab) {
355 355 rw_exit(&sharetab_lock);
356 356 return (set_errno(ENOENT));
357 357 }
358 358 break;
359 359 case (SHAREFS_ADD) :
360 360 default :
361 361 break;
362 362 }
363 363 rw_exit(&sharetab_lock);
364 364
365 365 model = get_udatamodel();
366 366
367 367 /*
368 368 * Initialize the data pointers.
369 369 */
370 370 STRUCT_INIT(u_sh, model);
371 371 if (copyin(sh_in, STRUCT_BUF(u_sh), STRUCT_SIZE(u_sh))) {
372 372 return (set_errno(EFAULT));
373 373 }
374 374
375 375 /*
376 376 * Get the share.
377 377 */
378 378 sh = kmem_zalloc(sizeof (share_t), KM_SLEEP);
379 379
380 380 /*
381 381 * Get some storage for copying in the strings.
382 382 */
383 383 buf = kmem_zalloc(bufsz + 1, KM_SLEEP);
384 384 bzero(&shl, sizeof (sharefs_lens_t));
385 385
386 386 /*
387 387 * Only grab these two until we know what we want.
388 388 */
389 389 SHARETAB_COPYIN(path);
390 390 SHARETAB_COPYIN(fstype);
391 391
392 392 switch (opcode) {
393 393 case (SHAREFS_ADD) :
394 394 case (SHAREFS_REPLACE) :
395 395 SHARETAB_COPYIN(res);
396 396 SHARETAB_COPYIN(opts);
397 397 SHARETAB_COPYIN(descr);
398 398
399 399 error = sharefs_add(sh, &shl);
400 400 break;
401 401
402 402 case (SHAREFS_REMOVE) :
403 403
404 404 error = sharefs_remove(sh, &shl);
405 405 break;
406 406
407 407 default:
408 408 error = EINVAL;
409 409 break;
410 410 }
411 411
412 412 cleanup:
413 413
414 414 /*
415 415 * If there is no error, then we have stashed the structure
416 416 * away in the sharetab hash table or have deleted it.
417 417 *
418 418 * Either way, the only reason to blow away the data is if
419 419 * there was an error.
420 420 */
421 421 if (error != 0) {
422 422 sharefree(sh, &shl);
423 423 }
424 424
425 425 if (buf) {
426 426 kmem_free(buf, bufsz + 1);
427 427 }
428 428
429 429 return ((error != 0) ? set_errno(error) : 0);
430 430 }
431 431
432 432 int
433 433 sharefs(enum sharefs_sys_op opcode, share_t *sh_in, uint32_t iMaxLen)
434 434 {
435 435 if (secpolicy_sys_config(CRED(), B_FALSE) != 0)
436 436 return (set_errno(EPERM));
437 437
438 438 return (sharefs_impl(opcode, sh_in, iMaxLen));
439 439 }
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX