Print this page
*** NO COMMENTS ***
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/fs/nfs/nfs_acl_srv.c
+++ new/usr/src/uts/common/fs/nfs/nfs_acl_srv.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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/param.h>
27 27 #include <sys/types.h>
28 28 #include <sys/systm.h>
29 29 #include <sys/cred.h>
30 30 #include <sys/proc.h>
31 31 #include <sys/user.h>
32 32 #include <sys/buf.h>
33 33 #include <sys/vfs.h>
34 34 #include <sys/vnode.h>
35 35 #include <sys/pathname.h>
36 36 #include <sys/uio.h>
37 37 #include <sys/file.h>
38 38 #include <sys/stat.h>
39 39 #include <sys/errno.h>
40 40 #include <sys/socket.h>
41 41 #include <sys/sysmacros.h>
42 42 #include <sys/siginfo.h>
43 43 #include <sys/tiuser.h>
44 44 #include <sys/statvfs.h>
45 45 #include <sys/t_kuser.h>
46 46 #include <sys/kmem.h>
47 47 #include <sys/kstat.h>
48 48 #include <sys/acl.h>
49 49 #include <sys/dirent.h>
50 50 #include <sys/cmn_err.h>
51 51 #include <sys/debug.h>
52 52 #include <sys/unistd.h>
53 53 #include <sys/vtrace.h>
54 54 #include <sys/mode.h>
55 55
56 56 #include <rpc/types.h>
57 57 #include <rpc/auth.h>
58 58 #include <rpc/svc.h>
59 59 #include <rpc/xdr.h>
60 60
61 61 #include <nfs/nfs.h>
62 62 #include <nfs/export.h>
63 63 #include <nfs/nfssys.h>
64 64 #include <nfs/nfs_clnt.h>
65 65 #include <nfs/nfs_acl.h>
66 66
67 67 #include <fs/fs_subr.h>
68 68
69 69 /*
70 70 * These are the interface routines for the server side of the
71 71 * NFS ACL server. See the NFS ACL protocol specification
72 72 * for a description of this interface.
73 73 */
74 74
75 75 /* ARGSUSED */
76 76 void
77 77 acl2_getacl(GETACL2args *args, GETACL2res *resp, struct exportinfo *exi,
78 78 struct svc_req *req, cred_t *cr)
79 79 {
80 80 int error;
81 81 vnode_t *vp;
82 82 vattr_t va;
83 83
84 84 vp = nfs_fhtovp(&args->fh, exi);
85 85 if (vp == NULL) {
86 86 resp->status = NFSERR_STALE;
87 87 return;
88 88 }
89 89
90 90 bzero((caddr_t)&resp->resok.acl, sizeof (resp->resok.acl));
91 91
92 92 resp->resok.acl.vsa_mask = args->mask;
93 93
94 94 error = VOP_GETSECATTR(vp, &resp->resok.acl, 0, cr, NULL);
95 95
96 96 if ((error == ENOSYS) && !(exi->exi_export.ex_flags & EX_NOACLFAB)) {
97 97 /*
98 98 * If the underlying file system doesn't support
99 99 * aclent_t type acls, fabricate an acl. This is
100 100 * required in order to to support existing clients
101 101 * that require the call to VOP_GETSECATTR to
102 102 * succeed while making the assumption that all
103 103 * file systems support aclent_t type acls. This
104 104 * causes problems for servers exporting ZFS file
105 105 * systems because ZFS supports ace_t type acls,
106 106 * and fails (with ENOSYS) when asked for aclent_t
107 107 * type acls.
108 108 *
109 109 * Note: if the fs_fab_acl() fails, we have other problems.
110 110 * This error should be returned to the caller.
111 111 */
112 112 error = fs_fab_acl(vp, &resp->resok.acl, 0, cr, NULL);
113 113 }
114 114
115 115 if (error) {
116 116 VN_RELE(vp);
117 117 resp->status = puterrno(error);
118 118 return;
119 119 }
120 120
121 121 va.va_mask = AT_ALL;
122 122 error = rfs4_delegated_getattr(vp, &va, 0, cr);
123 123
124 124 VN_RELE(vp);
125 125
126 126 /* check for overflowed values */
127 127 if (!error) {
128 128 error = vattr_to_nattr(&va, &resp->resok.attr);
129 129 }
130 130 if (error) {
131 131 resp->status = puterrno(error);
132 132 if (resp->resok.acl.vsa_aclcnt > 0 &&
133 133 resp->resok.acl.vsa_aclentp != NULL) {
134 134 kmem_free((caddr_t)resp->resok.acl.vsa_aclentp,
135 135 resp->resok.acl.vsa_aclcnt * sizeof (aclent_t));
136 136 }
137 137 if (resp->resok.acl.vsa_dfaclcnt > 0 &&
138 138 resp->resok.acl.vsa_dfaclentp != NULL) {
139 139 kmem_free((caddr_t)resp->resok.acl.vsa_dfaclentp,
140 140 resp->resok.acl.vsa_dfaclcnt * sizeof (aclent_t));
141 141 }
142 142 return;
143 143 }
144 144
145 145 resp->status = NFS_OK;
146 146 if (!(args->mask & NA_ACL)) {
147 147 if (resp->resok.acl.vsa_aclcnt > 0 &&
148 148 resp->resok.acl.vsa_aclentp != NULL) {
149 149 kmem_free((caddr_t)resp->resok.acl.vsa_aclentp,
150 150 resp->resok.acl.vsa_aclcnt * sizeof (aclent_t));
151 151 }
152 152 resp->resok.acl.vsa_aclentp = NULL;
153 153 }
154 154 if (!(args->mask & NA_DFACL)) {
155 155 if (resp->resok.acl.vsa_dfaclcnt > 0 &&
156 156 resp->resok.acl.vsa_dfaclentp != NULL) {
157 157 kmem_free((caddr_t)resp->resok.acl.vsa_dfaclentp,
158 158 resp->resok.acl.vsa_dfaclcnt * sizeof (aclent_t));
159 159 }
160 160 resp->resok.acl.vsa_dfaclentp = NULL;
161 161 }
162 162 }
163 163
164 164 void *
165 165 acl2_getacl_getfh(GETACL2args *args)
166 166 {
167 167
168 168 return (&args->fh);
169 169 }
170 170
171 171 void
172 172 acl2_getacl_free(GETACL2res *resp)
173 173 {
174 174
175 175 if (resp->status == NFS_OK) {
176 176 if (resp->resok.acl.vsa_aclcnt > 0 &&
177 177 resp->resok.acl.vsa_aclentp != NULL) {
178 178 kmem_free((caddr_t)resp->resok.acl.vsa_aclentp,
179 179 resp->resok.acl.vsa_aclcnt * sizeof (aclent_t));
180 180 }
181 181 if (resp->resok.acl.vsa_dfaclcnt > 0 &&
182 182 resp->resok.acl.vsa_dfaclentp != NULL) {
183 183 kmem_free((caddr_t)resp->resok.acl.vsa_dfaclentp,
184 184 resp->resok.acl.vsa_dfaclcnt * sizeof (aclent_t));
185 185 }
186 186 }
187 187 }
188 188
189 189 /* ARGSUSED */
190 190 void
191 191 acl2_setacl(SETACL2args *args, SETACL2res *resp, struct exportinfo *exi,
192 192 struct svc_req *req, cred_t *cr)
193 193 {
194 194 int error;
195 195 vnode_t *vp;
196 196 vattr_t va;
197 197
198 198 vp = nfs_fhtovp(&args->fh, exi);
199 199 if (vp == NULL) {
200 200 resp->status = NFSERR_STALE;
201 201 return;
202 202 }
203 203
204 204 if (rdonly(exi, req) || vn_is_readonly(vp)) {
205 205 VN_RELE(vp);
206 206 resp->status = NFSERR_ROFS;
207 207 return;
208 208 }
209 209
210 210 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
211 211 error = VOP_SETSECATTR(vp, &args->acl, 0, cr, NULL);
212 212 if (error) {
213 213 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
214 214 VN_RELE(vp);
215 215 resp->status = puterrno(error);
216 216 return;
217 217 }
218 218
219 219 va.va_mask = AT_ALL;
220 220 error = rfs4_delegated_getattr(vp, &va, 0, cr);
221 221
222 222 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
223 223 VN_RELE(vp);
224 224
225 225 /* check for overflowed values */
226 226 if (!error) {
227 227 error = vattr_to_nattr(&va, &resp->resok.attr);
228 228 }
229 229 if (error) {
230 230 resp->status = puterrno(error);
231 231 return;
232 232 }
233 233
234 234 resp->status = NFS_OK;
235 235 }
236 236
237 237 void *
238 238 acl2_setacl_getfh(SETACL2args *args)
239 239 {
240 240
241 241 return (&args->fh);
242 242 }
243 243
244 244 /* ARGSUSED */
245 245 void
246 246 acl2_getattr(GETATTR2args *args, GETATTR2res *resp, struct exportinfo *exi,
247 247 struct svc_req *req, cred_t *cr)
248 248 {
249 249 int error;
250 250 vnode_t *vp;
251 251 vattr_t va;
252 252
253 253 vp = nfs_fhtovp(&args->fh, exi);
254 254 if (vp == NULL) {
255 255 resp->status = NFSERR_STALE;
256 256 return;
257 257 }
258 258
259 259 va.va_mask = AT_ALL;
260 260 error = rfs4_delegated_getattr(vp, &va, 0, cr);
261 261
262 262 VN_RELE(vp);
263 263
264 264 /* check for overflowed values */
265 265 if (!error) {
266 266 error = vattr_to_nattr(&va, &resp->resok.attr);
267 267 }
268 268 if (error) {
269 269 resp->status = puterrno(error);
270 270 return;
271 271 }
272 272
273 273 resp->status = NFS_OK;
274 274 }
275 275
276 276 void *
277 277 acl2_getattr_getfh(GETATTR2args *args)
278 278 {
279 279
280 280 return (&args->fh);
281 281 }
282 282
283 283 /* ARGSUSED */
284 284 void
285 285 acl2_access(ACCESS2args *args, ACCESS2res *resp, struct exportinfo *exi,
286 286 struct svc_req *req, cred_t *cr)
287 287 {
288 288 int error;
289 289 vnode_t *vp;
290 290 vattr_t va;
291 291 int checkwriteperm;
292 292
293 293 vp = nfs_fhtovp(&args->fh, exi);
294 294 if (vp == NULL) {
295 295 resp->status = NFSERR_STALE;
296 296 return;
297 297 }
298 298
299 299 /*
300 300 * If the file system is exported read only, it is not appropriate
301 301 * to check write permissions for regular files and directories.
302 302 * Special files are interpreted by the client, so the underlying
303 303 * permissions are sent back to the client for interpretation.
304 304 */
305 305 if (rdonly(exi, req) && (vp->v_type == VREG || vp->v_type == VDIR))
306 306 checkwriteperm = 0;
307 307 else
308 308 checkwriteperm = 1;
309 309
310 310 /*
311 311 * We need the mode so that we can correctly determine access
312 312 * permissions relative to a mandatory lock file. Access to
313 313 * mandatory lock files is denied on the server, so it might
314 314 * as well be reflected to the server during the open.
315 315 */
316 316 va.va_mask = AT_MODE;
317 317 error = VOP_GETATTR(vp, &va, 0, cr, NULL);
318 318 if (error) {
319 319 VN_RELE(vp);
320 320 resp->status = puterrno(error);
321 321 return;
322 322 }
323 323
324 324 resp->resok.access = 0;
325 325
326 326 if (args->access & ACCESS2_READ) {
327 327 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL);
328 328 if (!error && !MANDLOCK(vp, va.va_mode))
329 329 resp->resok.access |= ACCESS2_READ;
330 330 }
331 331 if ((args->access & ACCESS2_LOOKUP) && vp->v_type == VDIR) {
332 332 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
333 333 if (!error)
334 334 resp->resok.access |= ACCESS2_LOOKUP;
335 335 }
336 336 if (checkwriteperm &&
337 337 (args->access & (ACCESS2_MODIFY|ACCESS2_EXTEND))) {
338 338 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
339 339 if (!error && !MANDLOCK(vp, va.va_mode))
340 340 resp->resok.access |=
341 341 (args->access & (ACCESS2_MODIFY|ACCESS2_EXTEND));
342 342 }
343 343 if (checkwriteperm &&
344 344 (args->access & ACCESS2_DELETE) && (vp->v_type == VDIR)) {
345 345 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL);
346 346 if (!error)
347 347 resp->resok.access |= ACCESS2_DELETE;
348 348 }
349 349 if (args->access & ACCESS2_EXECUTE) {
350 350 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL);
351 351 if (!error && !MANDLOCK(vp, va.va_mode))
352 352 resp->resok.access |= ACCESS2_EXECUTE;
353 353 }
354 354
355 355 va.va_mask = AT_ALL;
356 356 error = rfs4_delegated_getattr(vp, &va, 0, cr);
357 357
358 358 VN_RELE(vp);
359 359
360 360 /* check for overflowed values */
361 361 if (!error) {
362 362 error = vattr_to_nattr(&va, &resp->resok.attr);
363 363 }
364 364 if (error) {
365 365 resp->status = puterrno(error);
366 366 return;
367 367 }
368 368
369 369 resp->status = NFS_OK;
370 370 }
371 371
372 372 void *
373 373 acl2_access_getfh(ACCESS2args *args)
374 374 {
375 375
376 376 return (&args->fh);
377 377 }
378 378
379 379 /* ARGSUSED */
380 380 void
381 381 acl2_getxattrdir(GETXATTRDIR2args *args, GETXATTRDIR2res *resp,
382 382 struct exportinfo *exi, struct svc_req *req, cred_t *cr)
383 383 {
384 384 int error;
385 385 int flags;
386 386 vnode_t *vp, *avp;
387 387
388 388 vp = nfs_fhtovp(&args->fh, exi);
389 389 if (vp == NULL) {
390 390 resp->status = NFSERR_STALE;
391 391 return;
392 392 }
393 393
394 394 flags = LOOKUP_XATTR;
395 395 if (args->create)
396 396 flags |= CREATE_XATTR_DIR;
397 397 else {
398 398 ulong_t val = 0;
399 399 error = VOP_PATHCONF(vp, _PC_SATTR_EXISTS, &val, cr, NULL);
400 400 if (!error && val == 0) {
401 401 error = VOP_PATHCONF(vp, _PC_XATTR_EXISTS,
402 402 &val, cr, NULL);
403 403 if (!error && val == 0) {
404 404 VN_RELE(vp);
405 405 resp->status = NFSERR_NOENT;
406 406 return;
407 407 }
408 408 }
409 409 }
410 410
411 411 error = VOP_LOOKUP(vp, "", &avp, NULL, flags, NULL, cr,
412 412 NULL, NULL, NULL);
413 413 if (!error && avp == vp) { /* lookup of "" on old FS? */
414 414 error = EINVAL;
415 415 VN_RELE(avp);
416 416 }
417 417 if (!error) {
418 418 struct vattr va;
419 419 va.va_mask = AT_ALL;
420 420 error = rfs4_delegated_getattr(avp, &va, 0, cr);
421 421 if (!error) {
422 422 error = vattr_to_nattr(&va, &resp->resok.attr);
423 423 if (!error)
424 424 error = makefh(&resp->resok.fh, avp, exi);
425 425 }
426 426 VN_RELE(avp);
427 427 }
428 428
429 429 VN_RELE(vp);
430 430
431 431 if (error) {
432 432 resp->status = puterrno(error);
433 433 return;
434 434 }
435 435 resp->status = NFS_OK;
436 436 }
437 437
438 438 void *
439 439 acl2_getxattrdir_getfh(GETXATTRDIR2args *args)
440 440 {
441 441 return (&args->fh);
442 442 }
443 443
444 444 /* ARGSUSED */
445 445 void
446 446 acl3_getacl(GETACL3args *args, GETACL3res *resp, struct exportinfo *exi,
447 447 struct svc_req *req, cred_t *cr)
448 448 {
449 449 int error;
450 450 vnode_t *vp;
451 451 vattr_t *vap;
↓ open down ↓ |
451 lines elided |
↑ open up ↑ |
452 452 vattr_t va;
453 453
454 454 vap = NULL;
455 455
456 456 vp = nfs3_fhtovp(&args->fh, exi);
457 457 if (vp == NULL) {
458 458 error = ESTALE;
459 459 goto out;
460 460 }
461 461
462 -#ifdef DEBUG
463 - if (rfs3_do_post_op_attr) {
464 - va.va_mask = AT_ALL;
465 - vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
466 - } else
467 - vap = NULL;
468 -#else
469 462 va.va_mask = AT_ALL;
470 463 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
471 -#endif
472 464
473 465 bzero((caddr_t)&resp->resok.acl, sizeof (resp->resok.acl));
474 466
475 467 resp->resok.acl.vsa_mask = args->mask;
476 468
477 469 error = VOP_GETSECATTR(vp, &resp->resok.acl, 0, cr, NULL);
478 470
479 471 if ((error == ENOSYS) && !(exi->exi_export.ex_flags & EX_NOACLFAB)) {
480 472 /*
481 473 * If the underlying file system doesn't support
482 474 * aclent_t type acls, fabricate an acl. This is
483 475 * required in order to to support existing clients
484 476 * that require the call to VOP_GETSECATTR to
485 477 * succeed while making the assumption that all
486 478 * file systems support aclent_t type acls. This
487 479 * causes problems for servers exporting ZFS file
488 480 * systems because ZFS supports ace_t type acls,
489 481 * and fails (with ENOSYS) when asked for aclent_t
490 482 * type acls.
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
491 483 *
492 484 * Note: if the fs_fab_acl() fails, we have other problems.
493 485 * This error should be returned to the caller.
494 486 */
495 487 error = fs_fab_acl(vp, &resp->resok.acl, 0, cr, NULL);
496 488 }
497 489
498 490 if (error)
499 491 goto out;
500 492
501 -#ifdef DEBUG
502 - if (rfs3_do_post_op_attr) {
503 - va.va_mask = AT_ALL;
504 - vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
505 - } else
506 - vap = NULL;
507 -#else
508 493 va.va_mask = AT_ALL;
509 494 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
510 -#endif
511 495
512 496 VN_RELE(vp);
513 497
514 498 resp->status = NFS3_OK;
515 499 vattr_to_post_op_attr(vap, &resp->resok.attr);
516 500 if (!(args->mask & NA_ACL)) {
517 501 if (resp->resok.acl.vsa_aclcnt > 0 &&
518 502 resp->resok.acl.vsa_aclentp != NULL) {
519 503 kmem_free((caddr_t)resp->resok.acl.vsa_aclentp,
520 504 resp->resok.acl.vsa_aclcnt * sizeof (aclent_t));
521 505 }
522 506 resp->resok.acl.vsa_aclentp = NULL;
523 507 }
524 508 if (!(args->mask & NA_DFACL)) {
525 509 if (resp->resok.acl.vsa_dfaclcnt > 0 &&
526 510 resp->resok.acl.vsa_dfaclentp != NULL) {
527 511 kmem_free((caddr_t)resp->resok.acl.vsa_dfaclentp,
528 512 resp->resok.acl.vsa_dfaclcnt * sizeof (aclent_t));
529 513 }
530 514 resp->resok.acl.vsa_dfaclentp = NULL;
531 515 }
532 516 return;
533 517
534 518 out:
535 519 if (curthread->t_flag & T_WOULDBLOCK) {
536 520 curthread->t_flag &= ~T_WOULDBLOCK;
537 521 resp->status = NFS3ERR_JUKEBOX;
538 522 } else
539 523 resp->status = puterrno3(error);
540 524 out1:
541 525 if (vp != NULL)
542 526 VN_RELE(vp);
543 527 vattr_to_post_op_attr(vap, &resp->resfail.attr);
544 528 }
545 529
546 530 void *
547 531 acl3_getacl_getfh(GETACL3args *args)
548 532 {
549 533
550 534 return (&args->fh);
551 535 }
552 536
553 537 void
554 538 acl3_getacl_free(GETACL3res *resp)
555 539 {
556 540
557 541 if (resp->status == NFS3_OK) {
558 542 if (resp->resok.acl.vsa_aclcnt > 0 &&
559 543 resp->resok.acl.vsa_aclentp != NULL) {
560 544 kmem_free((caddr_t)resp->resok.acl.vsa_aclentp,
561 545 resp->resok.acl.vsa_aclcnt * sizeof (aclent_t));
562 546 }
563 547 if (resp->resok.acl.vsa_dfaclcnt > 0 &&
564 548 resp->resok.acl.vsa_dfaclentp != NULL) {
565 549 kmem_free((caddr_t)resp->resok.acl.vsa_dfaclentp,
566 550 resp->resok.acl.vsa_dfaclcnt * sizeof (aclent_t));
567 551 }
568 552 }
569 553 }
570 554
571 555 /* ARGSUSED */
572 556 void
573 557 acl3_setacl(SETACL3args *args, SETACL3res *resp, struct exportinfo *exi,
574 558 struct svc_req *req, cred_t *cr)
575 559 {
576 560 int error;
577 561 vnode_t *vp;
578 562 vattr_t *vap;
579 563 vattr_t va;
580 564
↓ open down ↓ |
60 lines elided |
↑ open up ↑ |
581 565 vap = NULL;
582 566
583 567 vp = nfs3_fhtovp(&args->fh, exi);
584 568 if (vp == NULL) {
585 569 error = ESTALE;
586 570 goto out1;
587 571 }
588 572
589 573 (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
590 574
591 -#ifdef DEBUG
592 - if (rfs3_do_post_op_attr) {
593 - va.va_mask = AT_ALL;
594 - vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
595 - } else
596 - vap = NULL;
597 -#else
598 575 va.va_mask = AT_ALL;
599 576 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
600 -#endif
601 577
602 578 if (rdonly(exi, req) || vn_is_readonly(vp)) {
603 579 resp->status = NFS3ERR_ROFS;
604 580 goto out1;
605 581 }
606 582
607 583 error = VOP_SETSECATTR(vp, &args->acl, 0, cr, NULL);
608 584
609 -#ifdef DEBUG
610 - if (rfs3_do_post_op_attr) {
611 - va.va_mask = AT_ALL;
612 - vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
613 - } else
614 - vap = NULL;
615 -#else
616 585 va.va_mask = AT_ALL;
617 586 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
618 -#endif
619 587
620 588 if (error)
621 589 goto out;
622 590
623 591 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
624 592 VN_RELE(vp);
625 593
626 594 resp->status = NFS3_OK;
627 595 vattr_to_post_op_attr(vap, &resp->resok.attr);
628 596 return;
629 597
630 598 out:
631 599 if (curthread->t_flag & T_WOULDBLOCK) {
632 600 curthread->t_flag &= ~T_WOULDBLOCK;
633 601 resp->status = NFS3ERR_JUKEBOX;
634 602 } else
635 603 resp->status = puterrno3(error);
636 604 out1:
637 605 if (vp != NULL) {
638 606 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
639 607 VN_RELE(vp);
640 608 }
641 609 vattr_to_post_op_attr(vap, &resp->resfail.attr);
642 610 }
643 611
644 612 void *
645 613 acl3_setacl_getfh(SETACL3args *args)
646 614 {
647 615
648 616 return (&args->fh);
649 617 }
650 618
651 619 /* ARGSUSED */
652 620 void
653 621 acl3_getxattrdir(GETXATTRDIR3args *args, GETXATTRDIR3res *resp,
654 622 struct exportinfo *exi, struct svc_req *req, cred_t *cr)
655 623 {
656 624 int error;
657 625 int flags;
658 626 vnode_t *vp, *avp;
659 627
660 628 vp = nfs3_fhtovp(&args->fh, exi);
661 629 if (vp == NULL) {
662 630 resp->status = NFS3ERR_STALE;
663 631 return;
664 632 }
665 633
666 634 flags = LOOKUP_XATTR;
667 635 if (args->create)
668 636 flags |= CREATE_XATTR_DIR;
669 637 else {
670 638 ulong_t val = 0;
671 639
672 640 error = VOP_PATHCONF(vp, _PC_SATTR_EXISTS, &val, cr, NULL);
673 641 if (!error && val == 0) {
674 642 error = VOP_PATHCONF(vp, _PC_XATTR_EXISTS,
675 643 &val, cr, NULL);
676 644 if (!error && val == 0) {
677 645 VN_RELE(vp);
678 646 resp->status = NFS3ERR_NOENT;
679 647 return;
680 648 }
681 649 }
682 650 }
683 651
684 652 error = VOP_LOOKUP(vp, "", &avp, NULL, flags, NULL, cr,
685 653 NULL, NULL, NULL);
686 654 if (!error && avp == vp) { /* lookup of "" on old FS? */
687 655 error = EINVAL;
688 656 VN_RELE(avp);
689 657 }
690 658 if (!error) {
691 659 struct vattr va;
692 660 va.va_mask = AT_ALL;
693 661 error = rfs4_delegated_getattr(avp, &va, 0, cr);
694 662 if (!error) {
695 663 vattr_to_post_op_attr(&va, &resp->resok.attr);
696 664 error = makefh3(&resp->resok.fh, avp, exi);
697 665 }
698 666 VN_RELE(avp);
699 667 }
700 668
701 669 VN_RELE(vp);
702 670
703 671 if (error) {
704 672 resp->status = puterrno3(error);
705 673 return;
706 674 }
707 675 resp->status = NFS3_OK;
708 676 }
709 677
710 678 void *
711 679 acl3_getxattrdir_getfh(GETXATTRDIR3args *args)
712 680 {
713 681 return (&args->fh);
714 682 }
↓ open down ↓ |
86 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX