1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 #include <sys/param.h> 30 #include <sys/types.h> 31 #include <sys/systm.h> 32 #include <sys/cred.h> 33 #include <sys/buf.h> 34 #include <sys/vfs.h> 35 #include <sys/vnode.h> 36 #include <sys/uio.h> 37 #include <sys/errno.h> 38 #include <sys/sysmacros.h> 39 #include <sys/statvfs.h> 40 #include <sys/kmem.h> 41 #include <sys/dirent.h> 42 #include <sys/cmn_err.h> 43 #include <sys/debug.h> 44 #include <sys/systeminfo.h> 45 #include <sys/flock.h> 46 #include <sys/nbmlock.h> 47 #include <sys/policy.h> 48 #include <sys/sdt.h> 49 50 #include <rpc/types.h> 51 #include <rpc/auth.h> 52 #include <rpc/svc.h> 53 #include <rpc/rpc_rdma.h> 54 55 #include <nfs/nfs.h> 56 #include <nfs/export.h> 57 #include <nfs/nfs_cmd.h> 58 59 #include <sys/strsubr.h> 60 61 #include <sys/tsol/label.h> 62 #include <sys/tsol/tndb.h> 63 64 #include <sys/zone.h> 65 66 #include <inet/ip.h> 67 #include <inet/ip6.h> 68 69 /* 70 * These are the interface routines for the server side of the 71 * Network File System. See the NFS version 3 protocol specification 72 * for a description of this interface. 73 */ 74 75 #ifdef DEBUG 76 int rfs3_do_pre_op_attr = 1; 77 int rfs3_do_post_op_attr = 1; 78 int rfs3_do_post_op_fh3 = 1; 79 #endif 80 81 static writeverf3 write3verf; 82 83 static int sattr3_to_vattr(sattr3 *, struct vattr *); 84 static int vattr_to_fattr3(struct vattr *, fattr3 *); 85 static int vattr_to_wcc_attr(struct vattr *, wcc_attr *); 86 static void vattr_to_pre_op_attr(struct vattr *, pre_op_attr *); 87 static void vattr_to_wcc_data(struct vattr *, struct vattr *, wcc_data *); 88 static int rdma_setup_read_data3(READ3args *, READ3resok *); 89 90 u_longlong_t nfs3_srv_caller_id; 91 92 /* ARGSUSED */ 93 void 94 rfs3_getattr(GETATTR3args *args, GETATTR3res *resp, struct exportinfo *exi, 95 struct svc_req *req, cred_t *cr) 96 { 97 int error; 98 vnode_t *vp; 99 struct vattr va; 100 101 vp = nfs3_fhtovp(&args->object, exi); 102 103 DTRACE_NFSV3_4(op__getattr__start, struct svc_req *, req, 104 cred_t *, cr, vnode_t *, vp, GETATTR3args *, args); 105 106 if (vp == NULL) { 107 error = ESTALE; 108 goto out; 109 } 110 111 va.va_mask = AT_ALL; 112 error = rfs4_delegated_getattr(vp, &va, 0, cr); 113 114 if (!error) { 115 /* Lie about the object type for a referral */ 116 if (vn_is_nfs_reparse(vp, cr)) 117 va.va_type = VLNK; 118 119 /* overflow error if time or size is out of range */ 120 error = vattr_to_fattr3(&va, &resp->resok.obj_attributes); 121 if (error) 122 goto out; 123 resp->status = NFS3_OK; 124 125 DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req, 126 cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp); 127 128 VN_RELE(vp); 129 130 return; 131 } 132 133 out: 134 if (curthread->t_flag & T_WOULDBLOCK) { 135 curthread->t_flag &= ~T_WOULDBLOCK; 136 resp->status = NFS3ERR_JUKEBOX; 137 } else 138 resp->status = puterrno3(error); 139 140 DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req, 141 cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp); 142 143 if (vp != NULL) 144 VN_RELE(vp); 145 } 146 147 void * 148 rfs3_getattr_getfh(GETATTR3args *args) 149 { 150 151 return (&args->object); 152 } 153 154 void 155 rfs3_setattr(SETATTR3args *args, SETATTR3res *resp, struct exportinfo *exi, 156 struct svc_req *req, cred_t *cr) 157 { 158 int error; 159 vnode_t *vp; 160 struct vattr *bvap; 161 struct vattr bva; 162 struct vattr *avap; 163 struct vattr ava; 164 int flag; 165 int in_crit = 0; 166 struct flock64 bf; 167 caller_context_t ct; 168 169 bvap = NULL; 170 avap = NULL; 171 172 vp = nfs3_fhtovp(&args->object, exi); 173 174 DTRACE_NFSV3_4(op__setattr__start, struct svc_req *, req, 175 cred_t *, cr, vnode_t *, vp, SETATTR3args *, args); 176 177 if (vp == NULL) { 178 error = ESTALE; 179 goto out; 180 } 181 182 error = sattr3_to_vattr(&args->new_attributes, &ava); 183 if (error) 184 goto out; 185 186 if (is_system_labeled()) { 187 bslabel_t *clabel = req->rq_label; 188 189 ASSERT(clabel != NULL); 190 DTRACE_PROBE2(tx__rfs3__log__info__opsetattr__clabel, char *, 191 "got client label from request(1)", struct svc_req *, req); 192 193 if (!blequal(&l_admin_low->tsl_label, clabel)) { 194 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, 195 exi)) { 196 resp->status = NFS3ERR_ACCES; 197 goto out1; 198 } 199 } 200 } 201 202 /* 203 * We need to specially handle size changes because of 204 * possible conflicting NBMAND locks. Get into critical 205 * region before VOP_GETATTR, so the size attribute is 206 * valid when checking conflicts. 207 * 208 * Also, check to see if the v4 side of the server has 209 * delegated this file. If so, then we return JUKEBOX to 210 * allow the client to retrasmit its request. 211 */ 212 if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) { 213 if (nbl_need_check(vp)) { 214 nbl_start_crit(vp, RW_READER); 215 in_crit = 1; 216 } 217 } 218 219 bva.va_mask = AT_ALL; 220 error = rfs4_delegated_getattr(vp, &bva, 0, cr); 221 222 /* 223 * If we can't get the attributes, then we can't do the 224 * right access checking. So, we'll fail the request. 225 */ 226 if (error) 227 goto out; 228 229 #ifdef DEBUG 230 if (rfs3_do_pre_op_attr) 231 bvap = &bva; 232 #else 233 bvap = &bva; 234 #endif 235 236 if (rdonly(exi, req) || vn_is_readonly(vp)) { 237 resp->status = NFS3ERR_ROFS; 238 goto out1; 239 } 240 241 if (args->guard.check && 242 (args->guard.obj_ctime.seconds != bva.va_ctime.tv_sec || 243 args->guard.obj_ctime.nseconds != bva.va_ctime.tv_nsec)) { 244 resp->status = NFS3ERR_NOT_SYNC; 245 goto out1; 246 } 247 248 if (args->new_attributes.mtime.set_it == SET_TO_CLIENT_TIME) 249 flag = ATTR_UTIME; 250 else 251 flag = 0; 252 253 /* 254 * If the filesystem is exported with nosuid, then mask off 255 * the setuid and setgid bits. 256 */ 257 if ((ava.va_mask & AT_MODE) && vp->v_type == VREG && 258 (exi->exi_export.ex_flags & EX_NOSUID)) 259 ava.va_mode &= ~(VSUID | VSGID); 260 261 ct.cc_sysid = 0; 262 ct.cc_pid = 0; 263 ct.cc_caller_id = nfs3_srv_caller_id; 264 ct.cc_flags = CC_DONTBLOCK; 265 266 /* 267 * We need to specially handle size changes because it is 268 * possible for the client to create a file with modes 269 * which indicate read-only, but with the file opened for 270 * writing. If the client then tries to set the size of 271 * the file, then the normal access checking done in 272 * VOP_SETATTR would prevent the client from doing so, 273 * although it should be legal for it to do so. To get 274 * around this, we do the access checking for ourselves 275 * and then use VOP_SPACE which doesn't do the access 276 * checking which VOP_SETATTR does. VOP_SPACE can only 277 * operate on VREG files, let VOP_SETATTR handle the other 278 * extremely rare cases. 279 * Also the client should not be allowed to change the 280 * size of the file if there is a conflicting non-blocking 281 * mandatory lock in the region the change. 282 */ 283 if (vp->v_type == VREG && (ava.va_mask & AT_SIZE)) { 284 if (in_crit) { 285 u_offset_t offset; 286 ssize_t length; 287 288 if (ava.va_size < bva.va_size) { 289 offset = ava.va_size; 290 length = bva.va_size - ava.va_size; 291 } else { 292 offset = bva.va_size; 293 length = ava.va_size - bva.va_size; 294 } 295 if (nbl_conflict(vp, NBL_WRITE, offset, length, 0, 296 NULL)) { 297 error = EACCES; 298 goto out; 299 } 300 } 301 302 if (crgetuid(cr) == bva.va_uid && ava.va_size != bva.va_size) { 303 ava.va_mask &= ~AT_SIZE; 304 bf.l_type = F_WRLCK; 305 bf.l_whence = 0; 306 bf.l_start = (off64_t)ava.va_size; 307 bf.l_len = 0; 308 bf.l_sysid = 0; 309 bf.l_pid = 0; 310 error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE, 311 (offset_t)ava.va_size, cr, &ct); 312 } 313 } 314 315 if (!error && ava.va_mask) 316 error = VOP_SETATTR(vp, &ava, flag, cr, &ct); 317 318 /* check if a monitor detected a delegation conflict */ 319 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 320 resp->status = NFS3ERR_JUKEBOX; 321 goto out1; 322 } 323 324 #ifdef DEBUG 325 if (rfs3_do_post_op_attr) { 326 ava.va_mask = AT_ALL; 327 avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava; 328 } else 329 avap = NULL; 330 #else 331 ava.va_mask = AT_ALL; 332 avap = rfs4_delegated_getattr(vp, &ava, 0, cr) ? NULL : &ava; 333 #endif 334 335 /* 336 * Force modified metadata out to stable storage. 337 */ 338 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct); 339 340 if (error) 341 goto out; 342 343 if (in_crit) 344 nbl_end_crit(vp); 345 346 resp->status = NFS3_OK; 347 vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc); 348 349 DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req, 350 cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp); 351 352 VN_RELE(vp); 353 354 return; 355 356 out: 357 if (curthread->t_flag & T_WOULDBLOCK) { 358 curthread->t_flag &= ~T_WOULDBLOCK; 359 resp->status = NFS3ERR_JUKEBOX; 360 } else 361 resp->status = puterrno3(error); 362 out1: 363 DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req, 364 cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp); 365 366 if (vp != NULL) { 367 if (in_crit) 368 nbl_end_crit(vp); 369 VN_RELE(vp); 370 } 371 vattr_to_wcc_data(bvap, avap, &resp->resfail.obj_wcc); 372 } 373 374 void * 375 rfs3_setattr_getfh(SETATTR3args *args) 376 { 377 378 return (&args->object); 379 } 380 381 /* ARGSUSED */ 382 void 383 rfs3_lookup(LOOKUP3args *args, LOOKUP3res *resp, struct exportinfo *exi, 384 struct svc_req *req, cred_t *cr) 385 { 386 int error; 387 vnode_t *vp; 388 vnode_t *dvp; 389 struct vattr *vap; 390 struct vattr va; 391 struct vattr *dvap; 392 struct vattr dva; 393 nfs_fh3 *fhp; 394 struct sec_ol sec = {0, 0}; 395 bool_t publicfh_flag = FALSE, auth_weak = FALSE; 396 struct sockaddr *ca; 397 char *name = NULL; 398 399 dvap = NULL; 400 401 /* 402 * Allow lookups from the root - the default 403 * location of the public filehandle. 404 */ 405 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) { 406 dvp = rootdir; 407 VN_HOLD(dvp); 408 409 DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req, 410 cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args); 411 } else { 412 dvp = nfs3_fhtovp(&args->what.dir, exi); 413 414 DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req, 415 cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args); 416 417 if (dvp == NULL) { 418 error = ESTALE; 419 goto out; 420 } 421 } 422 423 #ifdef DEBUG 424 if (rfs3_do_pre_op_attr) { 425 dva.va_mask = AT_ALL; 426 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva; 427 } 428 #else 429 dva.va_mask = AT_ALL; 430 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva; 431 #endif 432 433 if (args->what.name == nfs3nametoolong) { 434 resp->status = NFS3ERR_NAMETOOLONG; 435 goto out1; 436 } 437 438 if (args->what.name == NULL || *(args->what.name) == '\0') { 439 resp->status = NFS3ERR_ACCES; 440 goto out1; 441 } 442 443 fhp = &args->what.dir; 444 if (strcmp(args->what.name, "..") == 0 && 445 EQFID(&exi->exi_fid, FH3TOFIDP(fhp))) { 446 resp->status = NFS3ERR_NOENT; 447 goto out1; 448 } 449 450 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 451 name = nfscmd_convname(ca, exi, args->what.name, 452 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 453 454 if (name == NULL) { 455 resp->status = NFS3ERR_ACCES; 456 goto out1; 457 } 458 459 /* 460 * If the public filehandle is used then allow 461 * a multi-component lookup 462 */ 463 if (PUBLIC_FH3(&args->what.dir)) { 464 publicfh_flag = TRUE; 465 error = rfs_publicfh_mclookup(name, dvp, cr, &vp, 466 &exi, &sec); 467 if (error && exi != NULL) 468 exi_rele(exi); /* See comment below Re: publicfh_flag */ 469 /* 470 * Since WebNFS may bypass MOUNT, we need to ensure this 471 * request didn't come from an unlabeled admin_low client. 472 */ 473 if (is_system_labeled() && error == 0) { 474 int addr_type; 475 void *ipaddr; 476 tsol_tpc_t *tp; 477 478 if (ca->sa_family == AF_INET) { 479 addr_type = IPV4_VERSION; 480 ipaddr = &((struct sockaddr_in *)ca)->sin_addr; 481 } else if (ca->sa_family == AF_INET6) { 482 addr_type = IPV6_VERSION; 483 ipaddr = &((struct sockaddr_in6 *) 484 ca)->sin6_addr; 485 } 486 tp = find_tpc(ipaddr, addr_type, B_FALSE); 487 if (tp == NULL || tp->tpc_tp.tp_doi != 488 l_admin_low->tsl_doi || tp->tpc_tp.host_type != 489 SUN_CIPSO) { 490 if (exi != NULL) 491 exi_rele(exi); 492 VN_RELE(vp); 493 resp->status = NFS3ERR_ACCES; 494 error = 1; 495 } 496 if (tp != NULL) 497 TPC_RELE(tp); 498 } 499 } else { 500 error = VOP_LOOKUP(dvp, name, &vp, 501 NULL, 0, NULL, cr, NULL, NULL, NULL); 502 } 503 504 if (name != args->what.name) 505 kmem_free(name, MAXPATHLEN + 1); 506 507 if (is_system_labeled() && error == 0) { 508 bslabel_t *clabel = req->rq_label; 509 510 ASSERT(clabel != NULL); 511 DTRACE_PROBE2(tx__rfs3__log__info__oplookup__clabel, char *, 512 "got client label from request(1)", struct svc_req *, req); 513 514 if (!blequal(&l_admin_low->tsl_label, clabel)) { 515 if (!do_rfs_label_check(clabel, dvp, 516 DOMINANCE_CHECK, exi)) { 517 if (publicfh_flag && exi != NULL) 518 exi_rele(exi); 519 VN_RELE(vp); 520 resp->status = NFS3ERR_ACCES; 521 error = 1; 522 } 523 } 524 } 525 526 #ifdef DEBUG 527 if (rfs3_do_post_op_attr) { 528 dva.va_mask = AT_ALL; 529 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva; 530 } else 531 dvap = NULL; 532 #else 533 dva.va_mask = AT_ALL; 534 dvap = VOP_GETATTR(dvp, &dva, 0, cr, NULL) ? NULL : &dva; 535 #endif 536 537 if (error) 538 goto out; 539 540 if (sec.sec_flags & SEC_QUERY) { 541 error = makefh3_ol(&resp->resok.object, exi, sec.sec_index); 542 } else { 543 error = makefh3(&resp->resok.object, vp, exi); 544 if (!error && publicfh_flag && !chk_clnt_sec(exi, req)) 545 auth_weak = TRUE; 546 } 547 548 if (error) { 549 VN_RELE(vp); 550 goto out; 551 } 552 553 /* 554 * If publicfh_flag is true then we have called rfs_publicfh_mclookup 555 * and have obtained a new exportinfo in exi which needs to be 556 * released. Note the the original exportinfo pointed to by exi 557 * will be released by the caller, common_dispatch. 558 */ 559 if (publicfh_flag) 560 exi_rele(exi); 561 562 #ifdef DEBUG 563 if (rfs3_do_post_op_attr) { 564 va.va_mask = AT_ALL; 565 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; 566 } else 567 vap = NULL; 568 #else 569 va.va_mask = AT_ALL; 570 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; 571 #endif 572 573 VN_RELE(vp); 574 575 resp->status = NFS3_OK; 576 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 577 vattr_to_post_op_attr(dvap, &resp->resok.dir_attributes); 578 579 /* 580 * If it's public fh, no 0x81, and client's flavor is 581 * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now. 582 * Then set RPC status to AUTH_TOOWEAK in common_dispatch. 583 */ 584 if (auth_weak) 585 resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR; 586 587 DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req, 588 cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp); 589 VN_RELE(dvp); 590 591 return; 592 593 out: 594 if (curthread->t_flag & T_WOULDBLOCK) { 595 curthread->t_flag &= ~T_WOULDBLOCK; 596 resp->status = NFS3ERR_JUKEBOX; 597 } else 598 resp->status = puterrno3(error); 599 out1: 600 DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req, 601 cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp); 602 603 if (dvp != NULL) 604 VN_RELE(dvp); 605 vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes); 606 607 } 608 609 void * 610 rfs3_lookup_getfh(LOOKUP3args *args) 611 { 612 613 return (&args->what.dir); 614 } 615 616 /* ARGSUSED */ 617 void 618 rfs3_access(ACCESS3args *args, ACCESS3res *resp, struct exportinfo *exi, 619 struct svc_req *req, cred_t *cr) 620 { 621 int error; 622 vnode_t *vp; 623 struct vattr *vap; 624 struct vattr va; 625 int checkwriteperm; 626 boolean_t dominant_label = B_FALSE; 627 boolean_t equal_label = B_FALSE; 628 boolean_t admin_low_client; 629 630 vap = NULL; 631 632 vp = nfs3_fhtovp(&args->object, exi); 633 634 DTRACE_NFSV3_4(op__access__start, struct svc_req *, req, 635 cred_t *, cr, vnode_t *, vp, ACCESS3args *, args); 636 637 if (vp == NULL) { 638 error = ESTALE; 639 goto out; 640 } 641 642 /* 643 * If the file system is exported read only, it is not appropriate 644 * to check write permissions for regular files and directories. 645 * Special files are interpreted by the client, so the underlying 646 * permissions are sent back to the client for interpretation. 647 */ 648 if (rdonly(exi, req) && (vp->v_type == VREG || vp->v_type == VDIR)) 649 checkwriteperm = 0; 650 else 651 checkwriteperm = 1; 652 653 /* 654 * We need the mode so that we can correctly determine access 655 * permissions relative to a mandatory lock file. Access to 656 * mandatory lock files is denied on the server, so it might 657 * as well be reflected to the server during the open. 658 */ 659 va.va_mask = AT_MODE; 660 error = VOP_GETATTR(vp, &va, 0, cr, NULL); 661 if (error) 662 goto out; 663 664 #ifdef DEBUG 665 if (rfs3_do_post_op_attr) 666 vap = &va; 667 #else 668 vap = &va; 669 #endif 670 671 resp->resok.access = 0; 672 673 if (is_system_labeled()) { 674 bslabel_t *clabel = req->rq_label; 675 676 ASSERT(clabel != NULL); 677 DTRACE_PROBE2(tx__rfs3__log__info__opaccess__clabel, char *, 678 "got client label from request(1)", struct svc_req *, req); 679 680 if (!blequal(&l_admin_low->tsl_label, clabel)) { 681 if ((equal_label = do_rfs_label_check(clabel, vp, 682 EQUALITY_CHECK, exi)) == B_FALSE) { 683 dominant_label = do_rfs_label_check(clabel, 684 vp, DOMINANCE_CHECK, exi); 685 } else 686 dominant_label = B_TRUE; 687 admin_low_client = B_FALSE; 688 } else 689 admin_low_client = B_TRUE; 690 } 691 692 if (args->access & ACCESS3_READ) { 693 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL); 694 if (error) { 695 if (curthread->t_flag & T_WOULDBLOCK) 696 goto out; 697 } else if (!MANDLOCK(vp, va.va_mode) && 698 (!is_system_labeled() || admin_low_client || 699 dominant_label)) 700 resp->resok.access |= ACCESS3_READ; 701 } 702 if ((args->access & ACCESS3_LOOKUP) && vp->v_type == VDIR) { 703 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL); 704 if (error) { 705 if (curthread->t_flag & T_WOULDBLOCK) 706 goto out; 707 } else if (!is_system_labeled() || admin_low_client || 708 dominant_label) 709 resp->resok.access |= ACCESS3_LOOKUP; 710 } 711 if (checkwriteperm && 712 (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND))) { 713 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL); 714 if (error) { 715 if (curthread->t_flag & T_WOULDBLOCK) 716 goto out; 717 } else if (!MANDLOCK(vp, va.va_mode) && 718 (!is_system_labeled() || admin_low_client || equal_label)) { 719 resp->resok.access |= 720 (args->access & (ACCESS3_MODIFY|ACCESS3_EXTEND)); 721 } 722 } 723 if (checkwriteperm && 724 (args->access & ACCESS3_DELETE) && vp->v_type == VDIR) { 725 error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL); 726 if (error) { 727 if (curthread->t_flag & T_WOULDBLOCK) 728 goto out; 729 } else if (!is_system_labeled() || admin_low_client || 730 equal_label) 731 resp->resok.access |= ACCESS3_DELETE; 732 } 733 if (args->access & ACCESS3_EXECUTE) { 734 error = VOP_ACCESS(vp, VEXEC, 0, cr, NULL); 735 if (error) { 736 if (curthread->t_flag & T_WOULDBLOCK) 737 goto out; 738 } else if (!MANDLOCK(vp, va.va_mode) && 739 (!is_system_labeled() || admin_low_client || 740 dominant_label)) 741 resp->resok.access |= ACCESS3_EXECUTE; 742 } 743 744 #ifdef DEBUG 745 if (rfs3_do_post_op_attr) { 746 va.va_mask = AT_ALL; 747 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; 748 } else 749 vap = NULL; 750 #else 751 va.va_mask = AT_ALL; 752 vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; 753 #endif 754 755 resp->status = NFS3_OK; 756 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 757 758 DTRACE_NFSV3_4(op__access__done, struct svc_req *, req, 759 cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp); 760 761 VN_RELE(vp); 762 763 return; 764 765 out: 766 if (curthread->t_flag & T_WOULDBLOCK) { 767 curthread->t_flag &= ~T_WOULDBLOCK; 768 resp->status = NFS3ERR_JUKEBOX; 769 } else 770 resp->status = puterrno3(error); 771 DTRACE_NFSV3_4(op__access__done, struct svc_req *, req, 772 cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp); 773 if (vp != NULL) 774 VN_RELE(vp); 775 vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes); 776 } 777 778 void * 779 rfs3_access_getfh(ACCESS3args *args) 780 { 781 782 return (&args->object); 783 } 784 785 /* ARGSUSED */ 786 void 787 rfs3_readlink(READLINK3args *args, READLINK3res *resp, struct exportinfo *exi, 788 struct svc_req *req, cred_t *cr) 789 { 790 int error; 791 vnode_t *vp; 792 struct vattr *vap; 793 struct vattr va; 794 struct iovec iov; 795 struct uio uio; 796 char *data; 797 struct sockaddr *ca; 798 char *name = NULL; 799 int is_referral = 0; 800 801 vap = NULL; 802 803 vp = nfs3_fhtovp(&args->symlink, exi); 804 805 DTRACE_NFSV3_4(op__readlink__start, struct svc_req *, req, 806 cred_t *, cr, vnode_t *, vp, READLINK3args *, args); 807 808 if (vp == NULL) { 809 error = ESTALE; 810 goto out; 811 } 812 813 va.va_mask = AT_ALL; 814 error = VOP_GETATTR(vp, &va, 0, cr, NULL); 815 if (error) 816 goto out; 817 818 #ifdef DEBUG 819 if (rfs3_do_post_op_attr) 820 vap = &va; 821 #else 822 vap = &va; 823 #endif 824 825 /* We lied about the object type for a referral */ 826 if (vn_is_nfs_reparse(vp, cr)) 827 is_referral = 1; 828 829 if (vp->v_type != VLNK && !is_referral) { 830 resp->status = NFS3ERR_INVAL; 831 goto out1; 832 } 833 834 if (MANDLOCK(vp, va.va_mode)) { 835 resp->status = NFS3ERR_ACCES; 836 goto out1; 837 } 838 839 if (is_system_labeled()) { 840 bslabel_t *clabel = req->rq_label; 841 842 ASSERT(clabel != NULL); 843 DTRACE_PROBE2(tx__rfs3__log__info__opreadlink__clabel, char *, 844 "got client label from request(1)", struct svc_req *, req); 845 846 if (!blequal(&l_admin_low->tsl_label, clabel)) { 847 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, 848 exi)) { 849 resp->status = NFS3ERR_ACCES; 850 goto out1; 851 } 852 } 853 } 854 855 data = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP); 856 857 if (is_referral) { 858 char *s; 859 size_t strsz; 860 861 /* Get an artificial symlink based on a referral */ 862 s = build_symlink(vp, cr, &strsz); 863 global_svstat_ptr[3][NFS_REFERLINKS].value.ui64++; 864 DTRACE_PROBE2(nfs3serv__func__referral__reflink, 865 vnode_t *, vp, char *, s); 866 if (s == NULL) 867 error = EINVAL; 868 else { 869 error = 0; 870 (void) strlcpy(data, s, MAXPATHLEN + 1); 871 kmem_free(s, strsz); 872 } 873 874 } else { 875 876 iov.iov_base = data; 877 iov.iov_len = MAXPATHLEN; 878 uio.uio_iov = &iov; 879 uio.uio_iovcnt = 1; 880 uio.uio_segflg = UIO_SYSSPACE; 881 uio.uio_extflg = UIO_COPY_CACHED; 882 uio.uio_loffset = 0; 883 uio.uio_resid = MAXPATHLEN; 884 885 error = VOP_READLINK(vp, &uio, cr, NULL); 886 887 if (!error) 888 *(data + MAXPATHLEN - uio.uio_resid) = '\0'; 889 } 890 891 #ifdef DEBUG 892 if (rfs3_do_post_op_attr) { 893 va.va_mask = AT_ALL; 894 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 895 } else 896 vap = NULL; 897 #else 898 va.va_mask = AT_ALL; 899 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 900 #endif 901 /* Lie about object type again just to be consistent */ 902 if (is_referral && vap != NULL) 903 vap->va_type = VLNK; 904 905 #if 0 /* notyet */ 906 /* 907 * Don't do this. It causes local disk writes when just 908 * reading the file and the overhead is deemed larger 909 * than the benefit. 910 */ 911 /* 912 * Force modified metadata out to stable storage. 913 */ 914 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL); 915 #endif 916 917 if (error) { 918 kmem_free(data, MAXPATHLEN + 1); 919 goto out; 920 } 921 922 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 923 name = nfscmd_convname(ca, exi, data, NFSCMD_CONV_OUTBOUND, 924 MAXPATHLEN + 1); 925 926 if (name == NULL) { 927 /* 928 * Even though the conversion failed, we return 929 * something. We just don't translate it. 930 */ 931 name = data; 932 } 933 934 resp->status = NFS3_OK; 935 vattr_to_post_op_attr(vap, &resp->resok.symlink_attributes); 936 resp->resok.data = name; 937 938 DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req, 939 cred_t *, cr, vnode_t *, vp, READLINK3res *, resp); 940 VN_RELE(vp); 941 942 if (name != data) 943 kmem_free(data, MAXPATHLEN + 1); 944 945 return; 946 947 out: 948 if (curthread->t_flag & T_WOULDBLOCK) { 949 curthread->t_flag &= ~T_WOULDBLOCK; 950 resp->status = NFS3ERR_JUKEBOX; 951 } else 952 resp->status = puterrno3(error); 953 out1: 954 DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req, 955 cred_t *, cr, vnode_t *, vp, READLINK3res *, resp); 956 if (vp != NULL) 957 VN_RELE(vp); 958 vattr_to_post_op_attr(vap, &resp->resfail.symlink_attributes); 959 } 960 961 void * 962 rfs3_readlink_getfh(READLINK3args *args) 963 { 964 965 return (&args->symlink); 966 } 967 968 void 969 rfs3_readlink_free(READLINK3res *resp) 970 { 971 972 if (resp->status == NFS3_OK) 973 kmem_free(resp->resok.data, MAXPATHLEN + 1); 974 } 975 976 /* 977 * Server routine to handle read 978 * May handle RDMA data as well as mblks 979 */ 980 /* ARGSUSED */ 981 void 982 rfs3_read(READ3args *args, READ3res *resp, struct exportinfo *exi, 983 struct svc_req *req, cred_t *cr) 984 { 985 int error; 986 vnode_t *vp; 987 struct vattr *vap; 988 struct vattr va; 989 struct iovec iov; 990 struct uio uio; 991 u_offset_t offset; 992 mblk_t *mp; 993 int alloc_err = 0; 994 int in_crit = 0; 995 int need_rwunlock = 0; 996 caller_context_t ct; 997 998 vap = NULL; 999 1000 vp = nfs3_fhtovp(&args->file, exi); 1001 1002 DTRACE_NFSV3_4(op__read__start, struct svc_req *, req, 1003 cred_t *, cr, vnode_t *, vp, READ3args *, args); 1004 1005 if (vp == NULL) { 1006 error = ESTALE; 1007 goto out; 1008 } 1009 1010 if (is_system_labeled()) { 1011 bslabel_t *clabel = req->rq_label; 1012 1013 ASSERT(clabel != NULL); 1014 DTRACE_PROBE2(tx__rfs3__log__info__opread__clabel, char *, 1015 "got client label from request(1)", struct svc_req *, req); 1016 1017 if (!blequal(&l_admin_low->tsl_label, clabel)) { 1018 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, 1019 exi)) { 1020 resp->status = NFS3ERR_ACCES; 1021 goto out1; 1022 } 1023 } 1024 } 1025 1026 ct.cc_sysid = 0; 1027 ct.cc_pid = 0; 1028 ct.cc_caller_id = nfs3_srv_caller_id; 1029 ct.cc_flags = CC_DONTBLOCK; 1030 1031 /* 1032 * Enter the critical region before calling VOP_RWLOCK 1033 * to avoid a deadlock with write requests. 1034 */ 1035 if (nbl_need_check(vp)) { 1036 nbl_start_crit(vp, RW_READER); 1037 in_crit = 1; 1038 if (nbl_conflict(vp, NBL_READ, args->offset, args->count, 0, 1039 NULL)) { 1040 error = EACCES; 1041 goto out; 1042 } 1043 } 1044 1045 error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct); 1046 1047 /* check if a monitor detected a delegation conflict */ 1048 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 1049 resp->status = NFS3ERR_JUKEBOX; 1050 goto out1; 1051 } 1052 1053 need_rwunlock = 1; 1054 1055 va.va_mask = AT_ALL; 1056 error = VOP_GETATTR(vp, &va, 0, cr, &ct); 1057 1058 /* 1059 * If we can't get the attributes, then we can't do the 1060 * right access checking. So, we'll fail the request. 1061 */ 1062 if (error) 1063 goto out; 1064 1065 #ifdef DEBUG 1066 if (rfs3_do_post_op_attr) 1067 vap = &va; 1068 #else 1069 vap = &va; 1070 #endif 1071 1072 if (vp->v_type != VREG) { 1073 resp->status = NFS3ERR_INVAL; 1074 goto out1; 1075 } 1076 1077 if (crgetuid(cr) != va.va_uid) { 1078 error = VOP_ACCESS(vp, VREAD, 0, cr, &ct); 1079 if (error) { 1080 if (curthread->t_flag & T_WOULDBLOCK) 1081 goto out; 1082 error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct); 1083 if (error) 1084 goto out; 1085 } 1086 } 1087 1088 if (MANDLOCK(vp, va.va_mode)) { 1089 resp->status = NFS3ERR_ACCES; 1090 goto out1; 1091 } 1092 1093 offset = args->offset; 1094 if (offset >= va.va_size) { 1095 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 1096 if (in_crit) 1097 nbl_end_crit(vp); 1098 resp->status = NFS3_OK; 1099 vattr_to_post_op_attr(vap, &resp->resok.file_attributes); 1100 resp->resok.count = 0; 1101 resp->resok.eof = TRUE; 1102 resp->resok.data.data_len = 0; 1103 resp->resok.data.data_val = NULL; 1104 resp->resok.data.mp = NULL; 1105 /* RDMA */ 1106 resp->resok.wlist = args->wlist; 1107 resp->resok.wlist_len = resp->resok.count; 1108 if (resp->resok.wlist) 1109 clist_zero_len(resp->resok.wlist); 1110 goto done; 1111 } 1112 1113 if (args->count == 0) { 1114 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 1115 if (in_crit) 1116 nbl_end_crit(vp); 1117 resp->status = NFS3_OK; 1118 vattr_to_post_op_attr(vap, &resp->resok.file_attributes); 1119 resp->resok.count = 0; 1120 resp->resok.eof = FALSE; 1121 resp->resok.data.data_len = 0; 1122 resp->resok.data.data_val = NULL; 1123 resp->resok.data.mp = NULL; 1124 /* RDMA */ 1125 resp->resok.wlist = args->wlist; 1126 resp->resok.wlist_len = resp->resok.count; 1127 if (resp->resok.wlist) 1128 clist_zero_len(resp->resok.wlist); 1129 goto done; 1130 } 1131 1132 /* 1133 * do not allocate memory more the max. allowed 1134 * transfer size 1135 */ 1136 if (args->count > rfs3_tsize(req)) 1137 args->count = rfs3_tsize(req); 1138 1139 /* 1140 * If returning data via RDMA Write, then grab the chunk list. 1141 * If we aren't returning READ data w/RDMA_WRITE, then grab 1142 * a mblk. 1143 */ 1144 if (args->wlist) { 1145 mp = NULL; 1146 (void) rdma_get_wchunk(req, &iov, args->wlist); 1147 } else { 1148 /* 1149 * mp will contain the data to be sent out in the read reply. 1150 * This will be freed after the reply has been sent out (by the 1151 * driver). 1152 * Let's roundup the data to a BYTES_PER_XDR_UNIT multiple, so 1153 * that the call to xdrmblk_putmblk() never fails. 1154 */ 1155 mp = allocb_wait(RNDUP(args->count), BPRI_MED, STR_NOSIG, 1156 &alloc_err); 1157 ASSERT(mp != NULL); 1158 ASSERT(alloc_err == 0); 1159 1160 iov.iov_base = (caddr_t)mp->b_datap->db_base; 1161 iov.iov_len = args->count; 1162 } 1163 1164 uio.uio_iov = &iov; 1165 uio.uio_iovcnt = 1; 1166 uio.uio_segflg = UIO_SYSSPACE; 1167 uio.uio_extflg = UIO_COPY_CACHED; 1168 uio.uio_loffset = args->offset; 1169 uio.uio_resid = args->count; 1170 1171 error = VOP_READ(vp, &uio, 0, cr, &ct); 1172 1173 if (error) { 1174 freeb(mp); 1175 /* check if a monitor detected a delegation conflict */ 1176 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 1177 resp->status = NFS3ERR_JUKEBOX; 1178 goto out1; 1179 } 1180 goto out; 1181 } 1182 1183 va.va_mask = AT_ALL; 1184 error = VOP_GETATTR(vp, &va, 0, cr, &ct); 1185 1186 #ifdef DEBUG 1187 if (rfs3_do_post_op_attr) { 1188 if (error) 1189 vap = NULL; 1190 else 1191 vap = &va; 1192 } else 1193 vap = NULL; 1194 #else 1195 if (error) 1196 vap = NULL; 1197 else 1198 vap = &va; 1199 #endif 1200 1201 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 1202 1203 if (in_crit) 1204 nbl_end_crit(vp); 1205 1206 resp->status = NFS3_OK; 1207 vattr_to_post_op_attr(vap, &resp->resok.file_attributes); 1208 resp->resok.count = args->count - uio.uio_resid; 1209 if (!error && offset + resp->resok.count == va.va_size) 1210 resp->resok.eof = TRUE; 1211 else 1212 resp->resok.eof = FALSE; 1213 resp->resok.data.data_len = resp->resok.count; 1214 resp->resok.data.mp = mp; 1215 resp->resok.size = (uint_t)args->count; 1216 1217 if (args->wlist) { 1218 resp->resok.data.data_val = (caddr_t)iov.iov_base; 1219 if (!rdma_setup_read_data3(args, &(resp->resok))) { 1220 resp->status = NFS3ERR_INVAL; 1221 } 1222 } else { 1223 resp->resok.data.data_val = (caddr_t)mp->b_datap->db_base; 1224 (resp->resok).wlist = NULL; 1225 } 1226 1227 done: 1228 DTRACE_NFSV3_4(op__read__done, struct svc_req *, req, 1229 cred_t *, cr, vnode_t *, vp, READ3res *, resp); 1230 1231 VN_RELE(vp); 1232 1233 return; 1234 1235 out: 1236 if (curthread->t_flag & T_WOULDBLOCK) { 1237 curthread->t_flag &= ~T_WOULDBLOCK; 1238 resp->status = NFS3ERR_JUKEBOX; 1239 } else 1240 resp->status = puterrno3(error); 1241 out1: 1242 DTRACE_NFSV3_4(op__read__done, struct svc_req *, req, 1243 cred_t *, cr, vnode_t *, vp, READ3res *, resp); 1244 1245 if (vp != NULL) { 1246 if (need_rwunlock) 1247 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 1248 if (in_crit) 1249 nbl_end_crit(vp); 1250 VN_RELE(vp); 1251 } 1252 vattr_to_post_op_attr(vap, &resp->resfail.file_attributes); 1253 } 1254 1255 void 1256 rfs3_read_free(READ3res *resp) 1257 { 1258 mblk_t *mp; 1259 1260 if (resp->status == NFS3_OK) { 1261 mp = resp->resok.data.mp; 1262 if (mp != NULL) 1263 freeb(mp); 1264 } 1265 } 1266 1267 void * 1268 rfs3_read_getfh(READ3args *args) 1269 { 1270 1271 return (&args->file); 1272 } 1273 1274 #define MAX_IOVECS 12 1275 1276 #ifdef DEBUG 1277 static int rfs3_write_hits = 0; 1278 static int rfs3_write_misses = 0; 1279 #endif 1280 1281 void 1282 rfs3_write(WRITE3args *args, WRITE3res *resp, struct exportinfo *exi, 1283 struct svc_req *req, cred_t *cr) 1284 { 1285 int error; 1286 vnode_t *vp; 1287 struct vattr *bvap = NULL; 1288 struct vattr bva; 1289 struct vattr *avap = NULL; 1290 struct vattr ava; 1291 u_offset_t rlimit; 1292 struct uio uio; 1293 struct iovec iov[MAX_IOVECS]; 1294 mblk_t *m; 1295 struct iovec *iovp; 1296 int iovcnt; 1297 int ioflag; 1298 cred_t *savecred; 1299 int in_crit = 0; 1300 int rwlock_ret = -1; 1301 caller_context_t ct; 1302 1303 vp = nfs3_fhtovp(&args->file, exi); 1304 1305 DTRACE_NFSV3_4(op__write__start, struct svc_req *, req, 1306 cred_t *, cr, vnode_t *, vp, WRITE3args *, args); 1307 1308 if (vp == NULL) { 1309 error = ESTALE; 1310 goto err; 1311 } 1312 1313 if (is_system_labeled()) { 1314 bslabel_t *clabel = req->rq_label; 1315 1316 ASSERT(clabel != NULL); 1317 DTRACE_PROBE2(tx__rfs3__log__info__opwrite__clabel, char *, 1318 "got client label from request(1)", struct svc_req *, req); 1319 1320 if (!blequal(&l_admin_low->tsl_label, clabel)) { 1321 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, 1322 exi)) { 1323 resp->status = NFS3ERR_ACCES; 1324 goto err1; 1325 } 1326 } 1327 } 1328 1329 ct.cc_sysid = 0; 1330 ct.cc_pid = 0; 1331 ct.cc_caller_id = nfs3_srv_caller_id; 1332 ct.cc_flags = CC_DONTBLOCK; 1333 1334 /* 1335 * We have to enter the critical region before calling VOP_RWLOCK 1336 * to avoid a deadlock with ufs. 1337 */ 1338 if (nbl_need_check(vp)) { 1339 nbl_start_crit(vp, RW_READER); 1340 in_crit = 1; 1341 if (nbl_conflict(vp, NBL_WRITE, args->offset, args->count, 0, 1342 NULL)) { 1343 error = EACCES; 1344 goto err; 1345 } 1346 } 1347 1348 rwlock_ret = VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &ct); 1349 1350 /* check if a monitor detected a delegation conflict */ 1351 if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 1352 resp->status = NFS3ERR_JUKEBOX; 1353 rwlock_ret = -1; 1354 goto err1; 1355 } 1356 1357 1358 bva.va_mask = AT_ALL; 1359 error = VOP_GETATTR(vp, &bva, 0, cr, &ct); 1360 1361 /* 1362 * If we can't get the attributes, then we can't do the 1363 * right access checking. So, we'll fail the request. 1364 */ 1365 if (error) 1366 goto err; 1367 1368 bvap = &bva; 1369 #ifdef DEBUG 1370 if (!rfs3_do_pre_op_attr) 1371 bvap = NULL; 1372 #endif 1373 avap = bvap; 1374 1375 if (args->count != args->data.data_len) { 1376 resp->status = NFS3ERR_INVAL; 1377 goto err1; 1378 } 1379 1380 if (rdonly(exi, req)) { 1381 resp->status = NFS3ERR_ROFS; 1382 goto err1; 1383 } 1384 1385 if (vp->v_type != VREG) { 1386 resp->status = NFS3ERR_INVAL; 1387 goto err1; 1388 } 1389 1390 if (crgetuid(cr) != bva.va_uid && 1391 (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct))) 1392 goto err; 1393 1394 if (MANDLOCK(vp, bva.va_mode)) { 1395 resp->status = NFS3ERR_ACCES; 1396 goto err1; 1397 } 1398 1399 if (args->count == 0) { 1400 resp->status = NFS3_OK; 1401 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc); 1402 resp->resok.count = 0; 1403 resp->resok.committed = args->stable; 1404 resp->resok.verf = write3verf; 1405 goto out; 1406 } 1407 1408 if (args->mblk != NULL) { 1409 iovcnt = 0; 1410 for (m = args->mblk; m != NULL; m = m->b_cont) 1411 iovcnt++; 1412 if (iovcnt <= MAX_IOVECS) { 1413 #ifdef DEBUG 1414 rfs3_write_hits++; 1415 #endif 1416 iovp = iov; 1417 } else { 1418 #ifdef DEBUG 1419 rfs3_write_misses++; 1420 #endif 1421 iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP); 1422 } 1423 mblk_to_iov(args->mblk, iovcnt, iovp); 1424 1425 } else if (args->rlist != NULL) { 1426 iovcnt = 1; 1427 iovp = iov; 1428 iovp->iov_base = (char *)((args->rlist)->u.c_daddr3); 1429 iovp->iov_len = args->count; 1430 } else { 1431 iovcnt = 1; 1432 iovp = iov; 1433 iovp->iov_base = args->data.data_val; 1434 iovp->iov_len = args->count; 1435 } 1436 1437 uio.uio_iov = iovp; 1438 uio.uio_iovcnt = iovcnt; 1439 1440 uio.uio_segflg = UIO_SYSSPACE; 1441 uio.uio_extflg = UIO_COPY_DEFAULT; 1442 uio.uio_loffset = args->offset; 1443 uio.uio_resid = args->count; 1444 uio.uio_llimit = curproc->p_fsz_ctl; 1445 rlimit = uio.uio_llimit - args->offset; 1446 if (rlimit < (u_offset_t)uio.uio_resid) 1447 uio.uio_resid = (int)rlimit; 1448 1449 if (args->stable == UNSTABLE) 1450 ioflag = 0; 1451 else if (args->stable == FILE_SYNC) 1452 ioflag = FSYNC; 1453 else if (args->stable == DATA_SYNC) 1454 ioflag = FDSYNC; 1455 else { 1456 if (iovp != iov) 1457 kmem_free(iovp, sizeof (*iovp) * iovcnt); 1458 resp->status = NFS3ERR_INVAL; 1459 goto err1; 1460 } 1461 1462 /* 1463 * We're changing creds because VM may fault and we need 1464 * the cred of the current thread to be used if quota 1465 * checking is enabled. 1466 */ 1467 savecred = curthread->t_cred; 1468 curthread->t_cred = cr; 1469 error = VOP_WRITE(vp, &uio, ioflag, cr, &ct); 1470 curthread->t_cred = savecred; 1471 1472 if (iovp != iov) 1473 kmem_free(iovp, sizeof (*iovp) * iovcnt); 1474 1475 /* check if a monitor detected a delegation conflict */ 1476 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 1477 resp->status = NFS3ERR_JUKEBOX; 1478 goto err1; 1479 } 1480 1481 ava.va_mask = AT_ALL; 1482 avap = VOP_GETATTR(vp, &ava, 0, cr, &ct) ? NULL : &ava; 1483 1484 #ifdef DEBUG 1485 if (!rfs3_do_post_op_attr) 1486 avap = NULL; 1487 #endif 1488 1489 if (error) 1490 goto err; 1491 1492 /* 1493 * If we were unable to get the V_WRITELOCK_TRUE, then we 1494 * may not have accurate after attrs, so check if 1495 * we have both attributes, they have a non-zero va_seq, and 1496 * va_seq has changed by exactly one, 1497 * if not, turn off the before attr. 1498 */ 1499 if (rwlock_ret != V_WRITELOCK_TRUE) { 1500 if (bvap == NULL || avap == NULL || 1501 bvap->va_seq == 0 || avap->va_seq == 0 || 1502 avap->va_seq != (bvap->va_seq + 1)) { 1503 bvap = NULL; 1504 } 1505 } 1506 1507 resp->status = NFS3_OK; 1508 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc); 1509 resp->resok.count = args->count - uio.uio_resid; 1510 resp->resok.committed = args->stable; 1511 resp->resok.verf = write3verf; 1512 goto out; 1513 1514 err: 1515 if (curthread->t_flag & T_WOULDBLOCK) { 1516 curthread->t_flag &= ~T_WOULDBLOCK; 1517 resp->status = NFS3ERR_JUKEBOX; 1518 } else 1519 resp->status = puterrno3(error); 1520 err1: 1521 vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc); 1522 out: 1523 DTRACE_NFSV3_4(op__write__done, struct svc_req *, req, 1524 cred_t *, cr, vnode_t *, vp, WRITE3res *, resp); 1525 1526 if (vp != NULL) { 1527 if (rwlock_ret != -1) 1528 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct); 1529 if (in_crit) 1530 nbl_end_crit(vp); 1531 VN_RELE(vp); 1532 } 1533 } 1534 1535 void * 1536 rfs3_write_getfh(WRITE3args *args) 1537 { 1538 1539 return (&args->file); 1540 } 1541 1542 void 1543 rfs3_create(CREATE3args *args, CREATE3res *resp, struct exportinfo *exi, 1544 struct svc_req *req, cred_t *cr) 1545 { 1546 int error; 1547 int in_crit = 0; 1548 vnode_t *vp; 1549 vnode_t *tvp = NULL; 1550 vnode_t *dvp; 1551 struct vattr *vap; 1552 struct vattr va; 1553 struct vattr *dbvap; 1554 struct vattr dbva; 1555 struct vattr *davap; 1556 struct vattr dava; 1557 enum vcexcl excl; 1558 nfstime3 *mtime; 1559 len_t reqsize; 1560 bool_t trunc; 1561 struct sockaddr *ca; 1562 char *name = NULL; 1563 1564 dbvap = NULL; 1565 davap = NULL; 1566 1567 dvp = nfs3_fhtovp(&args->where.dir, exi); 1568 1569 DTRACE_NFSV3_4(op__create__start, struct svc_req *, req, 1570 cred_t *, cr, vnode_t *, dvp, CREATE3args *, args); 1571 1572 if (dvp == NULL) { 1573 error = ESTALE; 1574 goto out; 1575 } 1576 1577 #ifdef DEBUG 1578 if (rfs3_do_pre_op_attr) { 1579 dbva.va_mask = AT_ALL; 1580 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva; 1581 } else 1582 dbvap = NULL; 1583 #else 1584 dbva.va_mask = AT_ALL; 1585 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva; 1586 #endif 1587 davap = dbvap; 1588 1589 if (args->where.name == nfs3nametoolong) { 1590 resp->status = NFS3ERR_NAMETOOLONG; 1591 goto out1; 1592 } 1593 1594 if (args->where.name == NULL || *(args->where.name) == '\0') { 1595 resp->status = NFS3ERR_ACCES; 1596 goto out1; 1597 } 1598 1599 if (rdonly(exi, req)) { 1600 resp->status = NFS3ERR_ROFS; 1601 goto out1; 1602 } 1603 1604 if (is_system_labeled()) { 1605 bslabel_t *clabel = req->rq_label; 1606 1607 ASSERT(clabel != NULL); 1608 DTRACE_PROBE2(tx__rfs3__log__info__opcreate__clabel, char *, 1609 "got client label from request(1)", struct svc_req *, req); 1610 1611 if (!blequal(&l_admin_low->tsl_label, clabel)) { 1612 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, 1613 exi)) { 1614 resp->status = NFS3ERR_ACCES; 1615 goto out1; 1616 } 1617 } 1618 } 1619 1620 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 1621 name = nfscmd_convname(ca, exi, args->where.name, 1622 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 1623 1624 if (name == NULL) { 1625 /* This is really a Solaris EILSEQ */ 1626 resp->status = NFS3ERR_INVAL; 1627 goto out1; 1628 } 1629 1630 if (args->how.mode == EXCLUSIVE) { 1631 va.va_mask = AT_TYPE | AT_MODE | AT_MTIME; 1632 va.va_type = VREG; 1633 va.va_mode = (mode_t)0; 1634 /* 1635 * Ensure no time overflows and that types match 1636 */ 1637 mtime = (nfstime3 *)&args->how.createhow3_u.verf; 1638 va.va_mtime.tv_sec = mtime->seconds % INT32_MAX; 1639 va.va_mtime.tv_nsec = mtime->nseconds; 1640 excl = EXCL; 1641 } else { 1642 error = sattr3_to_vattr(&args->how.createhow3_u.obj_attributes, 1643 &va); 1644 if (error) 1645 goto out; 1646 va.va_mask |= AT_TYPE; 1647 va.va_type = VREG; 1648 if (args->how.mode == GUARDED) 1649 excl = EXCL; 1650 else { 1651 excl = NONEXCL; 1652 1653 /* 1654 * During creation of file in non-exclusive mode 1655 * if size of file is being set then make sure 1656 * that if the file already exists that no conflicting 1657 * non-blocking mandatory locks exists in the region 1658 * being modified. If there are conflicting locks fail 1659 * the operation with EACCES. 1660 */ 1661 if (va.va_mask & AT_SIZE) { 1662 struct vattr tva; 1663 1664 /* 1665 * Does file already exist? 1666 */ 1667 error = VOP_LOOKUP(dvp, name, &tvp, 1668 NULL, 0, NULL, cr, NULL, NULL, NULL); 1669 1670 /* 1671 * Check to see if the file has been delegated 1672 * to a v4 client. If so, then begin recall of 1673 * the delegation and return JUKEBOX to allow 1674 * the client to retrasmit its request. 1675 */ 1676 1677 trunc = va.va_size == 0; 1678 if (!error && 1679 rfs4_check_delegated(FWRITE, tvp, trunc)) { 1680 resp->status = NFS3ERR_JUKEBOX; 1681 goto out1; 1682 } 1683 1684 /* 1685 * Check for NBMAND lock conflicts 1686 */ 1687 if (!error && nbl_need_check(tvp)) { 1688 u_offset_t offset; 1689 ssize_t len; 1690 1691 nbl_start_crit(tvp, RW_READER); 1692 in_crit = 1; 1693 1694 tva.va_mask = AT_SIZE; 1695 error = VOP_GETATTR(tvp, &tva, 0, cr, 1696 NULL); 1697 /* 1698 * Can't check for conflicts, so return 1699 * error. 1700 */ 1701 if (error) 1702 goto out; 1703 1704 offset = tva.va_size < va.va_size ? 1705 tva.va_size : va.va_size; 1706 len = tva.va_size < va.va_size ? 1707 va.va_size - tva.va_size : 1708 tva.va_size - va.va_size; 1709 if (nbl_conflict(tvp, NBL_WRITE, 1710 offset, len, 0, NULL)) { 1711 error = EACCES; 1712 goto out; 1713 } 1714 } else if (tvp) { 1715 VN_RELE(tvp); 1716 tvp = NULL; 1717 } 1718 } 1719 } 1720 if (va.va_mask & AT_SIZE) 1721 reqsize = va.va_size; 1722 } 1723 1724 /* 1725 * Must specify the mode. 1726 */ 1727 if (!(va.va_mask & AT_MODE)) { 1728 resp->status = NFS3ERR_INVAL; 1729 goto out1; 1730 } 1731 1732 /* 1733 * If the filesystem is exported with nosuid, then mask off 1734 * the setuid and setgid bits. 1735 */ 1736 if (va.va_type == VREG && (exi->exi_export.ex_flags & EX_NOSUID)) 1737 va.va_mode &= ~(VSUID | VSGID); 1738 1739 tryagain: 1740 /* 1741 * The file open mode used is VWRITE. If the client needs 1742 * some other semantic, then it should do the access checking 1743 * itself. It would have been nice to have the file open mode 1744 * passed as part of the arguments. 1745 */ 1746 error = VOP_CREATE(dvp, name, &va, excl, VWRITE, 1747 &vp, cr, 0, NULL, NULL); 1748 1749 #ifdef DEBUG 1750 if (rfs3_do_post_op_attr) { 1751 dava.va_mask = AT_ALL; 1752 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava; 1753 } else 1754 davap = NULL; 1755 #else 1756 dava.va_mask = AT_ALL; 1757 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava; 1758 #endif 1759 1760 if (error) { 1761 /* 1762 * If we got something other than file already exists 1763 * then just return this error. Otherwise, we got 1764 * EEXIST. If we were doing a GUARDED create, then 1765 * just return this error. Otherwise, we need to 1766 * make sure that this wasn't a duplicate of an 1767 * exclusive create request. 1768 * 1769 * The assumption is made that a non-exclusive create 1770 * request will never return EEXIST. 1771 */ 1772 if (error != EEXIST || args->how.mode == GUARDED) 1773 goto out; 1774 /* 1775 * Lookup the file so that we can get a vnode for it. 1776 */ 1777 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, 1778 NULL, cr, NULL, NULL, NULL); 1779 if (error) { 1780 /* 1781 * We couldn't find the file that we thought that 1782 * we just created. So, we'll just try creating 1783 * it again. 1784 */ 1785 if (error == ENOENT) 1786 goto tryagain; 1787 goto out; 1788 } 1789 1790 /* 1791 * If the file is delegated to a v4 client, go ahead 1792 * and initiate recall, this create is a hint that a 1793 * conflicting v3 open has occurred. 1794 */ 1795 1796 if (rfs4_check_delegated(FWRITE, vp, FALSE)) { 1797 VN_RELE(vp); 1798 resp->status = NFS3ERR_JUKEBOX; 1799 goto out1; 1800 } 1801 1802 va.va_mask = AT_ALL; 1803 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 1804 1805 mtime = (nfstime3 *)&args->how.createhow3_u.verf; 1806 /* % with INT32_MAX to prevent overflows */ 1807 if (args->how.mode == EXCLUSIVE && (vap == NULL || 1808 vap->va_mtime.tv_sec != 1809 (mtime->seconds % INT32_MAX) || 1810 vap->va_mtime.tv_nsec != mtime->nseconds)) { 1811 VN_RELE(vp); 1812 error = EEXIST; 1813 goto out; 1814 } 1815 } else { 1816 1817 if ((args->how.mode == UNCHECKED || 1818 args->how.mode == GUARDED) && 1819 args->how.createhow3_u.obj_attributes.size.set_it && 1820 va.va_size == 0) 1821 trunc = TRUE; 1822 else 1823 trunc = FALSE; 1824 1825 if (rfs4_check_delegated(FWRITE, vp, trunc)) { 1826 VN_RELE(vp); 1827 resp->status = NFS3ERR_JUKEBOX; 1828 goto out1; 1829 } 1830 1831 va.va_mask = AT_ALL; 1832 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 1833 1834 /* 1835 * We need to check to make sure that the file got 1836 * created to the indicated size. If not, we do a 1837 * setattr to try to change the size, but we don't 1838 * try too hard. This shouldn't a problem as most 1839 * clients will only specifiy a size of zero which 1840 * local file systems handle. However, even if 1841 * the client does specify a non-zero size, it can 1842 * still recover by checking the size of the file 1843 * after it has created it and then issue a setattr 1844 * request of its own to set the size of the file. 1845 */ 1846 if (vap != NULL && 1847 (args->how.mode == UNCHECKED || 1848 args->how.mode == GUARDED) && 1849 args->how.createhow3_u.obj_attributes.size.set_it && 1850 vap->va_size != reqsize) { 1851 va.va_mask = AT_SIZE; 1852 va.va_size = reqsize; 1853 (void) VOP_SETATTR(vp, &va, 0, cr, NULL); 1854 va.va_mask = AT_ALL; 1855 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 1856 } 1857 } 1858 1859 if (name != args->where.name) 1860 kmem_free(name, MAXPATHLEN + 1); 1861 1862 #ifdef DEBUG 1863 if (!rfs3_do_post_op_attr) 1864 vap = NULL; 1865 #endif 1866 1867 #ifdef DEBUG 1868 if (!rfs3_do_post_op_fh3) 1869 resp->resok.obj.handle_follows = FALSE; 1870 else { 1871 #endif 1872 error = makefh3(&resp->resok.obj.handle, vp, exi); 1873 if (error) 1874 resp->resok.obj.handle_follows = FALSE; 1875 else 1876 resp->resok.obj.handle_follows = TRUE; 1877 #ifdef DEBUG 1878 } 1879 #endif 1880 1881 /* 1882 * Force modified data and metadata out to stable storage. 1883 */ 1884 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL); 1885 (void) VOP_FSYNC(dvp, 0, cr, NULL); 1886 1887 VN_RELE(vp); 1888 if (tvp != NULL) { 1889 if (in_crit) 1890 nbl_end_crit(tvp); 1891 VN_RELE(tvp); 1892 } 1893 1894 resp->status = NFS3_OK; 1895 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 1896 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc); 1897 1898 DTRACE_NFSV3_4(op__create__done, struct svc_req *, req, 1899 cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp); 1900 1901 VN_RELE(dvp); 1902 return; 1903 1904 out: 1905 if (curthread->t_flag & T_WOULDBLOCK) { 1906 curthread->t_flag &= ~T_WOULDBLOCK; 1907 resp->status = NFS3ERR_JUKEBOX; 1908 } else 1909 resp->status = puterrno3(error); 1910 out1: 1911 DTRACE_NFSV3_4(op__create__done, struct svc_req *, req, 1912 cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp); 1913 1914 if (name != NULL && name != args->where.name) 1915 kmem_free(name, MAXPATHLEN + 1); 1916 1917 if (tvp != NULL) { 1918 if (in_crit) 1919 nbl_end_crit(tvp); 1920 VN_RELE(tvp); 1921 } 1922 if (dvp != NULL) 1923 VN_RELE(dvp); 1924 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc); 1925 } 1926 1927 void * 1928 rfs3_create_getfh(CREATE3args *args) 1929 { 1930 1931 return (&args->where.dir); 1932 } 1933 1934 void 1935 rfs3_mkdir(MKDIR3args *args, MKDIR3res *resp, struct exportinfo *exi, 1936 struct svc_req *req, cred_t *cr) 1937 { 1938 int error; 1939 vnode_t *vp = NULL; 1940 vnode_t *dvp; 1941 struct vattr *vap; 1942 struct vattr va; 1943 struct vattr *dbvap; 1944 struct vattr dbva; 1945 struct vattr *davap; 1946 struct vattr dava; 1947 struct sockaddr *ca; 1948 char *name = NULL; 1949 1950 dbvap = NULL; 1951 davap = NULL; 1952 1953 dvp = nfs3_fhtovp(&args->where.dir, exi); 1954 1955 DTRACE_NFSV3_4(op__mkdir__start, struct svc_req *, req, 1956 cred_t *, cr, vnode_t *, dvp, MKDIR3args *, args); 1957 1958 if (dvp == NULL) { 1959 error = ESTALE; 1960 goto out; 1961 } 1962 1963 #ifdef DEBUG 1964 if (rfs3_do_pre_op_attr) { 1965 dbva.va_mask = AT_ALL; 1966 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva; 1967 } else 1968 dbvap = NULL; 1969 #else 1970 dbva.va_mask = AT_ALL; 1971 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva; 1972 #endif 1973 davap = dbvap; 1974 1975 if (args->where.name == nfs3nametoolong) { 1976 resp->status = NFS3ERR_NAMETOOLONG; 1977 goto out1; 1978 } 1979 1980 if (args->where.name == NULL || *(args->where.name) == '\0') { 1981 resp->status = NFS3ERR_ACCES; 1982 goto out1; 1983 } 1984 1985 if (rdonly(exi, req)) { 1986 resp->status = NFS3ERR_ROFS; 1987 goto out1; 1988 } 1989 1990 if (is_system_labeled()) { 1991 bslabel_t *clabel = req->rq_label; 1992 1993 ASSERT(clabel != NULL); 1994 DTRACE_PROBE2(tx__rfs3__log__info__opmkdir__clabel, char *, 1995 "got client label from request(1)", struct svc_req *, req); 1996 1997 if (!blequal(&l_admin_low->tsl_label, clabel)) { 1998 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, 1999 exi)) { 2000 resp->status = NFS3ERR_ACCES; 2001 goto out1; 2002 } 2003 } 2004 } 2005 2006 error = sattr3_to_vattr(&args->attributes, &va); 2007 if (error) 2008 goto out; 2009 2010 if (!(va.va_mask & AT_MODE)) { 2011 resp->status = NFS3ERR_INVAL; 2012 goto out1; 2013 } 2014 2015 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2016 name = nfscmd_convname(ca, exi, args->where.name, 2017 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 2018 2019 if (name == NULL) { 2020 resp->status = NFS3ERR_INVAL; 2021 goto out1; 2022 } 2023 2024 va.va_mask |= AT_TYPE; 2025 va.va_type = VDIR; 2026 2027 error = VOP_MKDIR(dvp, name, &va, &vp, cr, NULL, 0, NULL); 2028 2029 if (name != args->where.name) 2030 kmem_free(name, MAXPATHLEN + 1); 2031 2032 #ifdef DEBUG 2033 if (rfs3_do_post_op_attr) { 2034 dava.va_mask = AT_ALL; 2035 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava; 2036 } else 2037 davap = NULL; 2038 #else 2039 dava.va_mask = AT_ALL; 2040 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava; 2041 #endif 2042 2043 /* 2044 * Force modified data and metadata out to stable storage. 2045 */ 2046 (void) VOP_FSYNC(dvp, 0, cr, NULL); 2047 2048 if (error) 2049 goto out; 2050 2051 #ifdef DEBUG 2052 if (!rfs3_do_post_op_fh3) 2053 resp->resok.obj.handle_follows = FALSE; 2054 else { 2055 #endif 2056 error = makefh3(&resp->resok.obj.handle, vp, exi); 2057 if (error) 2058 resp->resok.obj.handle_follows = FALSE; 2059 else 2060 resp->resok.obj.handle_follows = TRUE; 2061 #ifdef DEBUG 2062 } 2063 #endif 2064 2065 #ifdef DEBUG 2066 if (rfs3_do_post_op_attr) { 2067 va.va_mask = AT_ALL; 2068 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 2069 } else 2070 vap = NULL; 2071 #else 2072 va.va_mask = AT_ALL; 2073 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 2074 #endif 2075 2076 /* 2077 * Force modified data and metadata out to stable storage. 2078 */ 2079 (void) VOP_FSYNC(vp, 0, cr, NULL); 2080 2081 VN_RELE(vp); 2082 2083 resp->status = NFS3_OK; 2084 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 2085 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc); 2086 2087 DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req, 2088 cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp); 2089 VN_RELE(dvp); 2090 2091 return; 2092 2093 out: 2094 if (curthread->t_flag & T_WOULDBLOCK) { 2095 curthread->t_flag &= ~T_WOULDBLOCK; 2096 resp->status = NFS3ERR_JUKEBOX; 2097 } else 2098 resp->status = puterrno3(error); 2099 out1: 2100 DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req, 2101 cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp); 2102 if (dvp != NULL) 2103 VN_RELE(dvp); 2104 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc); 2105 } 2106 2107 void * 2108 rfs3_mkdir_getfh(MKDIR3args *args) 2109 { 2110 2111 return (&args->where.dir); 2112 } 2113 2114 void 2115 rfs3_symlink(SYMLINK3args *args, SYMLINK3res *resp, struct exportinfo *exi, 2116 struct svc_req *req, cred_t *cr) 2117 { 2118 int error; 2119 vnode_t *vp; 2120 vnode_t *dvp; 2121 struct vattr *vap; 2122 struct vattr va; 2123 struct vattr *dbvap; 2124 struct vattr dbva; 2125 struct vattr *davap; 2126 struct vattr dava; 2127 struct sockaddr *ca; 2128 char *name = NULL; 2129 char *symdata = NULL; 2130 2131 dbvap = NULL; 2132 davap = NULL; 2133 2134 dvp = nfs3_fhtovp(&args->where.dir, exi); 2135 2136 DTRACE_NFSV3_4(op__symlink__start, struct svc_req *, req, 2137 cred_t *, cr, vnode_t *, dvp, SYMLINK3args *, args); 2138 2139 if (dvp == NULL) { 2140 error = ESTALE; 2141 goto err; 2142 } 2143 2144 #ifdef DEBUG 2145 if (rfs3_do_pre_op_attr) { 2146 dbva.va_mask = AT_ALL; 2147 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva; 2148 } else 2149 dbvap = NULL; 2150 #else 2151 dbva.va_mask = AT_ALL; 2152 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva; 2153 #endif 2154 davap = dbvap; 2155 2156 if (args->where.name == nfs3nametoolong) { 2157 resp->status = NFS3ERR_NAMETOOLONG; 2158 goto err1; 2159 } 2160 2161 if (args->where.name == NULL || *(args->where.name) == '\0') { 2162 resp->status = NFS3ERR_ACCES; 2163 goto err1; 2164 } 2165 2166 if (rdonly(exi, req)) { 2167 resp->status = NFS3ERR_ROFS; 2168 goto err1; 2169 } 2170 2171 if (is_system_labeled()) { 2172 bslabel_t *clabel = req->rq_label; 2173 2174 ASSERT(clabel != NULL); 2175 DTRACE_PROBE2(tx__rfs3__log__info__opsymlink__clabel, char *, 2176 "got client label from request(1)", struct svc_req *, req); 2177 2178 if (!blequal(&l_admin_low->tsl_label, clabel)) { 2179 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, 2180 exi)) { 2181 resp->status = NFS3ERR_ACCES; 2182 goto err1; 2183 } 2184 } 2185 } 2186 2187 error = sattr3_to_vattr(&args->symlink.symlink_attributes, &va); 2188 if (error) 2189 goto err; 2190 2191 if (!(va.va_mask & AT_MODE)) { 2192 resp->status = NFS3ERR_INVAL; 2193 goto err1; 2194 } 2195 2196 if (args->symlink.symlink_data == nfs3nametoolong) { 2197 resp->status = NFS3ERR_NAMETOOLONG; 2198 goto err1; 2199 } 2200 2201 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2202 name = nfscmd_convname(ca, exi, args->where.name, 2203 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 2204 2205 if (name == NULL) { 2206 /* This is really a Solaris EILSEQ */ 2207 resp->status = NFS3ERR_INVAL; 2208 goto err1; 2209 } 2210 2211 symdata = nfscmd_convname(ca, exi, args->symlink.symlink_data, 2212 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 2213 if (symdata == NULL) { 2214 /* This is really a Solaris EILSEQ */ 2215 resp->status = NFS3ERR_INVAL; 2216 goto err1; 2217 } 2218 2219 2220 va.va_mask |= AT_TYPE; 2221 va.va_type = VLNK; 2222 2223 error = VOP_SYMLINK(dvp, name, &va, symdata, cr, NULL, 0); 2224 2225 #ifdef DEBUG 2226 if (rfs3_do_post_op_attr) { 2227 dava.va_mask = AT_ALL; 2228 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava; 2229 } else 2230 davap = NULL; 2231 #else 2232 dava.va_mask = AT_ALL; 2233 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava; 2234 #endif 2235 2236 if (error) 2237 goto err; 2238 2239 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr, 2240 NULL, NULL, NULL); 2241 2242 /* 2243 * Force modified data and metadata out to stable storage. 2244 */ 2245 (void) VOP_FSYNC(dvp, 0, cr, NULL); 2246 2247 2248 resp->status = NFS3_OK; 2249 if (error) { 2250 resp->resok.obj.handle_follows = FALSE; 2251 vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes); 2252 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc); 2253 goto out; 2254 } 2255 2256 #ifdef DEBUG 2257 if (!rfs3_do_post_op_fh3) 2258 resp->resok.obj.handle_follows = FALSE; 2259 else { 2260 #endif 2261 error = makefh3(&resp->resok.obj.handle, vp, exi); 2262 if (error) 2263 resp->resok.obj.handle_follows = FALSE; 2264 else 2265 resp->resok.obj.handle_follows = TRUE; 2266 #ifdef DEBUG 2267 } 2268 #endif 2269 2270 #ifdef DEBUG 2271 if (rfs3_do_post_op_attr) { 2272 va.va_mask = AT_ALL; 2273 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 2274 } else 2275 vap = NULL; 2276 #else 2277 va.va_mask = AT_ALL; 2278 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 2279 #endif 2280 2281 /* 2282 * Force modified data and metadata out to stable storage. 2283 */ 2284 (void) VOP_FSYNC(vp, 0, cr, NULL); 2285 2286 VN_RELE(vp); 2287 2288 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 2289 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc); 2290 goto out; 2291 2292 err: 2293 if (curthread->t_flag & T_WOULDBLOCK) { 2294 curthread->t_flag &= ~T_WOULDBLOCK; 2295 resp->status = NFS3ERR_JUKEBOX; 2296 } else 2297 resp->status = puterrno3(error); 2298 err1: 2299 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc); 2300 out: 2301 if (name != NULL && name != args->where.name) 2302 kmem_free(name, MAXPATHLEN + 1); 2303 if (symdata != NULL && symdata != args->symlink.symlink_data) 2304 kmem_free(symdata, MAXPATHLEN + 1); 2305 2306 DTRACE_NFSV3_4(op__symlink__done, struct svc_req *, req, 2307 cred_t *, cr, vnode_t *, dvp, SYMLINK3res *, resp); 2308 2309 if (dvp != NULL) 2310 VN_RELE(dvp); 2311 } 2312 2313 void * 2314 rfs3_symlink_getfh(SYMLINK3args *args) 2315 { 2316 2317 return (&args->where.dir); 2318 } 2319 2320 void 2321 rfs3_mknod(MKNOD3args *args, MKNOD3res *resp, struct exportinfo *exi, 2322 struct svc_req *req, cred_t *cr) 2323 { 2324 int error; 2325 vnode_t *vp; 2326 vnode_t *realvp; 2327 vnode_t *dvp; 2328 struct vattr *vap; 2329 struct vattr va; 2330 struct vattr *dbvap; 2331 struct vattr dbva; 2332 struct vattr *davap; 2333 struct vattr dava; 2334 int mode; 2335 enum vcexcl excl; 2336 struct sockaddr *ca; 2337 char *name = NULL; 2338 2339 dbvap = NULL; 2340 davap = NULL; 2341 2342 dvp = nfs3_fhtovp(&args->where.dir, exi); 2343 2344 DTRACE_NFSV3_4(op__mknod__start, struct svc_req *, req, 2345 cred_t *, cr, vnode_t *, dvp, MKNOD3args *, args); 2346 2347 if (dvp == NULL) { 2348 error = ESTALE; 2349 goto out; 2350 } 2351 2352 #ifdef DEBUG 2353 if (rfs3_do_pre_op_attr) { 2354 dbva.va_mask = AT_ALL; 2355 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva; 2356 } else 2357 dbvap = NULL; 2358 #else 2359 dbva.va_mask = AT_ALL; 2360 dbvap = VOP_GETATTR(dvp, &dbva, 0, cr, NULL) ? NULL : &dbva; 2361 #endif 2362 davap = dbvap; 2363 2364 if (args->where.name == nfs3nametoolong) { 2365 resp->status = NFS3ERR_NAMETOOLONG; 2366 goto out1; 2367 } 2368 2369 if (args->where.name == NULL || *(args->where.name) == '\0') { 2370 resp->status = NFS3ERR_ACCES; 2371 goto out1; 2372 } 2373 2374 if (rdonly(exi, req)) { 2375 resp->status = NFS3ERR_ROFS; 2376 goto out1; 2377 } 2378 2379 if (is_system_labeled()) { 2380 bslabel_t *clabel = req->rq_label; 2381 2382 ASSERT(clabel != NULL); 2383 DTRACE_PROBE2(tx__rfs3__log__info__opmknod__clabel, char *, 2384 "got client label from request(1)", struct svc_req *, req); 2385 2386 if (!blequal(&l_admin_low->tsl_label, clabel)) { 2387 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, 2388 exi)) { 2389 resp->status = NFS3ERR_ACCES; 2390 goto out1; 2391 } 2392 } 2393 } 2394 2395 switch (args->what.type) { 2396 case NF3CHR: 2397 case NF3BLK: 2398 error = sattr3_to_vattr( 2399 &args->what.mknoddata3_u.device.dev_attributes, &va); 2400 if (error) 2401 goto out; 2402 if (secpolicy_sys_devices(cr) != 0) { 2403 resp->status = NFS3ERR_PERM; 2404 goto out1; 2405 } 2406 if (args->what.type == NF3CHR) 2407 va.va_type = VCHR; 2408 else 2409 va.va_type = VBLK; 2410 va.va_rdev = makedevice( 2411 args->what.mknoddata3_u.device.spec.specdata1, 2412 args->what.mknoddata3_u.device.spec.specdata2); 2413 va.va_mask |= AT_TYPE | AT_RDEV; 2414 break; 2415 case NF3SOCK: 2416 error = sattr3_to_vattr( 2417 &args->what.mknoddata3_u.pipe_attributes, &va); 2418 if (error) 2419 goto out; 2420 va.va_type = VSOCK; 2421 va.va_mask |= AT_TYPE; 2422 break; 2423 case NF3FIFO: 2424 error = sattr3_to_vattr( 2425 &args->what.mknoddata3_u.pipe_attributes, &va); 2426 if (error) 2427 goto out; 2428 va.va_type = VFIFO; 2429 va.va_mask |= AT_TYPE; 2430 break; 2431 default: 2432 resp->status = NFS3ERR_BADTYPE; 2433 goto out1; 2434 } 2435 2436 /* 2437 * Must specify the mode. 2438 */ 2439 if (!(va.va_mask & AT_MODE)) { 2440 resp->status = NFS3ERR_INVAL; 2441 goto out1; 2442 } 2443 2444 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2445 name = nfscmd_convname(ca, exi, args->where.name, 2446 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 2447 2448 if (name == NULL) { 2449 resp->status = NFS3ERR_INVAL; 2450 goto out1; 2451 } 2452 2453 excl = EXCL; 2454 2455 mode = 0; 2456 2457 error = VOP_CREATE(dvp, name, &va, excl, mode, 2458 &vp, cr, 0, NULL, NULL); 2459 2460 if (name != args->where.name) 2461 kmem_free(name, MAXPATHLEN + 1); 2462 2463 #ifdef DEBUG 2464 if (rfs3_do_post_op_attr) { 2465 dava.va_mask = AT_ALL; 2466 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava; 2467 } else 2468 davap = NULL; 2469 #else 2470 dava.va_mask = AT_ALL; 2471 davap = VOP_GETATTR(dvp, &dava, 0, cr, NULL) ? NULL : &dava; 2472 #endif 2473 2474 /* 2475 * Force modified data and metadata out to stable storage. 2476 */ 2477 (void) VOP_FSYNC(dvp, 0, cr, NULL); 2478 2479 if (error) 2480 goto out; 2481 2482 resp->status = NFS3_OK; 2483 2484 #ifdef DEBUG 2485 if (!rfs3_do_post_op_fh3) 2486 resp->resok.obj.handle_follows = FALSE; 2487 else { 2488 #endif 2489 error = makefh3(&resp->resok.obj.handle, vp, exi); 2490 if (error) 2491 resp->resok.obj.handle_follows = FALSE; 2492 else 2493 resp->resok.obj.handle_follows = TRUE; 2494 #ifdef DEBUG 2495 } 2496 #endif 2497 2498 #ifdef DEBUG 2499 if (rfs3_do_post_op_attr) { 2500 va.va_mask = AT_ALL; 2501 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 2502 } else 2503 vap = NULL; 2504 #else 2505 va.va_mask = AT_ALL; 2506 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 2507 #endif 2508 2509 /* 2510 * Force modified metadata out to stable storage. 2511 * 2512 * if a underlying vp exists, pass it to VOP_FSYNC 2513 */ 2514 if (VOP_REALVP(vp, &realvp, NULL) == 0) 2515 (void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL); 2516 else 2517 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL); 2518 2519 VN_RELE(vp); 2520 2521 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 2522 vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc); 2523 DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req, 2524 cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp); 2525 VN_RELE(dvp); 2526 return; 2527 2528 out: 2529 if (curthread->t_flag & T_WOULDBLOCK) { 2530 curthread->t_flag &= ~T_WOULDBLOCK; 2531 resp->status = NFS3ERR_JUKEBOX; 2532 } else 2533 resp->status = puterrno3(error); 2534 out1: 2535 DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req, 2536 cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp); 2537 if (dvp != NULL) 2538 VN_RELE(dvp); 2539 vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc); 2540 } 2541 2542 void * 2543 rfs3_mknod_getfh(MKNOD3args *args) 2544 { 2545 2546 return (&args->where.dir); 2547 } 2548 2549 void 2550 rfs3_remove(REMOVE3args *args, REMOVE3res *resp, struct exportinfo *exi, 2551 struct svc_req *req, cred_t *cr) 2552 { 2553 int error = 0; 2554 vnode_t *vp; 2555 struct vattr *bvap; 2556 struct vattr bva; 2557 struct vattr *avap; 2558 struct vattr ava; 2559 vnode_t *targvp = NULL; 2560 struct sockaddr *ca; 2561 char *name = NULL; 2562 2563 bvap = NULL; 2564 avap = NULL; 2565 2566 vp = nfs3_fhtovp(&args->object.dir, exi); 2567 2568 DTRACE_NFSV3_4(op__remove__start, struct svc_req *, req, 2569 cred_t *, cr, vnode_t *, vp, REMOVE3args *, args); 2570 2571 if (vp == NULL) { 2572 error = ESTALE; 2573 goto err; 2574 } 2575 2576 #ifdef DEBUG 2577 if (rfs3_do_pre_op_attr) { 2578 bva.va_mask = AT_ALL; 2579 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva; 2580 } else 2581 bvap = NULL; 2582 #else 2583 bva.va_mask = AT_ALL; 2584 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva; 2585 #endif 2586 avap = bvap; 2587 2588 if (vp->v_type != VDIR) { 2589 resp->status = NFS3ERR_NOTDIR; 2590 goto err1; 2591 } 2592 2593 if (args->object.name == nfs3nametoolong) { 2594 resp->status = NFS3ERR_NAMETOOLONG; 2595 goto err1; 2596 } 2597 2598 if (args->object.name == NULL || *(args->object.name) == '\0') { 2599 resp->status = NFS3ERR_ACCES; 2600 goto err1; 2601 } 2602 2603 if (rdonly(exi, req)) { 2604 resp->status = NFS3ERR_ROFS; 2605 goto err1; 2606 } 2607 2608 if (is_system_labeled()) { 2609 bslabel_t *clabel = req->rq_label; 2610 2611 ASSERT(clabel != NULL); 2612 DTRACE_PROBE2(tx__rfs3__log__info__opremove__clabel, char *, 2613 "got client label from request(1)", struct svc_req *, req); 2614 2615 if (!blequal(&l_admin_low->tsl_label, clabel)) { 2616 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, 2617 exi)) { 2618 resp->status = NFS3ERR_ACCES; 2619 goto err1; 2620 } 2621 } 2622 } 2623 2624 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2625 name = nfscmd_convname(ca, exi, args->object.name, 2626 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 2627 2628 if (name == NULL) { 2629 resp->status = NFS3ERR_INVAL; 2630 goto err1; 2631 } 2632 2633 /* 2634 * Check for a conflict with a non-blocking mandatory share 2635 * reservation and V4 delegations 2636 */ 2637 error = VOP_LOOKUP(vp, name, &targvp, NULL, 0, 2638 NULL, cr, NULL, NULL, NULL); 2639 if (error != 0) 2640 goto err; 2641 2642 if (rfs4_check_delegated(FWRITE, targvp, TRUE)) { 2643 resp->status = NFS3ERR_JUKEBOX; 2644 goto err1; 2645 } 2646 2647 if (!nbl_need_check(targvp)) { 2648 error = VOP_REMOVE(vp, name, cr, NULL, 0); 2649 } else { 2650 nbl_start_crit(targvp, RW_READER); 2651 if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) { 2652 error = EACCES; 2653 } else { 2654 error = VOP_REMOVE(vp, name, cr, NULL, 0); 2655 } 2656 nbl_end_crit(targvp); 2657 } 2658 VN_RELE(targvp); 2659 targvp = NULL; 2660 2661 #ifdef DEBUG 2662 if (rfs3_do_post_op_attr) { 2663 ava.va_mask = AT_ALL; 2664 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava; 2665 } else 2666 avap = NULL; 2667 #else 2668 ava.va_mask = AT_ALL; 2669 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava; 2670 #endif 2671 2672 /* 2673 * Force modified data and metadata out to stable storage. 2674 */ 2675 (void) VOP_FSYNC(vp, 0, cr, NULL); 2676 2677 if (error) 2678 goto err; 2679 2680 resp->status = NFS3_OK; 2681 vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc); 2682 goto out; 2683 2684 err: 2685 if (curthread->t_flag & T_WOULDBLOCK) { 2686 curthread->t_flag &= ~T_WOULDBLOCK; 2687 resp->status = NFS3ERR_JUKEBOX; 2688 } else 2689 resp->status = puterrno3(error); 2690 err1: 2691 vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc); 2692 out: 2693 DTRACE_NFSV3_4(op__remove__done, struct svc_req *, req, 2694 cred_t *, cr, vnode_t *, vp, REMOVE3res *, resp); 2695 2696 if (name != NULL && name != args->object.name) 2697 kmem_free(name, MAXPATHLEN + 1); 2698 2699 if (vp != NULL) 2700 VN_RELE(vp); 2701 } 2702 2703 void * 2704 rfs3_remove_getfh(REMOVE3args *args) 2705 { 2706 2707 return (&args->object.dir); 2708 } 2709 2710 void 2711 rfs3_rmdir(RMDIR3args *args, RMDIR3res *resp, struct exportinfo *exi, 2712 struct svc_req *req, cred_t *cr) 2713 { 2714 int error; 2715 vnode_t *vp; 2716 struct vattr *bvap; 2717 struct vattr bva; 2718 struct vattr *avap; 2719 struct vattr ava; 2720 struct sockaddr *ca; 2721 char *name = NULL; 2722 2723 bvap = NULL; 2724 avap = NULL; 2725 2726 vp = nfs3_fhtovp(&args->object.dir, exi); 2727 2728 DTRACE_NFSV3_4(op__rmdir__start, struct svc_req *, req, 2729 cred_t *, cr, vnode_t *, vp, RMDIR3args *, args); 2730 2731 if (vp == NULL) { 2732 error = ESTALE; 2733 goto err; 2734 } 2735 2736 #ifdef DEBUG 2737 if (rfs3_do_pre_op_attr) { 2738 bva.va_mask = AT_ALL; 2739 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva; 2740 } else 2741 bvap = NULL; 2742 #else 2743 bva.va_mask = AT_ALL; 2744 bvap = VOP_GETATTR(vp, &bva, 0, cr, NULL) ? NULL : &bva; 2745 #endif 2746 avap = bvap; 2747 2748 if (vp->v_type != VDIR) { 2749 resp->status = NFS3ERR_NOTDIR; 2750 goto err1; 2751 } 2752 2753 if (args->object.name == nfs3nametoolong) { 2754 resp->status = NFS3ERR_NAMETOOLONG; 2755 goto err1; 2756 } 2757 2758 if (args->object.name == NULL || *(args->object.name) == '\0') { 2759 resp->status = NFS3ERR_ACCES; 2760 goto err1; 2761 } 2762 2763 if (rdonly(exi, req)) { 2764 resp->status = NFS3ERR_ROFS; 2765 goto err1; 2766 } 2767 2768 if (is_system_labeled()) { 2769 bslabel_t *clabel = req->rq_label; 2770 2771 ASSERT(clabel != NULL); 2772 DTRACE_PROBE2(tx__rfs3__log__info__opremovedir__clabel, char *, 2773 "got client label from request(1)", struct svc_req *, req); 2774 2775 if (!blequal(&l_admin_low->tsl_label, clabel)) { 2776 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, 2777 exi)) { 2778 resp->status = NFS3ERR_ACCES; 2779 goto err1; 2780 } 2781 } 2782 } 2783 2784 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2785 name = nfscmd_convname(ca, exi, args->object.name, 2786 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 2787 2788 if (name == NULL) { 2789 resp->status = NFS3ERR_INVAL; 2790 goto err1; 2791 } 2792 2793 error = VOP_RMDIR(vp, name, rootdir, cr, NULL, 0); 2794 2795 if (name != args->object.name) 2796 kmem_free(name, MAXPATHLEN + 1); 2797 2798 #ifdef DEBUG 2799 if (rfs3_do_post_op_attr) { 2800 ava.va_mask = AT_ALL; 2801 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava; 2802 } else 2803 avap = NULL; 2804 #else 2805 ava.va_mask = AT_ALL; 2806 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava; 2807 #endif 2808 2809 /* 2810 * Force modified data and metadata out to stable storage. 2811 */ 2812 (void) VOP_FSYNC(vp, 0, cr, NULL); 2813 2814 if (error) { 2815 /* 2816 * System V defines rmdir to return EEXIST, not ENOTEMPTY, 2817 * if the directory is not empty. A System V NFS server 2818 * needs to map NFS3ERR_EXIST to NFS3ERR_NOTEMPTY to transmit 2819 * over the wire. 2820 */ 2821 if (error == EEXIST) 2822 error = ENOTEMPTY; 2823 goto err; 2824 } 2825 2826 resp->status = NFS3_OK; 2827 vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc); 2828 goto out; 2829 2830 err: 2831 if (curthread->t_flag & T_WOULDBLOCK) { 2832 curthread->t_flag &= ~T_WOULDBLOCK; 2833 resp->status = NFS3ERR_JUKEBOX; 2834 } else 2835 resp->status = puterrno3(error); 2836 err1: 2837 vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc); 2838 out: 2839 DTRACE_NFSV3_4(op__rmdir__done, struct svc_req *, req, 2840 cred_t *, cr, vnode_t *, vp, RMDIR3res *, resp); 2841 if (vp != NULL) 2842 VN_RELE(vp); 2843 2844 } 2845 2846 void * 2847 rfs3_rmdir_getfh(RMDIR3args *args) 2848 { 2849 2850 return (&args->object.dir); 2851 } 2852 2853 void 2854 rfs3_rename(RENAME3args *args, RENAME3res *resp, struct exportinfo *exi, 2855 struct svc_req *req, cred_t *cr) 2856 { 2857 int error = 0; 2858 vnode_t *fvp; 2859 vnode_t *tvp; 2860 vnode_t *targvp; 2861 struct vattr *fbvap; 2862 struct vattr fbva; 2863 struct vattr *favap; 2864 struct vattr fava; 2865 struct vattr *tbvap; 2866 struct vattr tbva; 2867 struct vattr *tavap; 2868 struct vattr tava; 2869 nfs_fh3 *fh3; 2870 struct exportinfo *to_exi; 2871 vnode_t *srcvp = NULL; 2872 bslabel_t *clabel; 2873 struct sockaddr *ca; 2874 char *name = NULL; 2875 char *toname = NULL; 2876 2877 fbvap = NULL; 2878 favap = NULL; 2879 tbvap = NULL; 2880 tavap = NULL; 2881 tvp = NULL; 2882 2883 fvp = nfs3_fhtovp(&args->from.dir, exi); 2884 2885 DTRACE_NFSV3_4(op__rename__start, struct svc_req *, req, 2886 cred_t *, cr, vnode_t *, fvp, RENAME3args *, args); 2887 2888 if (fvp == NULL) { 2889 error = ESTALE; 2890 goto err; 2891 } 2892 2893 if (is_system_labeled()) { 2894 clabel = req->rq_label; 2895 ASSERT(clabel != NULL); 2896 DTRACE_PROBE2(tx__rfs3__log__info__oprename__clabel, char *, 2897 "got client label from request(1)", struct svc_req *, req); 2898 2899 if (!blequal(&l_admin_low->tsl_label, clabel)) { 2900 if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK, 2901 exi)) { 2902 resp->status = NFS3ERR_ACCES; 2903 goto err1; 2904 } 2905 } 2906 } 2907 2908 #ifdef DEBUG 2909 if (rfs3_do_pre_op_attr) { 2910 fbva.va_mask = AT_ALL; 2911 fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva; 2912 } else 2913 fbvap = NULL; 2914 #else 2915 fbva.va_mask = AT_ALL; 2916 fbvap = VOP_GETATTR(fvp, &fbva, 0, cr, NULL) ? NULL : &fbva; 2917 #endif 2918 favap = fbvap; 2919 2920 fh3 = &args->to.dir; 2921 to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3)); 2922 if (to_exi == NULL) { 2923 resp->status = NFS3ERR_ACCES; 2924 goto err1; 2925 } 2926 exi_rele(to_exi); 2927 2928 if (to_exi != exi) { 2929 resp->status = NFS3ERR_XDEV; 2930 goto err1; 2931 } 2932 2933 tvp = nfs3_fhtovp(&args->to.dir, exi); 2934 if (tvp == NULL) { 2935 error = ESTALE; 2936 goto err; 2937 } 2938 2939 #ifdef DEBUG 2940 if (rfs3_do_pre_op_attr) { 2941 tbva.va_mask = AT_ALL; 2942 tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva; 2943 } else 2944 tbvap = NULL; 2945 #else 2946 tbva.va_mask = AT_ALL; 2947 tbvap = VOP_GETATTR(tvp, &tbva, 0, cr, NULL) ? NULL : &tbva; 2948 #endif 2949 tavap = tbvap; 2950 2951 if (fvp->v_type != VDIR || tvp->v_type != VDIR) { 2952 resp->status = NFS3ERR_NOTDIR; 2953 goto err1; 2954 } 2955 2956 if (args->from.name == nfs3nametoolong || 2957 args->to.name == nfs3nametoolong) { 2958 resp->status = NFS3ERR_NAMETOOLONG; 2959 goto err1; 2960 } 2961 if (args->from.name == NULL || *(args->from.name) == '\0' || 2962 args->to.name == NULL || *(args->to.name) == '\0') { 2963 resp->status = NFS3ERR_ACCES; 2964 goto err1; 2965 } 2966 2967 if (rdonly(exi, req)) { 2968 resp->status = NFS3ERR_ROFS; 2969 goto err1; 2970 } 2971 2972 if (is_system_labeled()) { 2973 if (!blequal(&l_admin_low->tsl_label, clabel)) { 2974 if (!do_rfs_label_check(clabel, tvp, EQUALITY_CHECK, 2975 exi)) { 2976 resp->status = NFS3ERR_ACCES; 2977 goto err1; 2978 } 2979 } 2980 } 2981 2982 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2983 name = nfscmd_convname(ca, exi, args->from.name, 2984 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 2985 2986 if (name == NULL) { 2987 resp->status = NFS3ERR_INVAL; 2988 goto err1; 2989 } 2990 2991 toname = nfscmd_convname(ca, exi, args->to.name, 2992 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 2993 2994 if (toname == NULL) { 2995 resp->status = NFS3ERR_INVAL; 2996 goto err1; 2997 } 2998 2999 /* 3000 * Check for a conflict with a non-blocking mandatory share 3001 * reservation or V4 delegations. 3002 */ 3003 error = VOP_LOOKUP(fvp, name, &srcvp, NULL, 0, 3004 NULL, cr, NULL, NULL, NULL); 3005 if (error != 0) 3006 goto err; 3007 3008 /* 3009 * If we rename a delegated file we should recall the 3010 * delegation, since future opens should fail or would 3011 * refer to a new file. 3012 */ 3013 if (rfs4_check_delegated(FWRITE, srcvp, FALSE)) { 3014 resp->status = NFS3ERR_JUKEBOX; 3015 goto err1; 3016 } 3017 3018 /* 3019 * Check for renaming over a delegated file. Check rfs4_deleg_policy 3020 * first to avoid VOP_LOOKUP if possible. 3021 */ 3022 if (rfs4_deleg_policy != SRV_NEVER_DELEGATE && 3023 VOP_LOOKUP(tvp, toname, &targvp, NULL, 0, NULL, cr, 3024 NULL, NULL, NULL) == 0) { 3025 3026 if (rfs4_check_delegated(FWRITE, targvp, TRUE)) { 3027 VN_RELE(targvp); 3028 resp->status = NFS3ERR_JUKEBOX; 3029 goto err1; 3030 } 3031 VN_RELE(targvp); 3032 } 3033 3034 if (!nbl_need_check(srcvp)) { 3035 error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0); 3036 } else { 3037 nbl_start_crit(srcvp, RW_READER); 3038 if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL)) 3039 error = EACCES; 3040 else 3041 error = VOP_RENAME(fvp, name, tvp, toname, cr, NULL, 0); 3042 nbl_end_crit(srcvp); 3043 } 3044 if (error == 0) 3045 vn_renamepath(tvp, srcvp, args->to.name, 3046 strlen(args->to.name)); 3047 VN_RELE(srcvp); 3048 srcvp = NULL; 3049 3050 #ifdef DEBUG 3051 if (rfs3_do_post_op_attr) { 3052 fava.va_mask = AT_ALL; 3053 favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava; 3054 tava.va_mask = AT_ALL; 3055 tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava; 3056 } else { 3057 favap = NULL; 3058 tavap = NULL; 3059 } 3060 #else 3061 fava.va_mask = AT_ALL; 3062 favap = VOP_GETATTR(fvp, &fava, 0, cr, NULL) ? NULL : &fava; 3063 tava.va_mask = AT_ALL; 3064 tavap = VOP_GETATTR(tvp, &tava, 0, cr, NULL) ? NULL : &tava; 3065 #endif 3066 3067 /* 3068 * Force modified data and metadata out to stable storage. 3069 */ 3070 (void) VOP_FSYNC(fvp, 0, cr, NULL); 3071 (void) VOP_FSYNC(tvp, 0, cr, NULL); 3072 3073 if (error) 3074 goto err; 3075 3076 resp->status = NFS3_OK; 3077 vattr_to_wcc_data(fbvap, favap, &resp->resok.fromdir_wcc); 3078 vattr_to_wcc_data(tbvap, tavap, &resp->resok.todir_wcc); 3079 goto out; 3080 3081 err: 3082 if (curthread->t_flag & T_WOULDBLOCK) { 3083 curthread->t_flag &= ~T_WOULDBLOCK; 3084 resp->status = NFS3ERR_JUKEBOX; 3085 } else { 3086 resp->status = puterrno3(error); 3087 } 3088 err1: 3089 vattr_to_wcc_data(fbvap, favap, &resp->resfail.fromdir_wcc); 3090 vattr_to_wcc_data(tbvap, tavap, &resp->resfail.todir_wcc); 3091 3092 out: 3093 if (name != NULL && name != args->from.name) 3094 kmem_free(name, MAXPATHLEN + 1); 3095 if (toname != NULL && toname != args->to.name) 3096 kmem_free(toname, MAXPATHLEN + 1); 3097 3098 DTRACE_NFSV3_4(op__rename__done, struct svc_req *, req, 3099 cred_t *, cr, vnode_t *, fvp, RENAME3res *, resp); 3100 if (fvp != NULL) 3101 VN_RELE(fvp); 3102 if (tvp != NULL) 3103 VN_RELE(tvp); 3104 } 3105 3106 void * 3107 rfs3_rename_getfh(RENAME3args *args) 3108 { 3109 3110 return (&args->from.dir); 3111 } 3112 3113 void 3114 rfs3_link(LINK3args *args, LINK3res *resp, struct exportinfo *exi, 3115 struct svc_req *req, cred_t *cr) 3116 { 3117 int error; 3118 vnode_t *vp; 3119 vnode_t *dvp; 3120 struct vattr *vap; 3121 struct vattr va; 3122 struct vattr *bvap; 3123 struct vattr bva; 3124 struct vattr *avap; 3125 struct vattr ava; 3126 nfs_fh3 *fh3; 3127 struct exportinfo *to_exi; 3128 bslabel_t *clabel; 3129 struct sockaddr *ca; 3130 char *name = NULL; 3131 3132 vap = NULL; 3133 bvap = NULL; 3134 avap = NULL; 3135 dvp = NULL; 3136 3137 vp = nfs3_fhtovp(&args->file, exi); 3138 3139 DTRACE_NFSV3_4(op__link__start, struct svc_req *, req, 3140 cred_t *, cr, vnode_t *, vp, LINK3args *, args); 3141 3142 if (vp == NULL) { 3143 error = ESTALE; 3144 goto out; 3145 } 3146 3147 #ifdef DEBUG 3148 if (rfs3_do_pre_op_attr) { 3149 va.va_mask = AT_ALL; 3150 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3151 } else 3152 vap = NULL; 3153 #else 3154 va.va_mask = AT_ALL; 3155 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3156 #endif 3157 3158 fh3 = &args->link.dir; 3159 to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3)); 3160 if (to_exi == NULL) { 3161 resp->status = NFS3ERR_ACCES; 3162 goto out1; 3163 } 3164 exi_rele(to_exi); 3165 3166 if (to_exi != exi) { 3167 resp->status = NFS3ERR_XDEV; 3168 goto out1; 3169 } 3170 3171 if (is_system_labeled()) { 3172 clabel = req->rq_label; 3173 3174 ASSERT(clabel != NULL); 3175 DTRACE_PROBE2(tx__rfs3__log__info__oplink__clabel, char *, 3176 "got client label from request(1)", struct svc_req *, req); 3177 3178 if (!blequal(&l_admin_low->tsl_label, clabel)) { 3179 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, 3180 exi)) { 3181 resp->status = NFS3ERR_ACCES; 3182 goto out1; 3183 } 3184 } 3185 } 3186 3187 dvp = nfs3_fhtovp(&args->link.dir, exi); 3188 if (dvp == NULL) { 3189 error = ESTALE; 3190 goto out; 3191 } 3192 3193 #ifdef DEBUG 3194 if (rfs3_do_pre_op_attr) { 3195 bva.va_mask = AT_ALL; 3196 bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva; 3197 } else 3198 bvap = NULL; 3199 #else 3200 bva.va_mask = AT_ALL; 3201 bvap = VOP_GETATTR(dvp, &bva, 0, cr, NULL) ? NULL : &bva; 3202 #endif 3203 3204 if (dvp->v_type != VDIR) { 3205 resp->status = NFS3ERR_NOTDIR; 3206 goto out1; 3207 } 3208 3209 if (args->link.name == nfs3nametoolong) { 3210 resp->status = NFS3ERR_NAMETOOLONG; 3211 goto out1; 3212 } 3213 3214 if (args->link.name == NULL || *(args->link.name) == '\0') { 3215 resp->status = NFS3ERR_ACCES; 3216 goto out1; 3217 } 3218 3219 if (rdonly(exi, req)) { 3220 resp->status = NFS3ERR_ROFS; 3221 goto out1; 3222 } 3223 3224 if (is_system_labeled()) { 3225 DTRACE_PROBE2(tx__rfs3__log__info__oplinkdir__clabel, char *, 3226 "got client label from request(1)", struct svc_req *, req); 3227 3228 if (!blequal(&l_admin_low->tsl_label, clabel)) { 3229 if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, 3230 exi)) { 3231 resp->status = NFS3ERR_ACCES; 3232 goto out1; 3233 } 3234 } 3235 } 3236 3237 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 3238 name = nfscmd_convname(ca, exi, args->link.name, 3239 NFSCMD_CONV_INBOUND, MAXPATHLEN + 1); 3240 3241 if (name == NULL) { 3242 resp->status = NFS3ERR_SERVERFAULT; 3243 goto out1; 3244 } 3245 3246 error = VOP_LINK(dvp, vp, name, cr, NULL, 0); 3247 3248 #ifdef DEBUG 3249 if (rfs3_do_post_op_attr) { 3250 va.va_mask = AT_ALL; 3251 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3252 ava.va_mask = AT_ALL; 3253 avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava; 3254 } else { 3255 vap = NULL; 3256 avap = NULL; 3257 } 3258 #else 3259 va.va_mask = AT_ALL; 3260 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3261 ava.va_mask = AT_ALL; 3262 avap = VOP_GETATTR(dvp, &ava, 0, cr, NULL) ? NULL : &ava; 3263 #endif 3264 3265 /* 3266 * Force modified data and metadata out to stable storage. 3267 */ 3268 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL); 3269 (void) VOP_FSYNC(dvp, 0, cr, NULL); 3270 3271 if (error) 3272 goto out; 3273 3274 VN_RELE(dvp); 3275 3276 resp->status = NFS3_OK; 3277 vattr_to_post_op_attr(vap, &resp->resok.file_attributes); 3278 vattr_to_wcc_data(bvap, avap, &resp->resok.linkdir_wcc); 3279 3280 DTRACE_NFSV3_4(op__link__done, struct svc_req *, req, 3281 cred_t *, cr, vnode_t *, vp, LINK3res *, resp); 3282 3283 VN_RELE(vp); 3284 3285 return; 3286 3287 out: 3288 if (curthread->t_flag & T_WOULDBLOCK) { 3289 curthread->t_flag &= ~T_WOULDBLOCK; 3290 resp->status = NFS3ERR_JUKEBOX; 3291 } else 3292 resp->status = puterrno3(error); 3293 out1: 3294 if (name != NULL && name != args->link.name) 3295 kmem_free(name, MAXPATHLEN + 1); 3296 3297 DTRACE_NFSV3_4(op__link__done, struct svc_req *, req, 3298 cred_t *, cr, vnode_t *, vp, LINK3res *, resp); 3299 3300 if (vp != NULL) 3301 VN_RELE(vp); 3302 if (dvp != NULL) 3303 VN_RELE(dvp); 3304 vattr_to_post_op_attr(vap, &resp->resfail.file_attributes); 3305 vattr_to_wcc_data(bvap, avap, &resp->resfail.linkdir_wcc); 3306 } 3307 3308 void * 3309 rfs3_link_getfh(LINK3args *args) 3310 { 3311 3312 return (&args->file); 3313 } 3314 3315 /* 3316 * This macro defines the size of a response which contains attribute 3317 * information and one directory entry (whose length is specified by 3318 * the macro parameter). If the incoming request is larger than this, 3319 * then we are guaranteed to be able to return at one directory entry 3320 * if one exists. Therefore, we do not need to check for 3321 * NFS3ERR_TOOSMALL if the requested size is larger then this. If it 3322 * is not, then we need to check to make sure that this error does not 3323 * need to be returned. 3324 * 3325 * NFS3_READDIR_MIN_COUNT is comprised of following : 3326 * 3327 * status - 1 * BYTES_PER_XDR_UNIT 3328 * attr. flag - 1 * BYTES_PER_XDR_UNIT 3329 * cookie verifier - 2 * BYTES_PER_XDR_UNIT 3330 * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT 3331 * boolean - 1 * BYTES_PER_XDR_UNIT 3332 * file id - 2 * BYTES_PER_XDR_UNIT 3333 * directory name length - 1 * BYTES_PER_XDR_UNIT 3334 * cookie - 2 * BYTES_PER_XDR_UNIT 3335 * end of list - 1 * BYTES_PER_XDR_UNIT 3336 * end of file - 1 * BYTES_PER_XDR_UNIT 3337 * Name length of directory to the nearest byte 3338 */ 3339 3340 #define NFS3_READDIR_MIN_COUNT(length) \ 3341 ((1 + 1 + 2 + NFS3_SIZEOF_FATTR3 + 1 + 2 + 1 + 2 + 1 + 1) * \ 3342 BYTES_PER_XDR_UNIT + roundup((length), BYTES_PER_XDR_UNIT)) 3343 3344 /* ARGSUSED */ 3345 void 3346 rfs3_readdir(READDIR3args *args, READDIR3res *resp, struct exportinfo *exi, 3347 struct svc_req *req, cred_t *cr) 3348 { 3349 int error; 3350 vnode_t *vp; 3351 struct vattr *vap; 3352 struct vattr va; 3353 struct iovec iov; 3354 struct uio uio; 3355 char *data; 3356 int iseof; 3357 int bufsize; 3358 int namlen; 3359 uint_t count; 3360 struct sockaddr *ca; 3361 3362 vap = NULL; 3363 3364 vp = nfs3_fhtovp(&args->dir, exi); 3365 3366 DTRACE_NFSV3_4(op__readdir__start, struct svc_req *, req, 3367 cred_t *, cr, vnode_t *, vp, READDIR3args *, args); 3368 3369 if (vp == NULL) { 3370 error = ESTALE; 3371 goto out; 3372 } 3373 3374 if (is_system_labeled()) { 3375 bslabel_t *clabel = req->rq_label; 3376 3377 ASSERT(clabel != NULL); 3378 DTRACE_PROBE2(tx__rfs3__log__info__opreaddir__clabel, char *, 3379 "got client label from request(1)", struct svc_req *, req); 3380 3381 if (!blequal(&l_admin_low->tsl_label, clabel)) { 3382 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, 3383 exi)) { 3384 resp->status = NFS3ERR_ACCES; 3385 goto out1; 3386 } 3387 } 3388 } 3389 3390 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); 3391 3392 #ifdef DEBUG 3393 if (rfs3_do_pre_op_attr) { 3394 va.va_mask = AT_ALL; 3395 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3396 } else 3397 vap = NULL; 3398 #else 3399 va.va_mask = AT_ALL; 3400 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3401 #endif 3402 3403 if (vp->v_type != VDIR) { 3404 resp->status = NFS3ERR_NOTDIR; 3405 goto out1; 3406 } 3407 3408 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL); 3409 if (error) 3410 goto out; 3411 3412 /* 3413 * Now don't allow arbitrary count to alloc; 3414 * allow the maximum not to exceed rfs3_tsize() 3415 */ 3416 if (args->count > rfs3_tsize(req)) 3417 args->count = rfs3_tsize(req); 3418 3419 /* 3420 * Make sure that there is room to read at least one entry 3421 * if any are available. 3422 */ 3423 if (args->count < DIRENT64_RECLEN(MAXNAMELEN)) 3424 count = DIRENT64_RECLEN(MAXNAMELEN); 3425 else 3426 count = args->count; 3427 3428 data = kmem_alloc(count, KM_SLEEP); 3429 3430 iov.iov_base = data; 3431 iov.iov_len = count; 3432 uio.uio_iov = &iov; 3433 uio.uio_iovcnt = 1; 3434 uio.uio_segflg = UIO_SYSSPACE; 3435 uio.uio_extflg = UIO_COPY_CACHED; 3436 uio.uio_loffset = (offset_t)args->cookie; 3437 uio.uio_resid = count; 3438 3439 error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0); 3440 3441 #ifdef DEBUG 3442 if (rfs3_do_post_op_attr) { 3443 va.va_mask = AT_ALL; 3444 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3445 } else 3446 vap = NULL; 3447 #else 3448 va.va_mask = AT_ALL; 3449 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3450 #endif 3451 3452 if (error) { 3453 kmem_free(data, count); 3454 goto out; 3455 } 3456 3457 /* 3458 * If the count was not large enough to be able to guarantee 3459 * to be able to return at least one entry, then need to 3460 * check to see if NFS3ERR_TOOSMALL should be returned. 3461 */ 3462 if (args->count < NFS3_READDIR_MIN_COUNT(MAXNAMELEN)) { 3463 /* 3464 * bufsize is used to keep track of the size of the response. 3465 * It is primed with: 3466 * 1 for the status + 3467 * 1 for the dir_attributes.attributes boolean + 3468 * 2 for the cookie verifier 3469 * all times BYTES_PER_XDR_UNIT to convert from XDR units 3470 * to bytes. If there are directory attributes to be 3471 * returned, then: 3472 * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3 3473 * time BYTES_PER_XDR_UNIT is added to account for them. 3474 */ 3475 bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT; 3476 if (vap != NULL) 3477 bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT; 3478 /* 3479 * An entry is composed of: 3480 * 1 for the true/false list indicator + 3481 * 2 for the fileid + 3482 * 1 for the length of the name + 3483 * 2 for the cookie + 3484 * all times BYTES_PER_XDR_UNIT to convert from 3485 * XDR units to bytes, plus the length of the name 3486 * rounded up to the nearest BYTES_PER_XDR_UNIT. 3487 */ 3488 if (count != uio.uio_resid) { 3489 namlen = strlen(((struct dirent64 *)data)->d_name); 3490 bufsize += (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT + 3491 roundup(namlen, BYTES_PER_XDR_UNIT); 3492 } 3493 /* 3494 * We need to check to see if the number of bytes left 3495 * to go into the buffer will actually fit into the 3496 * buffer. This is calculated as the size of this 3497 * entry plus: 3498 * 1 for the true/false list indicator + 3499 * 1 for the eof indicator 3500 * times BYTES_PER_XDR_UNIT to convert from from 3501 * XDR units to bytes. 3502 */ 3503 bufsize += (1 + 1) * BYTES_PER_XDR_UNIT; 3504 if (bufsize > args->count) { 3505 kmem_free(data, count); 3506 resp->status = NFS3ERR_TOOSMALL; 3507 goto out1; 3508 } 3509 } 3510 3511 /* 3512 * Have a valid readir buffer for the native character 3513 * set. Need to check if a conversion is necessary and 3514 * potentially rewrite the whole buffer. Note that if the 3515 * conversion expands names enough, the structure may not 3516 * fit. In this case, we need to drop entries until if fits 3517 * and patch the counts in order that the next readdir will 3518 * get the correct entries. 3519 */ 3520 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 3521 data = nfscmd_convdirent(ca, exi, data, count, &resp->status); 3522 3523 3524 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 3525 3526 #if 0 /* notyet */ 3527 /* 3528 * Don't do this. It causes local disk writes when just 3529 * reading the file and the overhead is deemed larger 3530 * than the benefit. 3531 */ 3532 /* 3533 * Force modified metadata out to stable storage. 3534 */ 3535 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL); 3536 #endif 3537 3538 resp->status = NFS3_OK; 3539 vattr_to_post_op_attr(vap, &resp->resok.dir_attributes); 3540 resp->resok.cookieverf = 0; 3541 resp->resok.reply.entries = (entry3 *)data; 3542 resp->resok.reply.eof = iseof; 3543 resp->resok.size = count - uio.uio_resid; 3544 resp->resok.count = args->count; 3545 resp->resok.freecount = count; 3546 3547 DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req, 3548 cred_t *, cr, vnode_t *, vp, READDIR3res *, resp); 3549 3550 VN_RELE(vp); 3551 3552 return; 3553 3554 out: 3555 if (curthread->t_flag & T_WOULDBLOCK) { 3556 curthread->t_flag &= ~T_WOULDBLOCK; 3557 resp->status = NFS3ERR_JUKEBOX; 3558 } else 3559 resp->status = puterrno3(error); 3560 out1: 3561 DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req, 3562 cred_t *, cr, vnode_t *, vp, READDIR3res *, resp); 3563 3564 if (vp != NULL) { 3565 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 3566 VN_RELE(vp); 3567 } 3568 vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes); 3569 } 3570 3571 void * 3572 rfs3_readdir_getfh(READDIR3args *args) 3573 { 3574 3575 return (&args->dir); 3576 } 3577 3578 void 3579 rfs3_readdir_free(READDIR3res *resp) 3580 { 3581 3582 if (resp->status == NFS3_OK) 3583 kmem_free(resp->resok.reply.entries, resp->resok.freecount); 3584 } 3585 3586 #ifdef nextdp 3587 #undef nextdp 3588 #endif 3589 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 3590 3591 /* 3592 * This macro computes the size of a response which contains 3593 * one directory entry including the attributes as well as file handle. 3594 * If the incoming request is larger than this, then we are guaranteed to be 3595 * able to return at least one more directory entry if one exists. 3596 * 3597 * NFS3_READDIRPLUS_ENTRY is made up of the following: 3598 * 3599 * boolean - 1 * BYTES_PER_XDR_UNIT 3600 * file id - 2 * BYTES_PER_XDR_UNIT 3601 * directory name length - 1 * BYTES_PER_XDR_UNIT 3602 * cookie - 2 * BYTES_PER_XDR_UNIT 3603 * attribute flag - 1 * BYTES_PER_XDR_UNIT 3604 * attributes - NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT 3605 * status byte for file handle - 1 * BYTES_PER_XDR_UNIT 3606 * length of a file handle - 1 * BYTES_PER_XDR_UNIT 3607 * Maximum length of a file handle (NFS3_MAXFHSIZE) 3608 * name length of the entry to the nearest bytes 3609 */ 3610 #define NFS3_READDIRPLUS_ENTRY(namelen) \ 3611 ((1 + 2 + 1 + 2 + 1 + NFS3_SIZEOF_FATTR3 + 1 + 1) * \ 3612 BYTES_PER_XDR_UNIT + \ 3613 NFS3_MAXFHSIZE + roundup(namelen, BYTES_PER_XDR_UNIT)) 3614 3615 static int rfs3_readdir_unit = MAXBSIZE; 3616 3617 /* ARGSUSED */ 3618 void 3619 rfs3_readdirplus(READDIRPLUS3args *args, READDIRPLUS3res *resp, 3620 struct exportinfo *exi, struct svc_req *req, cred_t *cr) 3621 { 3622 int error; 3623 vnode_t *vp; 3624 struct vattr *vap; 3625 struct vattr va; 3626 struct iovec iov; 3627 struct uio uio; 3628 char *data; 3629 int iseof; 3630 struct dirent64 *dp; 3631 vnode_t *nvp; 3632 struct vattr *nvap; 3633 struct vattr nva; 3634 entryplus3_info *infop = NULL; 3635 int size = 0; 3636 int nents = 0; 3637 int bufsize = 0; 3638 int entrysize = 0; 3639 int tofit = 0; 3640 int rd_unit = rfs3_readdir_unit; 3641 int prev_len; 3642 int space_left; 3643 int i; 3644 uint_t *namlen = NULL; 3645 char *ndata = NULL; 3646 struct sockaddr *ca; 3647 size_t ret; 3648 3649 vap = NULL; 3650 3651 vp = nfs3_fhtovp(&args->dir, exi); 3652 3653 DTRACE_NFSV3_4(op__readdirplus__start, struct svc_req *, req, 3654 cred_t *, cr, vnode_t *, vp, READDIRPLUS3args *, args); 3655 3656 if (vp == NULL) { 3657 error = ESTALE; 3658 goto out; 3659 } 3660 3661 if (is_system_labeled()) { 3662 bslabel_t *clabel = req->rq_label; 3663 3664 ASSERT(clabel != NULL); 3665 DTRACE_PROBE2(tx__rfs3__log__info__opreaddirplus__clabel, 3666 char *, "got client label from request(1)", 3667 struct svc_req *, req); 3668 3669 if (!blequal(&l_admin_low->tsl_label, clabel)) { 3670 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, 3671 exi)) { 3672 resp->status = NFS3ERR_ACCES; 3673 goto out1; 3674 } 3675 } 3676 } 3677 3678 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); 3679 3680 #ifdef DEBUG 3681 if (rfs3_do_pre_op_attr) { 3682 va.va_mask = AT_ALL; 3683 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3684 } else 3685 vap = NULL; 3686 #else 3687 va.va_mask = AT_ALL; 3688 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3689 #endif 3690 3691 if (vp->v_type != VDIR) { 3692 error = ENOTDIR; 3693 goto out; 3694 } 3695 3696 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL); 3697 if (error) 3698 goto out; 3699 3700 /* 3701 * Don't allow arbitrary counts for allocation 3702 */ 3703 if (args->maxcount > rfs3_tsize(req)) 3704 args->maxcount = rfs3_tsize(req); 3705 3706 /* 3707 * Make sure that there is room to read at least one entry 3708 * if any are available 3709 */ 3710 args->dircount = MIN(args->dircount, args->maxcount); 3711 3712 if (args->dircount < DIRENT64_RECLEN(MAXNAMELEN)) 3713 args->dircount = DIRENT64_RECLEN(MAXNAMELEN); 3714 3715 /* 3716 * This allocation relies on a minimum directory entry 3717 * being roughly 24 bytes. Therefore, the namlen array 3718 * will have enough space based on the maximum number of 3719 * entries to read. 3720 */ 3721 namlen = kmem_alloc(args->dircount, KM_SLEEP); 3722 3723 space_left = args->dircount; 3724 data = kmem_alloc(args->dircount, KM_SLEEP); 3725 dp = (struct dirent64 *)data; 3726 uio.uio_iov = &iov; 3727 uio.uio_iovcnt = 1; 3728 uio.uio_segflg = UIO_SYSSPACE; 3729 uio.uio_extflg = UIO_COPY_CACHED; 3730 uio.uio_loffset = (offset_t)args->cookie; 3731 3732 /* 3733 * bufsize is used to keep track of the size of the response as we 3734 * get post op attributes and filehandles for each entry. This is 3735 * an optimization as the server may have read more entries than will 3736 * fit in the buffer specified by maxcount. We stop calculating 3737 * post op attributes and filehandles once we have exceeded maxcount. 3738 * This will minimize the effect of truncation. 3739 * 3740 * It is primed with: 3741 * 1 for the status + 3742 * 1 for the dir_attributes.attributes boolean + 3743 * 2 for the cookie verifier 3744 * all times BYTES_PER_XDR_UNIT to convert from XDR units 3745 * to bytes. If there are directory attributes to be 3746 * returned, then: 3747 * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3 3748 * time BYTES_PER_XDR_UNIT is added to account for them. 3749 */ 3750 bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT; 3751 if (vap != NULL) 3752 bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT; 3753 3754 getmoredents: 3755 /* 3756 * Here we make a check so that our read unit is not larger than 3757 * the space left in the buffer. 3758 */ 3759 rd_unit = MIN(rd_unit, space_left); 3760 iov.iov_base = (char *)dp; 3761 iov.iov_len = rd_unit; 3762 uio.uio_resid = rd_unit; 3763 prev_len = rd_unit; 3764 3765 error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0); 3766 3767 if (error) { 3768 kmem_free(data, args->dircount); 3769 goto out; 3770 } 3771 3772 if (uio.uio_resid == prev_len && !iseof) { 3773 if (nents == 0) { 3774 kmem_free(data, args->dircount); 3775 resp->status = NFS3ERR_TOOSMALL; 3776 goto out1; 3777 } 3778 3779 /* 3780 * We could not get any more entries, so get the attributes 3781 * and filehandle for the entries already obtained. 3782 */ 3783 goto good; 3784 } 3785 3786 /* 3787 * We estimate the size of the response by assuming the 3788 * entry exists and attributes and filehandle are also valid 3789 */ 3790 for (size = prev_len - uio.uio_resid; 3791 size > 0; 3792 size -= dp->d_reclen, dp = nextdp(dp)) { 3793 3794 if (dp->d_ino == 0) { 3795 nents++; 3796 continue; 3797 } 3798 3799 namlen[nents] = strlen(dp->d_name); 3800 entrysize = NFS3_READDIRPLUS_ENTRY(namlen[nents]); 3801 3802 /* 3803 * We need to check to see if the number of bytes left 3804 * to go into the buffer will actually fit into the 3805 * buffer. This is calculated as the size of this 3806 * entry plus: 3807 * 1 for the true/false list indicator + 3808 * 1 for the eof indicator 3809 * times BYTES_PER_XDR_UNIT to convert from XDR units 3810 * to bytes. 3811 * 3812 * Also check the dircount limit against the first entry read 3813 * 3814 */ 3815 tofit = entrysize + (1 + 1) * BYTES_PER_XDR_UNIT; 3816 if (bufsize + tofit > args->maxcount) { 3817 /* 3818 * We make a check here to see if this was the 3819 * first entry being measured. If so, then maxcount 3820 * was too small to begin with and so we need to 3821 * return with NFS3ERR_TOOSMALL. 3822 */ 3823 if (nents == 0) { 3824 kmem_free(data, args->dircount); 3825 resp->status = NFS3ERR_TOOSMALL; 3826 goto out1; 3827 } 3828 iseof = FALSE; 3829 goto good; 3830 } 3831 bufsize += entrysize; 3832 nents++; 3833 } 3834 3835 /* 3836 * If there is enough room to fit at least 1 more entry including 3837 * post op attributes and filehandle in the buffer AND that we haven't 3838 * exceeded dircount then go back and get some more. 3839 */ 3840 if (!iseof && 3841 (args->maxcount - bufsize) >= NFS3_READDIRPLUS_ENTRY(MAXNAMELEN)) { 3842 space_left -= (prev_len - uio.uio_resid); 3843 if (space_left >= DIRENT64_RECLEN(MAXNAMELEN)) 3844 goto getmoredents; 3845 3846 /* else, fall through */ 3847 } 3848 3849 good: 3850 3851 #ifdef DEBUG 3852 if (rfs3_do_post_op_attr) { 3853 va.va_mask = AT_ALL; 3854 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3855 } else 3856 vap = NULL; 3857 #else 3858 va.va_mask = AT_ALL; 3859 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 3860 #endif 3861 3862 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 3863 3864 infop = kmem_alloc(nents * sizeof (struct entryplus3_info), KM_SLEEP); 3865 resp->resok.infop = infop; 3866 3867 dp = (struct dirent64 *)data; 3868 for (i = 0; i < nents; i++) { 3869 3870 if (dp->d_ino == 0) { 3871 infop[i].attr.attributes = FALSE; 3872 infop[i].fh.handle_follows = FALSE; 3873 dp = nextdp(dp); 3874 continue; 3875 } 3876 3877 infop[i].namelen = namlen[i]; 3878 3879 error = VOP_LOOKUP(vp, dp->d_name, &nvp, NULL, 0, NULL, cr, 3880 NULL, NULL, NULL); 3881 if (error) { 3882 infop[i].attr.attributes = FALSE; 3883 infop[i].fh.handle_follows = FALSE; 3884 dp = nextdp(dp); 3885 continue; 3886 } 3887 3888 #ifdef DEBUG 3889 if (rfs3_do_post_op_attr) { 3890 nva.va_mask = AT_ALL; 3891 nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? 3892 NULL : &nva; 3893 } else 3894 nvap = NULL; 3895 #else 3896 nva.va_mask = AT_ALL; 3897 nvap = rfs4_delegated_getattr(nvp, &nva, 0, cr) ? NULL : &nva; 3898 #endif 3899 /* Lie about the object type for a referral */ 3900 if (vn_is_nfs_reparse(nvp, cr)) 3901 nvap->va_type = VLNK; 3902 3903 vattr_to_post_op_attr(nvap, &infop[i].attr); 3904 3905 #ifdef DEBUG 3906 if (!rfs3_do_post_op_fh3) 3907 infop[i].fh.handle_follows = FALSE; 3908 else { 3909 #endif 3910 error = makefh3(&infop[i].fh.handle, nvp, exi); 3911 if (!error) 3912 infop[i].fh.handle_follows = TRUE; 3913 else 3914 infop[i].fh.handle_follows = FALSE; 3915 #ifdef DEBUG 3916 } 3917 #endif 3918 3919 VN_RELE(nvp); 3920 dp = nextdp(dp); 3921 } 3922 3923 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 3924 ret = nfscmd_convdirplus(ca, exi, data, nents, args->dircount, &ndata); 3925 if (ndata == NULL) 3926 ndata = data; 3927 3928 if (ret > 0) { 3929 /* 3930 * We had to drop one or more entries in order to fit 3931 * during the character conversion. We need to patch 3932 * up the size and eof info. 3933 */ 3934 if (iseof) 3935 iseof = FALSE; 3936 3937 ret = nfscmd_dropped_entrysize((struct dirent64 *)data, 3938 nents, ret); 3939 } 3940 3941 3942 #if 0 /* notyet */ 3943 /* 3944 * Don't do this. It causes local disk writes when just 3945 * reading the file and the overhead is deemed larger 3946 * than the benefit. 3947 */ 3948 /* 3949 * Force modified metadata out to stable storage. 3950 */ 3951 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL); 3952 #endif 3953 3954 kmem_free(namlen, args->dircount); 3955 3956 resp->status = NFS3_OK; 3957 vattr_to_post_op_attr(vap, &resp->resok.dir_attributes); 3958 resp->resok.cookieverf = 0; 3959 resp->resok.reply.entries = (entryplus3 *)ndata; 3960 resp->resok.reply.eof = iseof; 3961 resp->resok.size = nents; 3962 resp->resok.count = args->dircount - ret; 3963 resp->resok.maxcount = args->maxcount; 3964 3965 DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req, 3966 cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp); 3967 if (ndata != data) 3968 kmem_free(data, args->dircount); 3969 3970 3971 VN_RELE(vp); 3972 3973 return; 3974 3975 out: 3976 if (curthread->t_flag & T_WOULDBLOCK) { 3977 curthread->t_flag &= ~T_WOULDBLOCK; 3978 resp->status = NFS3ERR_JUKEBOX; 3979 } else { 3980 resp->status = puterrno3(error); 3981 } 3982 out1: 3983 DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req, 3984 cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp); 3985 3986 if (vp != NULL) { 3987 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 3988 VN_RELE(vp); 3989 } 3990 3991 if (namlen != NULL) 3992 kmem_free(namlen, args->dircount); 3993 3994 vattr_to_post_op_attr(vap, &resp->resfail.dir_attributes); 3995 } 3996 3997 void * 3998 rfs3_readdirplus_getfh(READDIRPLUS3args *args) 3999 { 4000 4001 return (&args->dir); 4002 } 4003 4004 void 4005 rfs3_readdirplus_free(READDIRPLUS3res *resp) 4006 { 4007 4008 if (resp->status == NFS3_OK) { 4009 kmem_free(resp->resok.reply.entries, resp->resok.count); 4010 kmem_free(resp->resok.infop, 4011 resp->resok.size * sizeof (struct entryplus3_info)); 4012 } 4013 } 4014 4015 /* ARGSUSED */ 4016 void 4017 rfs3_fsstat(FSSTAT3args *args, FSSTAT3res *resp, struct exportinfo *exi, 4018 struct svc_req *req, cred_t *cr) 4019 { 4020 int error; 4021 vnode_t *vp; 4022 struct vattr *vap; 4023 struct vattr va; 4024 struct statvfs64 sb; 4025 4026 vap = NULL; 4027 4028 vp = nfs3_fhtovp(&args->fsroot, exi); 4029 4030 DTRACE_NFSV3_4(op__fsstat__start, struct svc_req *, req, 4031 cred_t *, cr, vnode_t *, vp, FSSTAT3args *, args); 4032 4033 if (vp == NULL) { 4034 error = ESTALE; 4035 goto out; 4036 } 4037 4038 if (is_system_labeled()) { 4039 bslabel_t *clabel = req->rq_label; 4040 4041 ASSERT(clabel != NULL); 4042 DTRACE_PROBE2(tx__rfs3__log__info__opfsstat__clabel, char *, 4043 "got client label from request(1)", struct svc_req *, req); 4044 4045 if (!blequal(&l_admin_low->tsl_label, clabel)) { 4046 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, 4047 exi)) { 4048 resp->status = NFS3ERR_ACCES; 4049 goto out1; 4050 } 4051 } 4052 } 4053 4054 error = VFS_STATVFS(vp->v_vfsp, &sb); 4055 4056 #ifdef DEBUG 4057 if (rfs3_do_post_op_attr) { 4058 va.va_mask = AT_ALL; 4059 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 4060 } else 4061 vap = NULL; 4062 #else 4063 va.va_mask = AT_ALL; 4064 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 4065 #endif 4066 4067 if (error) 4068 goto out; 4069 4070 resp->status = NFS3_OK; 4071 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 4072 if (sb.f_blocks != (fsblkcnt64_t)-1) 4073 resp->resok.tbytes = (size3)sb.f_frsize * (size3)sb.f_blocks; 4074 else 4075 resp->resok.tbytes = (size3)sb.f_blocks; 4076 if (sb.f_bfree != (fsblkcnt64_t)-1) 4077 resp->resok.fbytes = (size3)sb.f_frsize * (size3)sb.f_bfree; 4078 else 4079 resp->resok.fbytes = (size3)sb.f_bfree; 4080 if (sb.f_bavail != (fsblkcnt64_t)-1) 4081 resp->resok.abytes = (size3)sb.f_frsize * (size3)sb.f_bavail; 4082 else 4083 resp->resok.abytes = (size3)sb.f_bavail; 4084 resp->resok.tfiles = (size3)sb.f_files; 4085 resp->resok.ffiles = (size3)sb.f_ffree; 4086 resp->resok.afiles = (size3)sb.f_favail; 4087 resp->resok.invarsec = 0; 4088 4089 DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req, 4090 cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp); 4091 VN_RELE(vp); 4092 4093 return; 4094 4095 out: 4096 if (curthread->t_flag & T_WOULDBLOCK) { 4097 curthread->t_flag &= ~T_WOULDBLOCK; 4098 resp->status = NFS3ERR_JUKEBOX; 4099 } else 4100 resp->status = puterrno3(error); 4101 out1: 4102 DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req, 4103 cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp); 4104 4105 if (vp != NULL) 4106 VN_RELE(vp); 4107 vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes); 4108 } 4109 4110 void * 4111 rfs3_fsstat_getfh(FSSTAT3args *args) 4112 { 4113 4114 return (&args->fsroot); 4115 } 4116 4117 void 4118 rfs3_fsinfo(FSINFO3args *args, FSINFO3res *resp, struct exportinfo *exi, 4119 struct svc_req *req, cred_t *cr) 4120 { 4121 vnode_t *vp; 4122 struct vattr *vap; 4123 struct vattr va; 4124 uint32_t xfer_size; 4125 ulong_t l = 0; 4126 int error; 4127 4128 vp = nfs3_fhtovp(&args->fsroot, exi); 4129 4130 DTRACE_NFSV3_4(op__fsinfo__start, struct svc_req *, req, 4131 cred_t *, cr, vnode_t *, vp, FSINFO3args *, args); 4132 4133 if (vp == NULL) { 4134 if (curthread->t_flag & T_WOULDBLOCK) { 4135 curthread->t_flag &= ~T_WOULDBLOCK; 4136 resp->status = NFS3ERR_JUKEBOX; 4137 } else 4138 resp->status = NFS3ERR_STALE; 4139 vattr_to_post_op_attr(NULL, &resp->resfail.obj_attributes); 4140 goto out; 4141 } 4142 4143 if (is_system_labeled()) { 4144 bslabel_t *clabel = req->rq_label; 4145 4146 ASSERT(clabel != NULL); 4147 DTRACE_PROBE2(tx__rfs3__log__info__opfsinfo__clabel, char *, 4148 "got client label from request(1)", struct svc_req *, req); 4149 4150 if (!blequal(&l_admin_low->tsl_label, clabel)) { 4151 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, 4152 exi)) { 4153 resp->status = NFS3ERR_STALE; 4154 vattr_to_post_op_attr(NULL, 4155 &resp->resfail.obj_attributes); 4156 goto out; 4157 } 4158 } 4159 } 4160 4161 #ifdef DEBUG 4162 if (rfs3_do_post_op_attr) { 4163 va.va_mask = AT_ALL; 4164 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 4165 } else 4166 vap = NULL; 4167 #else 4168 va.va_mask = AT_ALL; 4169 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 4170 #endif 4171 4172 resp->status = NFS3_OK; 4173 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 4174 xfer_size = rfs3_tsize(req); 4175 resp->resok.rtmax = xfer_size; 4176 resp->resok.rtpref = xfer_size; 4177 resp->resok.rtmult = DEV_BSIZE; 4178 resp->resok.wtmax = xfer_size; 4179 resp->resok.wtpref = xfer_size; 4180 resp->resok.wtmult = DEV_BSIZE; 4181 resp->resok.dtpref = MAXBSIZE; 4182 4183 /* 4184 * Large file spec: want maxfilesize based on limit of 4185 * underlying filesystem. We can guess 2^31-1 if need be. 4186 */ 4187 error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL); 4188 if (error) { 4189 resp->status = puterrno3(error); 4190 goto out; 4191 } 4192 4193 /* 4194 * If the underlying file system does not support _PC_FILESIZEBITS, 4195 * return a reasonable default. Note that error code on VOP_PATHCONF 4196 * will be 0, even if the underlying file system does not support 4197 * _PC_FILESIZEBITS. 4198 */ 4199 if (l == (ulong_t)-1) { 4200 resp->resok.maxfilesize = MAXOFF32_T; 4201 } else { 4202 if (l >= (sizeof (uint64_t) * 8)) 4203 resp->resok.maxfilesize = INT64_MAX; 4204 else 4205 resp->resok.maxfilesize = (1LL << (l-1)) - 1; 4206 } 4207 4208 resp->resok.time_delta.seconds = 0; 4209 resp->resok.time_delta.nseconds = 1000; 4210 resp->resok.properties = FSF3_LINK | FSF3_SYMLINK | 4211 FSF3_HOMOGENEOUS | FSF3_CANSETTIME; 4212 4213 DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req, 4214 cred_t *, cr, vnode_t *, vp, FSINFO3res *, resp); 4215 4216 VN_RELE(vp); 4217 4218 return; 4219 4220 out: 4221 DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req, 4222 cred_t *, cr, vnode_t *, NULL, FSINFO3res *, resp); 4223 if (vp != NULL) 4224 VN_RELE(vp); 4225 } 4226 4227 void * 4228 rfs3_fsinfo_getfh(FSINFO3args *args) 4229 { 4230 4231 return (&args->fsroot); 4232 } 4233 4234 /* ARGSUSED */ 4235 void 4236 rfs3_pathconf(PATHCONF3args *args, PATHCONF3res *resp, struct exportinfo *exi, 4237 struct svc_req *req, cred_t *cr) 4238 { 4239 int error; 4240 vnode_t *vp; 4241 struct vattr *vap; 4242 struct vattr va; 4243 ulong_t val; 4244 4245 vap = NULL; 4246 4247 vp = nfs3_fhtovp(&args->object, exi); 4248 4249 DTRACE_NFSV3_4(op__pathconf__start, struct svc_req *, req, 4250 cred_t *, cr, vnode_t *, vp, PATHCONF3args *, args); 4251 4252 if (vp == NULL) { 4253 error = ESTALE; 4254 goto out; 4255 } 4256 4257 if (is_system_labeled()) { 4258 bslabel_t *clabel = req->rq_label; 4259 4260 ASSERT(clabel != NULL); 4261 DTRACE_PROBE2(tx__rfs3__log__info__oppathconf__clabel, char *, 4262 "got client label from request(1)", struct svc_req *, req); 4263 4264 if (!blequal(&l_admin_low->tsl_label, clabel)) { 4265 if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, 4266 exi)) { 4267 resp->status = NFS3ERR_ACCES; 4268 goto out1; 4269 } 4270 } 4271 } 4272 4273 #ifdef DEBUG 4274 if (rfs3_do_post_op_attr) { 4275 va.va_mask = AT_ALL; 4276 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 4277 } else 4278 vap = NULL; 4279 #else 4280 va.va_mask = AT_ALL; 4281 vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va; 4282 #endif 4283 4284 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &val, cr, NULL); 4285 if (error) 4286 goto out; 4287 resp->resok.info.link_max = (uint32)val; 4288 4289 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &val, cr, NULL); 4290 if (error) 4291 goto out; 4292 resp->resok.info.name_max = (uint32)val; 4293 4294 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &val, cr, NULL); 4295 if (error) 4296 goto out; 4297 if (val == 1) 4298 resp->resok.info.no_trunc = TRUE; 4299 else 4300 resp->resok.info.no_trunc = FALSE; 4301 4302 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &val, cr, NULL); 4303 if (error) 4304 goto out; 4305 if (val == 1) 4306 resp->resok.info.chown_restricted = TRUE; 4307 else 4308 resp->resok.info.chown_restricted = FALSE; 4309 4310 resp->status = NFS3_OK; 4311 vattr_to_post_op_attr(vap, &resp->resok.obj_attributes); 4312 resp->resok.info.case_insensitive = FALSE; 4313 resp->resok.info.case_preserving = TRUE; 4314 DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req, 4315 cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp); 4316 VN_RELE(vp); 4317 return; 4318 4319 out: 4320 if (curthread->t_flag & T_WOULDBLOCK) { 4321 curthread->t_flag &= ~T_WOULDBLOCK; 4322 resp->status = NFS3ERR_JUKEBOX; 4323 } else 4324 resp->status = puterrno3(error); 4325 out1: 4326 DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req, 4327 cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp); 4328 if (vp != NULL) 4329 VN_RELE(vp); 4330 vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes); 4331 } 4332 4333 void * 4334 rfs3_pathconf_getfh(PATHCONF3args *args) 4335 { 4336 4337 return (&args->object); 4338 } 4339 4340 void 4341 rfs3_commit(COMMIT3args *args, COMMIT3res *resp, struct exportinfo *exi, 4342 struct svc_req *req, cred_t *cr) 4343 { 4344 int error; 4345 vnode_t *vp; 4346 struct vattr *bvap; 4347 struct vattr bva; 4348 struct vattr *avap; 4349 struct vattr ava; 4350 4351 bvap = NULL; 4352 avap = NULL; 4353 4354 vp = nfs3_fhtovp(&args->file, exi); 4355 4356 DTRACE_NFSV3_4(op__commit__start, struct svc_req *, req, 4357 cred_t *, cr, vnode_t *, vp, COMMIT3args *, args); 4358 4359 if (vp == NULL) { 4360 error = ESTALE; 4361 goto out; 4362 } 4363 4364 bva.va_mask = AT_ALL; 4365 error = VOP_GETATTR(vp, &bva, 0, cr, NULL); 4366 4367 /* 4368 * If we can't get the attributes, then we can't do the 4369 * right access checking. So, we'll fail the request. 4370 */ 4371 if (error) 4372 goto out; 4373 4374 #ifdef DEBUG 4375 if (rfs3_do_pre_op_attr) 4376 bvap = &bva; 4377 else 4378 bvap = NULL; 4379 #else 4380 bvap = &bva; 4381 #endif 4382 4383 if (rdonly(exi, req)) { 4384 resp->status = NFS3ERR_ROFS; 4385 goto out1; 4386 } 4387 4388 if (vp->v_type != VREG) { 4389 resp->status = NFS3ERR_INVAL; 4390 goto out1; 4391 } 4392 4393 if (is_system_labeled()) { 4394 bslabel_t *clabel = req->rq_label; 4395 4396 ASSERT(clabel != NULL); 4397 DTRACE_PROBE2(tx__rfs3__log__info__opcommit__clabel, char *, 4398 "got client label from request(1)", struct svc_req *, req); 4399 4400 if (!blequal(&l_admin_low->tsl_label, clabel)) { 4401 if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, 4402 exi)) { 4403 resp->status = NFS3ERR_ACCES; 4404 goto out1; 4405 } 4406 } 4407 } 4408 4409 if (crgetuid(cr) != bva.va_uid && 4410 (error = VOP_ACCESS(vp, VWRITE, 0, cr, NULL))) 4411 goto out; 4412 4413 error = VOP_PUTPAGE(vp, args->offset, args->count, 0, cr, NULL); 4414 if (!error) 4415 error = VOP_FSYNC(vp, FNODSYNC, cr, NULL); 4416 4417 #ifdef DEBUG 4418 if (rfs3_do_post_op_attr) { 4419 ava.va_mask = AT_ALL; 4420 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava; 4421 } else 4422 avap = NULL; 4423 #else 4424 ava.va_mask = AT_ALL; 4425 avap = VOP_GETATTR(vp, &ava, 0, cr, NULL) ? NULL : &ava; 4426 #endif 4427 4428 if (error) 4429 goto out; 4430 4431 resp->status = NFS3_OK; 4432 vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc); 4433 resp->resok.verf = write3verf; 4434 4435 DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req, 4436 cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp); 4437 4438 VN_RELE(vp); 4439 4440 return; 4441 4442 out: 4443 if (curthread->t_flag & T_WOULDBLOCK) { 4444 curthread->t_flag &= ~T_WOULDBLOCK; 4445 resp->status = NFS3ERR_JUKEBOX; 4446 } else 4447 resp->status = puterrno3(error); 4448 out1: 4449 DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req, 4450 cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp); 4451 4452 if (vp != NULL) 4453 VN_RELE(vp); 4454 vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc); 4455 } 4456 4457 void * 4458 rfs3_commit_getfh(COMMIT3args *args) 4459 { 4460 4461 return (&args->file); 4462 } 4463 4464 static int 4465 sattr3_to_vattr(sattr3 *sap, struct vattr *vap) 4466 { 4467 4468 vap->va_mask = 0; 4469 4470 if (sap->mode.set_it) { 4471 vap->va_mode = (mode_t)sap->mode.mode; 4472 vap->va_mask |= AT_MODE; 4473 } 4474 if (sap->uid.set_it) { 4475 vap->va_uid = (uid_t)sap->uid.uid; 4476 vap->va_mask |= AT_UID; 4477 } 4478 if (sap->gid.set_it) { 4479 vap->va_gid = (gid_t)sap->gid.gid; 4480 vap->va_mask |= AT_GID; 4481 } 4482 if (sap->size.set_it) { 4483 if (sap->size.size > (size3)((u_longlong_t)-1)) 4484 return (EINVAL); 4485 vap->va_size = sap->size.size; 4486 vap->va_mask |= AT_SIZE; 4487 } 4488 if (sap->atime.set_it == SET_TO_CLIENT_TIME) { 4489 #ifndef _LP64 4490 /* check time validity */ 4491 if (!NFS3_TIME_OK(sap->atime.atime.seconds)) 4492 return (EOVERFLOW); 4493 #endif 4494 /* 4495 * nfs protocol defines times as unsigned so don't extend sign, 4496 * unless sysadmin set nfs_allow_preepoch_time. 4497 */ 4498 NFS_TIME_T_CONVERT(vap->va_atime.tv_sec, 4499 sap->atime.atime.seconds); 4500 vap->va_atime.tv_nsec = (uint32_t)sap->atime.atime.nseconds; 4501 vap->va_mask |= AT_ATIME; 4502 } else if (sap->atime.set_it == SET_TO_SERVER_TIME) { 4503 gethrestime(&vap->va_atime); 4504 vap->va_mask |= AT_ATIME; 4505 } 4506 if (sap->mtime.set_it == SET_TO_CLIENT_TIME) { 4507 #ifndef _LP64 4508 /* check time validity */ 4509 if (!NFS3_TIME_OK(sap->mtime.mtime.seconds)) 4510 return (EOVERFLOW); 4511 #endif 4512 /* 4513 * nfs protocol defines times as unsigned so don't extend sign, 4514 * unless sysadmin set nfs_allow_preepoch_time. 4515 */ 4516 NFS_TIME_T_CONVERT(vap->va_mtime.tv_sec, 4517 sap->mtime.mtime.seconds); 4518 vap->va_mtime.tv_nsec = (uint32_t)sap->mtime.mtime.nseconds; 4519 vap->va_mask |= AT_MTIME; 4520 } else if (sap->mtime.set_it == SET_TO_SERVER_TIME) { 4521 gethrestime(&vap->va_mtime); 4522 vap->va_mask |= AT_MTIME; 4523 } 4524 4525 return (0); 4526 } 4527 4528 static ftype3 vt_to_nf3[] = { 4529 0, NF3REG, NF3DIR, NF3BLK, NF3CHR, NF3LNK, NF3FIFO, 0, 0, NF3SOCK, 0 4530 }; 4531 4532 static int 4533 vattr_to_fattr3(struct vattr *vap, fattr3 *fap) 4534 { 4535 4536 ASSERT(vap->va_type >= VNON && vap->va_type <= VBAD); 4537 /* Return error if time or size overflow */ 4538 if (! (NFS_VAP_TIME_OK(vap) && NFS3_SIZE_OK(vap->va_size))) { 4539 return (EOVERFLOW); 4540 } 4541 fap->type = vt_to_nf3[vap->va_type]; 4542 fap->mode = (mode3)(vap->va_mode & MODEMASK); 4543 fap->nlink = (uint32)vap->va_nlink; 4544 if (vap->va_uid == UID_NOBODY) 4545 fap->uid = (uid3)NFS_UID_NOBODY; 4546 else 4547 fap->uid = (uid3)vap->va_uid; 4548 if (vap->va_gid == GID_NOBODY) 4549 fap->gid = (gid3)NFS_GID_NOBODY; 4550 else 4551 fap->gid = (gid3)vap->va_gid; 4552 fap->size = (size3)vap->va_size; 4553 fap->used = (size3)DEV_BSIZE * (size3)vap->va_nblocks; 4554 fap->rdev.specdata1 = (uint32)getmajor(vap->va_rdev); 4555 fap->rdev.specdata2 = (uint32)getminor(vap->va_rdev); 4556 fap->fsid = (uint64)vap->va_fsid; 4557 fap->fileid = (fileid3)vap->va_nodeid; 4558 fap->atime.seconds = vap->va_atime.tv_sec; 4559 fap->atime.nseconds = vap->va_atime.tv_nsec; 4560 fap->mtime.seconds = vap->va_mtime.tv_sec; 4561 fap->mtime.nseconds = vap->va_mtime.tv_nsec; 4562 fap->ctime.seconds = vap->va_ctime.tv_sec; 4563 fap->ctime.nseconds = vap->va_ctime.tv_nsec; 4564 return (0); 4565 } 4566 4567 static int 4568 vattr_to_wcc_attr(struct vattr *vap, wcc_attr *wccap) 4569 { 4570 4571 /* Return error if time or size overflow */ 4572 if (!(NFS_TIME_T_OK(vap->va_mtime.tv_sec) && 4573 NFS_TIME_T_OK(vap->va_ctime.tv_sec) && 4574 NFS3_SIZE_OK(vap->va_size))) { 4575 return (EOVERFLOW); 4576 } 4577 wccap->size = (size3)vap->va_size; 4578 wccap->mtime.seconds = vap->va_mtime.tv_sec; 4579 wccap->mtime.nseconds = vap->va_mtime.tv_nsec; 4580 wccap->ctime.seconds = vap->va_ctime.tv_sec; 4581 wccap->ctime.nseconds = vap->va_ctime.tv_nsec; 4582 return (0); 4583 } 4584 4585 static void 4586 vattr_to_pre_op_attr(struct vattr *vap, pre_op_attr *poap) 4587 { 4588 4589 /* don't return attrs if time overflow */ 4590 if ((vap != NULL) && !vattr_to_wcc_attr(vap, &poap->attr)) { 4591 poap->attributes = TRUE; 4592 } else 4593 poap->attributes = FALSE; 4594 } 4595 4596 void 4597 vattr_to_post_op_attr(struct vattr *vap, post_op_attr *poap) 4598 { 4599 4600 /* don't return attrs if time overflow */ 4601 if ((vap != NULL) && !vattr_to_fattr3(vap, &poap->attr)) { 4602 poap->attributes = TRUE; 4603 } else 4604 poap->attributes = FALSE; 4605 } 4606 4607 static void 4608 vattr_to_wcc_data(struct vattr *bvap, struct vattr *avap, wcc_data *wccp) 4609 { 4610 4611 vattr_to_pre_op_attr(bvap, &wccp->before); 4612 vattr_to_post_op_attr(avap, &wccp->after); 4613 } 4614 4615 void 4616 rfs3_srvrinit(void) 4617 { 4618 struct rfs3_verf_overlay { 4619 uint_t id; /* a "unique" identifier */ 4620 int ts; /* a unique timestamp */ 4621 } *verfp; 4622 timestruc_t now; 4623 4624 /* 4625 * The following algorithm attempts to find a unique verifier 4626 * to be used as the write verifier returned from the server 4627 * to the client. It is important that this verifier change 4628 * whenever the server reboots. Of secondary importance, it 4629 * is important for the verifier to be unique between two 4630 * different servers. 4631 * 4632 * Thus, an attempt is made to use the system hostid and the 4633 * current time in seconds when the nfssrv kernel module is 4634 * loaded. It is assumed that an NFS server will not be able 4635 * to boot and then to reboot in less than a second. If the 4636 * hostid has not been set, then the current high resolution 4637 * time is used. This will ensure different verifiers each 4638 * time the server reboots and minimize the chances that two 4639 * different servers will have the same verifier. 4640 */ 4641 4642 #ifndef lint 4643 /* 4644 * We ASSERT that this constant logic expression is 4645 * always true because in the past, it wasn't. 4646 */ 4647 ASSERT(sizeof (*verfp) <= sizeof (write3verf)); 4648 #endif 4649 4650 gethrestime(&now); 4651 verfp = (struct rfs3_verf_overlay *)&write3verf; 4652 verfp->ts = (int)now.tv_sec; 4653 verfp->id = zone_get_hostid(NULL); 4654 4655 if (verfp->id == 0) 4656 verfp->id = (uint_t)now.tv_nsec; 4657 4658 nfs3_srv_caller_id = fs_new_caller_id(); 4659 4660 } 4661 4662 static int 4663 rdma_setup_read_data3(READ3args *args, READ3resok *rok) 4664 { 4665 struct clist *wcl; 4666 int wlist_len; 4667 count3 count = rok->count; 4668 4669 wcl = args->wlist; 4670 if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE) { 4671 return (FALSE); 4672 } 4673 4674 wcl = args->wlist; 4675 rok->wlist_len = wlist_len; 4676 rok->wlist = wcl; 4677 return (TRUE); 4678 } 4679 4680 void 4681 rfs3_srvrfini(void) 4682 { 4683 /* Nothing to do */ 4684 } 4685