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 (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. 28 * All rights reserved. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/systm.h> 34 #include <sys/cred.h> 35 #include <sys/buf.h> 36 #include <sys/vfs.h> 37 #include <sys/vnode.h> 38 #include <sys/uio.h> 39 #include <sys/stat.h> 40 #include <sys/errno.h> 41 #include <sys/sysmacros.h> 42 #include <sys/statvfs.h> 43 #include <sys/kmem.h> 44 #include <sys/kstat.h> 45 #include <sys/dirent.h> 46 #include <sys/cmn_err.h> 47 #include <sys/debug.h> 48 #include <sys/vtrace.h> 49 #include <sys/mode.h> 50 #include <sys/acl.h> 51 #include <sys/nbmlock.h> 52 #include <sys/policy.h> 53 #include <sys/sdt.h> 54 55 #include <rpc/types.h> 56 #include <rpc/auth.h> 57 #include <rpc/svc.h> 58 59 #include <nfs/nfs.h> 60 #include <nfs/export.h> 61 #include <nfs/nfs_cmd.h> 62 63 #include <vm/hat.h> 64 #include <vm/as.h> 65 #include <vm/seg.h> 66 #include <vm/seg_map.h> 67 #include <vm/seg_kmem.h> 68 69 #include <sys/strsubr.h> 70 71 /* 72 * These are the interface routines for the server side of the 73 * Network File System. See the NFS version 2 protocol specification 74 * for a description of this interface. 75 */ 76 77 static int sattr_to_vattr(struct nfssattr *, struct vattr *); 78 static void acl_perm(struct vnode *, struct exportinfo *, struct vattr *, 79 cred_t *); 80 81 /* 82 * Some "over the wire" UNIX file types. These are encoded 83 * into the mode. This needs to be fixed in the next rev. 84 */ 85 #define IFMT 0170000 /* type of file */ 86 #define IFCHR 0020000 /* character special */ 87 #define IFBLK 0060000 /* block special */ 88 #define IFSOCK 0140000 /* socket */ 89 90 u_longlong_t nfs2_srv_caller_id; 91 92 /* 93 * Get file attributes. 94 * Returns the current attributes of the file with the given fhandle. 95 */ 96 /* ARGSUSED */ 97 void 98 rfs_getattr(fhandle_t *fhp, struct nfsattrstat *ns, struct exportinfo *exi, 99 struct svc_req *req, cred_t *cr, bool_t ro) 100 { 101 int error; 102 vnode_t *vp; 103 struct vattr va; 104 105 vp = nfs_fhtovp(fhp, exi); 106 if (vp == NULL) { 107 ns->ns_status = NFSERR_STALE; 108 return; 109 } 110 111 /* 112 * Do the getattr. 113 */ 114 va.va_mask = AT_ALL; /* we want all the attributes */ 115 116 error = rfs4_delegated_getattr(vp, &va, 0, cr); 117 118 /* check for overflows */ 119 if (!error) { 120 /* Lie about the object type for a referral */ 121 if (vn_is_nfs_reparse(vp, cr)) 122 va.va_type = VLNK; 123 124 acl_perm(vp, exi, &va, cr); 125 error = vattr_to_nattr(&va, &ns->ns_attr); 126 } 127 128 VN_RELE(vp); 129 130 ns->ns_status = puterrno(error); 131 } 132 void * 133 rfs_getattr_getfh(fhandle_t *fhp) 134 { 135 return (fhp); 136 } 137 138 /* 139 * Set file attributes. 140 * Sets the attributes of the file with the given fhandle. Returns 141 * the new attributes. 142 */ 143 /* ARGSUSED */ 144 void 145 rfs_setattr(struct nfssaargs *args, struct nfsattrstat *ns, 146 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 147 { 148 int error; 149 int flag; 150 int in_crit = 0; 151 vnode_t *vp; 152 struct vattr va; 153 struct vattr bva; 154 struct flock64 bf; 155 caller_context_t ct; 156 157 158 vp = nfs_fhtovp(&args->saa_fh, exi); 159 if (vp == NULL) { 160 ns->ns_status = NFSERR_STALE; 161 return; 162 } 163 164 if (rdonly(ro, vp)) { 165 VN_RELE(vp); 166 ns->ns_status = NFSERR_ROFS; 167 return; 168 } 169 170 error = sattr_to_vattr(&args->saa_sa, &va); 171 if (error) { 172 VN_RELE(vp); 173 ns->ns_status = puterrno(error); 174 return; 175 } 176 177 /* 178 * If the client is requesting a change to the mtime, 179 * but the nanosecond field is set to 1 billion, then 180 * this is a flag to the server that it should set the 181 * atime and mtime fields to the server's current time. 182 * The 1 billion number actually came from the client 183 * as 1 million, but the units in the over the wire 184 * request are microseconds instead of nanoseconds. 185 * 186 * This is an overload of the protocol and should be 187 * documented in the NFS Version 2 protocol specification. 188 */ 189 if (va.va_mask & AT_MTIME) { 190 if (va.va_mtime.tv_nsec == 1000000000) { 191 gethrestime(&va.va_mtime); 192 va.va_atime = va.va_mtime; 193 va.va_mask |= AT_ATIME; 194 flag = 0; 195 } else 196 flag = ATTR_UTIME; 197 } else 198 flag = 0; 199 200 /* 201 * If the filesystem is exported with nosuid, then mask off 202 * the setuid and setgid bits. 203 */ 204 if ((va.va_mask & AT_MODE) && vp->v_type == VREG && 205 (exi->exi_export.ex_flags & EX_NOSUID)) 206 va.va_mode &= ~(VSUID | VSGID); 207 208 ct.cc_sysid = 0; 209 ct.cc_pid = 0; 210 ct.cc_caller_id = nfs2_srv_caller_id; 211 ct.cc_flags = CC_DONTBLOCK; 212 213 /* 214 * We need to specially handle size changes because it is 215 * possible for the client to create a file with modes 216 * which indicate read-only, but with the file opened for 217 * writing. If the client then tries to set the size of 218 * the file, then the normal access checking done in 219 * VOP_SETATTR would prevent the client from doing so, 220 * although it should be legal for it to do so. To get 221 * around this, we do the access checking for ourselves 222 * and then use VOP_SPACE which doesn't do the access 223 * checking which VOP_SETATTR does. VOP_SPACE can only 224 * operate on VREG files, let VOP_SETATTR handle the other 225 * extremely rare cases. 226 * Also the client should not be allowed to change the 227 * size of the file if there is a conflicting non-blocking 228 * mandatory lock in the region of change. 229 */ 230 if (vp->v_type == VREG && va.va_mask & AT_SIZE) { 231 if (nbl_need_check(vp)) { 232 nbl_start_crit(vp, RW_READER); 233 in_crit = 1; 234 } 235 236 bva.va_mask = AT_UID | AT_SIZE; 237 238 error = VOP_GETATTR(vp, &bva, 0, cr, &ct); 239 240 if (error) { 241 if (in_crit) 242 nbl_end_crit(vp); 243 VN_RELE(vp); 244 ns->ns_status = puterrno(error); 245 return; 246 } 247 248 if (in_crit) { 249 u_offset_t offset; 250 ssize_t length; 251 252 if (va.va_size < bva.va_size) { 253 offset = va.va_size; 254 length = bva.va_size - va.va_size; 255 } else { 256 offset = bva.va_size; 257 length = va.va_size - bva.va_size; 258 } 259 if (nbl_conflict(vp, NBL_WRITE, offset, length, 0, 260 NULL)) { 261 error = EACCES; 262 } 263 } 264 265 if (crgetuid(cr) == bva.va_uid && !error && 266 va.va_size != bva.va_size) { 267 va.va_mask &= ~AT_SIZE; 268 bf.l_type = F_WRLCK; 269 bf.l_whence = 0; 270 bf.l_start = (off64_t)va.va_size; 271 bf.l_len = 0; 272 bf.l_sysid = 0; 273 bf.l_pid = 0; 274 275 error = VOP_SPACE(vp, F_FREESP, &bf, FWRITE, 276 (offset_t)va.va_size, cr, &ct); 277 } 278 if (in_crit) 279 nbl_end_crit(vp); 280 } else 281 error = 0; 282 283 /* 284 * Do the setattr. 285 */ 286 if (!error && va.va_mask) { 287 error = VOP_SETATTR(vp, &va, flag, cr, &ct); 288 } 289 290 /* 291 * check if the monitor on either vop_space or vop_setattr detected 292 * a delegation conflict and if so, mark the thread flag as 293 * wouldblock so that the response is dropped and the client will 294 * try again. 295 */ 296 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 297 VN_RELE(vp); 298 curthread->t_flag |= T_WOULDBLOCK; 299 return; 300 } 301 302 if (!error) { 303 va.va_mask = AT_ALL; /* get everything */ 304 305 error = rfs4_delegated_getattr(vp, &va, 0, cr); 306 307 /* check for overflows */ 308 if (!error) { 309 acl_perm(vp, exi, &va, cr); 310 error = vattr_to_nattr(&va, &ns->ns_attr); 311 } 312 } 313 314 ct.cc_flags = 0; 315 316 /* 317 * Force modified metadata out to stable storage. 318 */ 319 (void) VOP_FSYNC(vp, FNODSYNC, cr, &ct); 320 321 VN_RELE(vp); 322 323 ns->ns_status = puterrno(error); 324 } 325 void * 326 rfs_setattr_getfh(struct nfssaargs *args) 327 { 328 return (&args->saa_fh); 329 } 330 331 /* 332 * Directory lookup. 333 * Returns an fhandle and file attributes for file name in a directory. 334 */ 335 /* ARGSUSED */ 336 void 337 rfs_lookup(struct nfsdiropargs *da, struct nfsdiropres *dr, 338 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 339 { 340 int error; 341 vnode_t *dvp; 342 vnode_t *vp; 343 struct vattr va; 344 fhandle_t *fhp = da->da_fhandle; 345 struct sec_ol sec = {0, 0}; 346 bool_t publicfh_flag = FALSE, auth_weak = FALSE; 347 char *name; 348 struct sockaddr *ca; 349 350 /* 351 * Trusted Extension doesn't support NFSv2. MOUNT 352 * will reject v2 clients. Need to prevent v2 client 353 * access via WebNFS here. 354 */ 355 if (is_system_labeled() && req->rq_vers == 2) { 356 dr->dr_status = NFSERR_ACCES; 357 return; 358 } 359 360 /* 361 * Disallow NULL paths 362 */ 363 if (da->da_name == NULL || *da->da_name == '\0') { 364 dr->dr_status = NFSERR_ACCES; 365 return; 366 } 367 368 /* 369 * Allow lookups from the root - the default 370 * location of the public filehandle. 371 */ 372 if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) { 373 dvp = rootdir; 374 VN_HOLD(dvp); 375 } else { 376 dvp = nfs_fhtovp(fhp, exi); 377 if (dvp == NULL) { 378 dr->dr_status = NFSERR_STALE; 379 return; 380 } 381 } 382 383 /* 384 * Not allow lookup beyond root. 385 * If the filehandle matches a filehandle of the exi, 386 * then the ".." refers beyond the root of an exported filesystem. 387 */ 388 if (strcmp(da->da_name, "..") == 0 && 389 EQFID(&exi->exi_fid, (fid_t *)&fhp->fh_len)) { 390 VN_RELE(dvp); 391 dr->dr_status = NFSERR_NOENT; 392 return; 393 } 394 395 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 396 name = nfscmd_convname(ca, exi, da->da_name, NFSCMD_CONV_INBOUND, 397 MAXPATHLEN); 398 399 if (name == NULL) { 400 dr->dr_status = NFSERR_ACCES; 401 return; 402 } 403 404 /* 405 * If the public filehandle is used then allow 406 * a multi-component lookup, i.e. evaluate 407 * a pathname and follow symbolic links if 408 * necessary. 409 * 410 * This may result in a vnode in another filesystem 411 * which is OK as long as the filesystem is exported. 412 */ 413 if (PUBLIC_FH2(fhp)) { 414 publicfh_flag = TRUE; 415 error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi, 416 &sec); 417 } else { 418 /* 419 * Do a normal single component lookup. 420 */ 421 error = VOP_LOOKUP(dvp, name, &vp, NULL, 0, NULL, cr, 422 NULL, NULL, NULL); 423 } 424 425 if (name != da->da_name) 426 kmem_free(name, MAXPATHLEN); 427 428 429 if (!error) { 430 va.va_mask = AT_ALL; /* we want everything */ 431 432 error = rfs4_delegated_getattr(vp, &va, 0, cr); 433 434 /* check for overflows */ 435 if (!error) { 436 acl_perm(vp, exi, &va, cr); 437 error = vattr_to_nattr(&va, &dr->dr_attr); 438 if (!error) { 439 if (sec.sec_flags & SEC_QUERY) 440 error = makefh_ol(&dr->dr_fhandle, exi, 441 sec.sec_index); 442 else { 443 error = makefh(&dr->dr_fhandle, vp, 444 exi); 445 if (!error && publicfh_flag && 446 !chk_clnt_sec(exi, req)) 447 auth_weak = TRUE; 448 } 449 } 450 } 451 VN_RELE(vp); 452 } 453 454 VN_RELE(dvp); 455 456 /* 457 * If publicfh_flag is true then we have called rfs_publicfh_mclookup 458 * and have obtained a new exportinfo in exi which needs to be 459 * released. Note the the original exportinfo pointed to by exi 460 * will be released by the caller, comon_dispatch. 461 */ 462 if (publicfh_flag && exi != NULL) 463 exi_rele(exi); 464 465 /* 466 * If it's public fh, no 0x81, and client's flavor is 467 * invalid, set WebNFS status to WNFSERR_CLNT_FLAVOR now. 468 * Then set RPC status to AUTH_TOOWEAK in common_dispatch. 469 */ 470 if (auth_weak) 471 dr->dr_status = (enum nfsstat)WNFSERR_CLNT_FLAVOR; 472 else 473 dr->dr_status = puterrno(error); 474 } 475 void * 476 rfs_lookup_getfh(struct nfsdiropargs *da) 477 { 478 return (da->da_fhandle); 479 } 480 481 /* 482 * Read symbolic link. 483 * Returns the string in the symbolic link at the given fhandle. 484 */ 485 /* ARGSUSED */ 486 void 487 rfs_readlink(fhandle_t *fhp, struct nfsrdlnres *rl, struct exportinfo *exi, 488 struct svc_req *req, cred_t *cr, bool_t ro) 489 { 490 int error; 491 struct iovec iov; 492 struct uio uio; 493 vnode_t *vp; 494 struct vattr va; 495 struct sockaddr *ca; 496 char *name = NULL; 497 int is_referral = 0; 498 499 vp = nfs_fhtovp(fhp, exi); 500 if (vp == NULL) { 501 rl->rl_data = NULL; 502 rl->rl_status = NFSERR_STALE; 503 return; 504 } 505 506 va.va_mask = AT_MODE; 507 508 error = VOP_GETATTR(vp, &va, 0, cr, NULL); 509 510 if (error) { 511 VN_RELE(vp); 512 rl->rl_data = NULL; 513 rl->rl_status = puterrno(error); 514 return; 515 } 516 517 if (MANDLOCK(vp, va.va_mode)) { 518 VN_RELE(vp); 519 rl->rl_data = NULL; 520 rl->rl_status = NFSERR_ACCES; 521 return; 522 } 523 524 /* We lied about the object type for a referral */ 525 if (vn_is_nfs_reparse(vp, cr)) 526 is_referral = 1; 527 528 /* 529 * XNFS and RFC1094 require us to return ENXIO if argument 530 * is not a link. BUGID 1138002. 531 */ 532 if (vp->v_type != VLNK && !is_referral) { 533 VN_RELE(vp); 534 rl->rl_data = NULL; 535 rl->rl_status = NFSERR_NXIO; 536 return; 537 } 538 539 /* 540 * Allocate data for pathname. This will be freed by rfs_rlfree. 541 */ 542 rl->rl_data = kmem_alloc(NFS_MAXPATHLEN, KM_SLEEP); 543 544 if (is_referral) { 545 char *s; 546 size_t strsz; 547 548 /* Get an artificial symlink based on a referral */ 549 s = build_symlink(vp, cr, &strsz); 550 global_svstat_ptr[2][NFS_REFERLINKS].value.ui64++; 551 DTRACE_PROBE2(nfs2serv__func__referral__reflink, 552 vnode_t *, vp, char *, s); 553 if (s == NULL) 554 error = EINVAL; 555 else { 556 error = 0; 557 (void) strlcpy(rl->rl_data, s, NFS_MAXPATHLEN); 558 rl->rl_count = (uint32_t)MIN(strsz, NFS_MAXPATHLEN); 559 kmem_free(s, strsz); 560 } 561 562 } else { 563 564 /* 565 * Set up io vector to read sym link data 566 */ 567 iov.iov_base = rl->rl_data; 568 iov.iov_len = NFS_MAXPATHLEN; 569 uio.uio_iov = &iov; 570 uio.uio_iovcnt = 1; 571 uio.uio_segflg = UIO_SYSSPACE; 572 uio.uio_extflg = UIO_COPY_CACHED; 573 uio.uio_loffset = (offset_t)0; 574 uio.uio_resid = NFS_MAXPATHLEN; 575 576 /* 577 * Do the readlink. 578 */ 579 error = VOP_READLINK(vp, &uio, cr, NULL); 580 581 rl->rl_count = (uint32_t)(NFS_MAXPATHLEN - uio.uio_resid); 582 583 if (!error) 584 rl->rl_data[rl->rl_count] = '\0'; 585 586 } 587 588 589 VN_RELE(vp); 590 591 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 592 name = nfscmd_convname(ca, exi, rl->rl_data, 593 NFSCMD_CONV_OUTBOUND, MAXPATHLEN); 594 595 if (name != NULL && name != rl->rl_data) { 596 kmem_free(rl->rl_data, NFS_MAXPATHLEN); 597 rl->rl_data = name; 598 } 599 600 /* 601 * XNFS and RFC1094 require us to return ENXIO if argument 602 * is not a link. UFS returns EINVAL if this is the case, 603 * so we do the mapping here. BUGID 1138002. 604 */ 605 if (error == EINVAL) 606 rl->rl_status = NFSERR_NXIO; 607 else 608 rl->rl_status = puterrno(error); 609 610 } 611 void * 612 rfs_readlink_getfh(fhandle_t *fhp) 613 { 614 return (fhp); 615 } 616 /* 617 * Free data allocated by rfs_readlink 618 */ 619 void 620 rfs_rlfree(struct nfsrdlnres *rl) 621 { 622 if (rl->rl_data != NULL) 623 kmem_free(rl->rl_data, NFS_MAXPATHLEN); 624 } 625 626 static int rdma_setup_read_data2(struct nfsreadargs *, struct nfsrdresult *); 627 628 /* 629 * Read data. 630 * Returns some data read from the file at the given fhandle. 631 */ 632 /* ARGSUSED */ 633 void 634 rfs_read(struct nfsreadargs *ra, struct nfsrdresult *rr, 635 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 636 { 637 vnode_t *vp; 638 int error; 639 struct vattr va; 640 struct iovec iov; 641 struct uio uio; 642 mblk_t *mp; 643 int alloc_err = 0; 644 int in_crit = 0; 645 caller_context_t ct; 646 647 vp = nfs_fhtovp(&ra->ra_fhandle, exi); 648 if (vp == NULL) { 649 rr->rr_data = NULL; 650 rr->rr_status = NFSERR_STALE; 651 return; 652 } 653 654 if (vp->v_type != VREG) { 655 VN_RELE(vp); 656 rr->rr_data = NULL; 657 rr->rr_status = NFSERR_ISDIR; 658 return; 659 } 660 661 ct.cc_sysid = 0; 662 ct.cc_pid = 0; 663 ct.cc_caller_id = nfs2_srv_caller_id; 664 ct.cc_flags = CC_DONTBLOCK; 665 666 /* 667 * Enter the critical region before calling VOP_RWLOCK 668 * to avoid a deadlock with write requests. 669 */ 670 if (nbl_need_check(vp)) { 671 nbl_start_crit(vp, RW_READER); 672 if (nbl_conflict(vp, NBL_READ, ra->ra_offset, ra->ra_count, 673 0, NULL)) { 674 nbl_end_crit(vp); 675 VN_RELE(vp); 676 rr->rr_data = NULL; 677 rr->rr_status = NFSERR_ACCES; 678 return; 679 } 680 in_crit = 1; 681 } 682 683 error = VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &ct); 684 685 /* check if a monitor detected a delegation conflict */ 686 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 687 VN_RELE(vp); 688 /* mark as wouldblock so response is dropped */ 689 curthread->t_flag |= T_WOULDBLOCK; 690 691 rr->rr_data = NULL; 692 return; 693 } 694 695 va.va_mask = AT_ALL; 696 697 error = VOP_GETATTR(vp, &va, 0, cr, &ct); 698 699 if (error) { 700 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 701 if (in_crit) 702 nbl_end_crit(vp); 703 704 VN_RELE(vp); 705 rr->rr_data = NULL; 706 rr->rr_status = puterrno(error); 707 708 return; 709 } 710 711 /* 712 * This is a kludge to allow reading of files created 713 * with no read permission. The owner of the file 714 * is always allowed to read it. 715 */ 716 if (crgetuid(cr) != va.va_uid) { 717 error = VOP_ACCESS(vp, VREAD, 0, cr, &ct); 718 719 if (error) { 720 /* 721 * Exec is the same as read over the net because 722 * of demand loading. 723 */ 724 error = VOP_ACCESS(vp, VEXEC, 0, cr, &ct); 725 } 726 if (error) { 727 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 728 if (in_crit) 729 nbl_end_crit(vp); 730 VN_RELE(vp); 731 rr->rr_data = NULL; 732 rr->rr_status = puterrno(error); 733 734 return; 735 } 736 } 737 738 if (MANDLOCK(vp, va.va_mode)) { 739 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 740 if (in_crit) 741 nbl_end_crit(vp); 742 743 VN_RELE(vp); 744 rr->rr_data = NULL; 745 rr->rr_status = NFSERR_ACCES; 746 747 return; 748 } 749 750 rr->rr_ok.rrok_wlist_len = 0; 751 rr->rr_ok.rrok_wlist = NULL; 752 753 if ((u_offset_t)ra->ra_offset >= va.va_size) { 754 rr->rr_count = 0; 755 rr->rr_data = NULL; 756 /* 757 * In this case, status is NFS_OK, but there is no data 758 * to encode. So set rr_mp to NULL. 759 */ 760 rr->rr_mp = NULL; 761 rr->rr_ok.rrok_wlist = ra->ra_wlist; 762 if (rr->rr_ok.rrok_wlist) 763 clist_zero_len(rr->rr_ok.rrok_wlist); 764 goto done; 765 } 766 767 if (ra->ra_wlist) { 768 mp = NULL; 769 rr->rr_mp = NULL; 770 (void) rdma_get_wchunk(req, &iov, ra->ra_wlist); 771 if (ra->ra_count > iov.iov_len) { 772 rr->rr_data = NULL; 773 rr->rr_status = NFSERR_INVAL; 774 goto done; 775 } 776 } else { 777 /* 778 * mp will contain the data to be sent out in the read reply. 779 * This will be freed after the reply has been sent out (by the 780 * driver). 781 * Let's roundup the data to a BYTES_PER_XDR_UNIT multiple, so 782 * that the call to xdrmblk_putmblk() never fails. 783 */ 784 mp = allocb_wait(RNDUP(ra->ra_count), BPRI_MED, STR_NOSIG, 785 &alloc_err); 786 ASSERT(mp != NULL); 787 ASSERT(alloc_err == 0); 788 789 rr->rr_mp = mp; 790 791 /* 792 * Set up io vector 793 */ 794 iov.iov_base = (caddr_t)mp->b_datap->db_base; 795 iov.iov_len = ra->ra_count; 796 } 797 798 uio.uio_iov = &iov; 799 uio.uio_iovcnt = 1; 800 uio.uio_segflg = UIO_SYSSPACE; 801 uio.uio_extflg = UIO_COPY_CACHED; 802 uio.uio_loffset = (offset_t)ra->ra_offset; 803 uio.uio_resid = ra->ra_count; 804 805 error = VOP_READ(vp, &uio, 0, cr, &ct); 806 807 if (error) { 808 if (mp) 809 freeb(mp); 810 811 /* 812 * check if a monitor detected a delegation conflict and 813 * mark as wouldblock so response is dropped 814 */ 815 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) 816 curthread->t_flag |= T_WOULDBLOCK; 817 else 818 rr->rr_status = puterrno(error); 819 820 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 821 if (in_crit) 822 nbl_end_crit(vp); 823 824 VN_RELE(vp); 825 rr->rr_data = NULL; 826 827 return; 828 } 829 830 /* 831 * Get attributes again so we can send the latest access 832 * time to the client side for his cache. 833 */ 834 va.va_mask = AT_ALL; 835 836 error = VOP_GETATTR(vp, &va, 0, cr, &ct); 837 838 if (error) { 839 if (mp) 840 freeb(mp); 841 842 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 843 if (in_crit) 844 nbl_end_crit(vp); 845 846 VN_RELE(vp); 847 rr->rr_data = NULL; 848 rr->rr_status = puterrno(error); 849 850 return; 851 } 852 853 rr->rr_count = (uint32_t)(ra->ra_count - uio.uio_resid); 854 855 if (mp) { 856 rr->rr_data = (char *)mp->b_datap->db_base; 857 } else { 858 if (ra->ra_wlist) { 859 rr->rr_data = (caddr_t)iov.iov_base; 860 if (!rdma_setup_read_data2(ra, rr)) { 861 rr->rr_data = NULL; 862 rr->rr_status = puterrno(NFSERR_INVAL); 863 } 864 } 865 } 866 done: 867 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct); 868 if (in_crit) 869 nbl_end_crit(vp); 870 871 acl_perm(vp, exi, &va, cr); 872 873 /* check for overflows */ 874 error = vattr_to_nattr(&va, &rr->rr_attr); 875 876 VN_RELE(vp); 877 878 rr->rr_status = puterrno(error); 879 } 880 881 /* 882 * Free data allocated by rfs_read 883 */ 884 void 885 rfs_rdfree(struct nfsrdresult *rr) 886 { 887 mblk_t *mp; 888 889 if (rr->rr_status == NFS_OK) { 890 mp = rr->rr_mp; 891 if (mp != NULL) 892 freeb(mp); 893 } 894 } 895 896 void * 897 rfs_read_getfh(struct nfsreadargs *ra) 898 { 899 return (&ra->ra_fhandle); 900 } 901 902 #define MAX_IOVECS 12 903 904 #ifdef DEBUG 905 static int rfs_write_sync_hits = 0; 906 static int rfs_write_sync_misses = 0; 907 #endif 908 909 /* 910 * Write data to file. 911 * Returns attributes of a file after writing some data to it. 912 * 913 * Any changes made here, especially in error handling might have 914 * to also be done in rfs_write (which clusters write requests). 915 */ 916 /* ARGSUSED */ 917 void 918 rfs_write_sync(struct nfswriteargs *wa, struct nfsattrstat *ns, 919 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 920 { 921 int error; 922 vnode_t *vp; 923 rlim64_t rlimit; 924 struct vattr va; 925 struct uio uio; 926 struct iovec iov[MAX_IOVECS]; 927 mblk_t *m; 928 struct iovec *iovp; 929 int iovcnt; 930 cred_t *savecred; 931 int in_crit = 0; 932 caller_context_t ct; 933 934 vp = nfs_fhtovp(&wa->wa_fhandle, exi); 935 if (vp == NULL) { 936 ns->ns_status = NFSERR_STALE; 937 return; 938 } 939 940 if (rdonly(ro, vp)) { 941 VN_RELE(vp); 942 ns->ns_status = NFSERR_ROFS; 943 return; 944 } 945 946 if (vp->v_type != VREG) { 947 VN_RELE(vp); 948 ns->ns_status = NFSERR_ISDIR; 949 return; 950 } 951 952 ct.cc_sysid = 0; 953 ct.cc_pid = 0; 954 ct.cc_caller_id = nfs2_srv_caller_id; 955 ct.cc_flags = CC_DONTBLOCK; 956 957 va.va_mask = AT_UID|AT_MODE; 958 959 error = VOP_GETATTR(vp, &va, 0, cr, &ct); 960 961 if (error) { 962 VN_RELE(vp); 963 ns->ns_status = puterrno(error); 964 965 return; 966 } 967 968 if (crgetuid(cr) != va.va_uid) { 969 /* 970 * This is a kludge to allow writes of files created 971 * with read only permission. The owner of the file 972 * is always allowed to write it. 973 */ 974 error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct); 975 976 if (error) { 977 VN_RELE(vp); 978 ns->ns_status = puterrno(error); 979 return; 980 } 981 } 982 983 /* 984 * Can't access a mandatory lock file. This might cause 985 * the NFS service thread to block forever waiting for a 986 * lock to be released that will never be released. 987 */ 988 if (MANDLOCK(vp, va.va_mode)) { 989 VN_RELE(vp); 990 ns->ns_status = NFSERR_ACCES; 991 return; 992 } 993 994 /* 995 * We have to enter the critical region before calling VOP_RWLOCK 996 * to avoid a deadlock with ufs. 997 */ 998 if (nbl_need_check(vp)) { 999 nbl_start_crit(vp, RW_READER); 1000 in_crit = 1; 1001 if (nbl_conflict(vp, NBL_WRITE, wa->wa_offset, 1002 wa->wa_count, 0, NULL)) { 1003 error = EACCES; 1004 goto out; 1005 } 1006 } 1007 1008 error = VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &ct); 1009 1010 /* check if a monitor detected a delegation conflict */ 1011 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 1012 VN_RELE(vp); 1013 /* mark as wouldblock so response is dropped */ 1014 curthread->t_flag |= T_WOULDBLOCK; 1015 return; 1016 } 1017 1018 if (wa->wa_data || wa->wa_rlist) { 1019 /* Do the RDMA thing if necessary */ 1020 if (wa->wa_rlist) { 1021 iov[0].iov_base = (char *)((wa->wa_rlist)->u.c_daddr3); 1022 iov[0].iov_len = wa->wa_count; 1023 } else { 1024 iov[0].iov_base = wa->wa_data; 1025 iov[0].iov_len = wa->wa_count; 1026 } 1027 uio.uio_iov = iov; 1028 uio.uio_iovcnt = 1; 1029 uio.uio_segflg = UIO_SYSSPACE; 1030 uio.uio_extflg = UIO_COPY_DEFAULT; 1031 uio.uio_loffset = (offset_t)wa->wa_offset; 1032 uio.uio_resid = wa->wa_count; 1033 /* 1034 * The limit is checked on the client. We 1035 * should allow any size writes here. 1036 */ 1037 uio.uio_llimit = curproc->p_fsz_ctl; 1038 rlimit = uio.uio_llimit - wa->wa_offset; 1039 if (rlimit < (rlim64_t)uio.uio_resid) 1040 uio.uio_resid = (uint_t)rlimit; 1041 1042 /* 1043 * for now we assume no append mode 1044 */ 1045 /* 1046 * We're changing creds because VM may fault and we need 1047 * the cred of the current thread to be used if quota 1048 * checking is enabled. 1049 */ 1050 savecred = curthread->t_cred; 1051 curthread->t_cred = cr; 1052 error = VOP_WRITE(vp, &uio, FSYNC, cr, &ct); 1053 curthread->t_cred = savecred; 1054 } else { 1055 iovcnt = 0; 1056 for (m = wa->wa_mblk; m != NULL; m = m->b_cont) 1057 iovcnt++; 1058 if (iovcnt <= MAX_IOVECS) { 1059 #ifdef DEBUG 1060 rfs_write_sync_hits++; 1061 #endif 1062 iovp = iov; 1063 } else { 1064 #ifdef DEBUG 1065 rfs_write_sync_misses++; 1066 #endif 1067 iovp = kmem_alloc(sizeof (*iovp) * iovcnt, KM_SLEEP); 1068 } 1069 mblk_to_iov(wa->wa_mblk, iovcnt, iovp); 1070 uio.uio_iov = iovp; 1071 uio.uio_iovcnt = iovcnt; 1072 uio.uio_segflg = UIO_SYSSPACE; 1073 uio.uio_extflg = UIO_COPY_DEFAULT; 1074 uio.uio_loffset = (offset_t)wa->wa_offset; 1075 uio.uio_resid = wa->wa_count; 1076 /* 1077 * The limit is checked on the client. We 1078 * should allow any size writes here. 1079 */ 1080 uio.uio_llimit = curproc->p_fsz_ctl; 1081 rlimit = uio.uio_llimit - wa->wa_offset; 1082 if (rlimit < (rlim64_t)uio.uio_resid) 1083 uio.uio_resid = (uint_t)rlimit; 1084 1085 /* 1086 * For now we assume no append mode. 1087 */ 1088 /* 1089 * We're changing creds because VM may fault and we need 1090 * the cred of the current thread to be used if quota 1091 * checking is enabled. 1092 */ 1093 savecred = curthread->t_cred; 1094 curthread->t_cred = cr; 1095 error = VOP_WRITE(vp, &uio, FSYNC, cr, &ct); 1096 curthread->t_cred = savecred; 1097 1098 if (iovp != iov) 1099 kmem_free(iovp, sizeof (*iovp) * iovcnt); 1100 } 1101 1102 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct); 1103 1104 if (!error) { 1105 /* 1106 * Get attributes again so we send the latest mod 1107 * time to the client side for his cache. 1108 */ 1109 va.va_mask = AT_ALL; /* now we want everything */ 1110 1111 error = VOP_GETATTR(vp, &va, 0, cr, &ct); 1112 1113 /* check for overflows */ 1114 if (!error) { 1115 acl_perm(vp, exi, &va, cr); 1116 error = vattr_to_nattr(&va, &ns->ns_attr); 1117 } 1118 } 1119 1120 out: 1121 if (in_crit) 1122 nbl_end_crit(vp); 1123 VN_RELE(vp); 1124 1125 /* check if a monitor detected a delegation conflict */ 1126 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) 1127 /* mark as wouldblock so response is dropped */ 1128 curthread->t_flag |= T_WOULDBLOCK; 1129 else 1130 ns->ns_status = puterrno(error); 1131 1132 } 1133 1134 struct rfs_async_write { 1135 struct nfswriteargs *wa; 1136 struct nfsattrstat *ns; 1137 struct svc_req *req; 1138 cred_t *cr; 1139 bool_t ro; 1140 kthread_t *thread; 1141 struct rfs_async_write *list; 1142 }; 1143 1144 struct rfs_async_write_list { 1145 fhandle_t *fhp; 1146 kcondvar_t cv; 1147 struct rfs_async_write *list; 1148 struct rfs_async_write_list *next; 1149 }; 1150 1151 static struct rfs_async_write_list *rfs_async_write_head = NULL; 1152 static kmutex_t rfs_async_write_lock; 1153 static int rfs_write_async = 1; /* enables write clustering if == 1 */ 1154 1155 #define MAXCLIOVECS 42 1156 #define RFSWRITE_INITVAL (enum nfsstat) -1 1157 1158 #ifdef DEBUG 1159 static int rfs_write_hits = 0; 1160 static int rfs_write_misses = 0; 1161 #endif 1162 1163 /* 1164 * Write data to file. 1165 * Returns attributes of a file after writing some data to it. 1166 */ 1167 void 1168 rfs_write(struct nfswriteargs *wa, struct nfsattrstat *ns, 1169 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 1170 { 1171 int error; 1172 vnode_t *vp; 1173 rlim64_t rlimit; 1174 struct vattr va; 1175 struct uio uio; 1176 struct rfs_async_write_list *lp; 1177 struct rfs_async_write_list *nlp; 1178 struct rfs_async_write *rp; 1179 struct rfs_async_write *nrp; 1180 struct rfs_async_write *trp; 1181 struct rfs_async_write *lrp; 1182 int data_written; 1183 int iovcnt; 1184 mblk_t *m; 1185 struct iovec *iovp; 1186 struct iovec *niovp; 1187 struct iovec iov[MAXCLIOVECS]; 1188 int count; 1189 int rcount; 1190 uint_t off; 1191 uint_t len; 1192 struct rfs_async_write nrpsp; 1193 struct rfs_async_write_list nlpsp; 1194 ushort_t t_flag; 1195 cred_t *savecred; 1196 int in_crit = 0; 1197 caller_context_t ct; 1198 1199 if (!rfs_write_async) { 1200 rfs_write_sync(wa, ns, exi, req, cr, ro); 1201 return; 1202 } 1203 1204 /* 1205 * Initialize status to RFSWRITE_INITVAL instead of 0, since value of 0 1206 * is considered an OK. 1207 */ 1208 ns->ns_status = RFSWRITE_INITVAL; 1209 1210 nrp = &nrpsp; 1211 nrp->wa = wa; 1212 nrp->ns = ns; 1213 nrp->req = req; 1214 nrp->cr = cr; 1215 nrp->ro = ro; 1216 nrp->thread = curthread; 1217 1218 ASSERT(curthread->t_schedflag & TS_DONT_SWAP); 1219 1220 /* 1221 * Look to see if there is already a cluster started 1222 * for this file. 1223 */ 1224 mutex_enter(&rfs_async_write_lock); 1225 for (lp = rfs_async_write_head; lp != NULL; lp = lp->next) { 1226 if (bcmp(&wa->wa_fhandle, lp->fhp, 1227 sizeof (fhandle_t)) == 0) 1228 break; 1229 } 1230 1231 /* 1232 * If lp is non-NULL, then there is already a cluster 1233 * started. We need to place ourselves in the cluster 1234 * list in the right place as determined by starting 1235 * offset. Conflicts with non-blocking mandatory locked 1236 * regions will be checked when the cluster is processed. 1237 */ 1238 if (lp != NULL) { 1239 rp = lp->list; 1240 trp = NULL; 1241 while (rp != NULL && rp->wa->wa_offset < wa->wa_offset) { 1242 trp = rp; 1243 rp = rp->list; 1244 } 1245 nrp->list = rp; 1246 if (trp == NULL) 1247 lp->list = nrp; 1248 else 1249 trp->list = nrp; 1250 while (nrp->ns->ns_status == RFSWRITE_INITVAL) 1251 cv_wait(&lp->cv, &rfs_async_write_lock); 1252 mutex_exit(&rfs_async_write_lock); 1253 1254 return; 1255 } 1256 1257 /* 1258 * No cluster started yet, start one and add ourselves 1259 * to the list of clusters. 1260 */ 1261 nrp->list = NULL; 1262 1263 nlp = &nlpsp; 1264 nlp->fhp = &wa->wa_fhandle; 1265 cv_init(&nlp->cv, NULL, CV_DEFAULT, NULL); 1266 nlp->list = nrp; 1267 nlp->next = NULL; 1268 1269 if (rfs_async_write_head == NULL) { 1270 rfs_async_write_head = nlp; 1271 } else { 1272 lp = rfs_async_write_head; 1273 while (lp->next != NULL) 1274 lp = lp->next; 1275 lp->next = nlp; 1276 } 1277 mutex_exit(&rfs_async_write_lock); 1278 1279 /* 1280 * Convert the file handle common to all of the requests 1281 * in this cluster to a vnode. 1282 */ 1283 vp = nfs_fhtovp(&wa->wa_fhandle, exi); 1284 if (vp == NULL) { 1285 mutex_enter(&rfs_async_write_lock); 1286 if (rfs_async_write_head == nlp) 1287 rfs_async_write_head = nlp->next; 1288 else { 1289 lp = rfs_async_write_head; 1290 while (lp->next != nlp) 1291 lp = lp->next; 1292 lp->next = nlp->next; 1293 } 1294 t_flag = curthread->t_flag & T_WOULDBLOCK; 1295 for (rp = nlp->list; rp != NULL; rp = rp->list) { 1296 rp->ns->ns_status = NFSERR_STALE; 1297 rp->thread->t_flag |= t_flag; 1298 } 1299 cv_broadcast(&nlp->cv); 1300 mutex_exit(&rfs_async_write_lock); 1301 1302 return; 1303 } 1304 1305 /* 1306 * Can only write regular files. Attempts to write any 1307 * other file types fail with EISDIR. 1308 */ 1309 if (vp->v_type != VREG) { 1310 VN_RELE(vp); 1311 mutex_enter(&rfs_async_write_lock); 1312 if (rfs_async_write_head == nlp) 1313 rfs_async_write_head = nlp->next; 1314 else { 1315 lp = rfs_async_write_head; 1316 while (lp->next != nlp) 1317 lp = lp->next; 1318 lp->next = nlp->next; 1319 } 1320 t_flag = curthread->t_flag & T_WOULDBLOCK; 1321 for (rp = nlp->list; rp != NULL; rp = rp->list) { 1322 rp->ns->ns_status = NFSERR_ISDIR; 1323 rp->thread->t_flag |= t_flag; 1324 } 1325 cv_broadcast(&nlp->cv); 1326 mutex_exit(&rfs_async_write_lock); 1327 1328 return; 1329 } 1330 1331 /* 1332 * Enter the critical region before calling VOP_RWLOCK, to avoid a 1333 * deadlock with ufs. 1334 */ 1335 if (nbl_need_check(vp)) { 1336 nbl_start_crit(vp, RW_READER); 1337 in_crit = 1; 1338 } 1339 1340 ct.cc_sysid = 0; 1341 ct.cc_pid = 0; 1342 ct.cc_caller_id = nfs2_srv_caller_id; 1343 ct.cc_flags = CC_DONTBLOCK; 1344 1345 /* 1346 * Lock the file for writing. This operation provides 1347 * the delay which allows clusters to grow. 1348 */ 1349 error = VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &ct); 1350 1351 /* check if a monitor detected a delegation conflict */ 1352 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) { 1353 if (in_crit) 1354 nbl_end_crit(vp); 1355 VN_RELE(vp); 1356 /* mark as wouldblock so response is dropped */ 1357 curthread->t_flag |= T_WOULDBLOCK; 1358 mutex_enter(&rfs_async_write_lock); 1359 if (rfs_async_write_head == nlp) 1360 rfs_async_write_head = nlp->next; 1361 else { 1362 lp = rfs_async_write_head; 1363 while (lp->next != nlp) 1364 lp = lp->next; 1365 lp->next = nlp->next; 1366 } 1367 for (rp = nlp->list; rp != NULL; rp = rp->list) { 1368 if (rp->ns->ns_status == RFSWRITE_INITVAL) { 1369 rp->ns->ns_status = puterrno(error); 1370 rp->thread->t_flag |= T_WOULDBLOCK; 1371 } 1372 } 1373 cv_broadcast(&nlp->cv); 1374 mutex_exit(&rfs_async_write_lock); 1375 1376 return; 1377 } 1378 1379 /* 1380 * Disconnect this cluster from the list of clusters. 1381 * The cluster that is being dealt with must be fixed 1382 * in size after this point, so there is no reason 1383 * to leave it on the list so that new requests can 1384 * find it. 1385 * 1386 * The algorithm is that the first write request will 1387 * create a cluster, convert the file handle to a 1388 * vnode pointer, and then lock the file for writing. 1389 * This request is not likely to be clustered with 1390 * any others. However, the next request will create 1391 * a new cluster and be blocked in VOP_RWLOCK while 1392 * the first request is being processed. This delay 1393 * will allow more requests to be clustered in this 1394 * second cluster. 1395 */ 1396 mutex_enter(&rfs_async_write_lock); 1397 if (rfs_async_write_head == nlp) 1398 rfs_async_write_head = nlp->next; 1399 else { 1400 lp = rfs_async_write_head; 1401 while (lp->next != nlp) 1402 lp = lp->next; 1403 lp->next = nlp->next; 1404 } 1405 mutex_exit(&rfs_async_write_lock); 1406 1407 /* 1408 * Step through the list of requests in this cluster. 1409 * We need to check permissions to make sure that all 1410 * of the requests have sufficient permission to write 1411 * the file. A cluster can be composed of requests 1412 * from different clients and different users on each 1413 * client. 1414 * 1415 * As a side effect, we also calculate the size of the 1416 * byte range that this cluster encompasses. 1417 */ 1418 rp = nlp->list; 1419 off = rp->wa->wa_offset; 1420 len = (uint_t)0; 1421 do { 1422 if (rdonly(rp->ro, vp)) { 1423 rp->ns->ns_status = NFSERR_ROFS; 1424 t_flag = curthread->t_flag & T_WOULDBLOCK; 1425 rp->thread->t_flag |= t_flag; 1426 continue; 1427 } 1428 1429 va.va_mask = AT_UID|AT_MODE; 1430 1431 error = VOP_GETATTR(vp, &va, 0, rp->cr, &ct); 1432 1433 if (!error) { 1434 if (crgetuid(rp->cr) != va.va_uid) { 1435 /* 1436 * This is a kludge to allow writes of files 1437 * created with read only permission. The 1438 * owner of the file is always allowed to 1439 * write it. 1440 */ 1441 error = VOP_ACCESS(vp, VWRITE, 0, rp->cr, &ct); 1442 } 1443 if (!error && MANDLOCK(vp, va.va_mode)) 1444 error = EACCES; 1445 } 1446 1447 /* 1448 * Check for a conflict with a nbmand-locked region. 1449 */ 1450 if (in_crit && nbl_conflict(vp, NBL_WRITE, rp->wa->wa_offset, 1451 rp->wa->wa_count, 0, NULL)) { 1452 error = EACCES; 1453 } 1454 1455 if (error) { 1456 rp->ns->ns_status = puterrno(error); 1457 t_flag = curthread->t_flag & T_WOULDBLOCK; 1458 rp->thread->t_flag |= t_flag; 1459 continue; 1460 } 1461 if (len < rp->wa->wa_offset + rp->wa->wa_count - off) 1462 len = rp->wa->wa_offset + rp->wa->wa_count - off; 1463 } while ((rp = rp->list) != NULL); 1464 1465 /* 1466 * Step through the cluster attempting to gather as many 1467 * requests which are contiguous as possible. These 1468 * contiguous requests are handled via one call to VOP_WRITE 1469 * instead of different calls to VOP_WRITE. We also keep 1470 * track of the fact that any data was written. 1471 */ 1472 rp = nlp->list; 1473 data_written = 0; 1474 do { 1475 /* 1476 * Skip any requests which are already marked as having an 1477 * error. 1478 */ 1479 if (rp->ns->ns_status != RFSWRITE_INITVAL) { 1480 rp = rp->list; 1481 continue; 1482 } 1483 1484 /* 1485 * Count the number of iovec's which are required 1486 * to handle this set of requests. One iovec is 1487 * needed for each data buffer, whether addressed 1488 * by wa_data or by the b_rptr pointers in the 1489 * mblk chains. 1490 */ 1491 iovcnt = 0; 1492 lrp = rp; 1493 for (;;) { 1494 if (lrp->wa->wa_data || lrp->wa->wa_rlist) 1495 iovcnt++; 1496 else { 1497 m = lrp->wa->wa_mblk; 1498 while (m != NULL) { 1499 iovcnt++; 1500 m = m->b_cont; 1501 } 1502 } 1503 if (lrp->list == NULL || 1504 lrp->list->ns->ns_status != RFSWRITE_INITVAL || 1505 lrp->wa->wa_offset + lrp->wa->wa_count != 1506 lrp->list->wa->wa_offset) { 1507 lrp = lrp->list; 1508 break; 1509 } 1510 lrp = lrp->list; 1511 } 1512 1513 if (iovcnt <= MAXCLIOVECS) { 1514 #ifdef DEBUG 1515 rfs_write_hits++; 1516 #endif 1517 niovp = iov; 1518 } else { 1519 #ifdef DEBUG 1520 rfs_write_misses++; 1521 #endif 1522 niovp = kmem_alloc(sizeof (*niovp) * iovcnt, KM_SLEEP); 1523 } 1524 /* 1525 * Put together the scatter/gather iovecs. 1526 */ 1527 iovp = niovp; 1528 trp = rp; 1529 count = 0; 1530 do { 1531 if (trp->wa->wa_data || trp->wa->wa_rlist) { 1532 if (trp->wa->wa_rlist) { 1533 iovp->iov_base = 1534 (char *)((trp->wa->wa_rlist)-> 1535 u.c_daddr3); 1536 iovp->iov_len = trp->wa->wa_count; 1537 } else { 1538 iovp->iov_base = trp->wa->wa_data; 1539 iovp->iov_len = trp->wa->wa_count; 1540 } 1541 iovp++; 1542 } else { 1543 m = trp->wa->wa_mblk; 1544 rcount = trp->wa->wa_count; 1545 while (m != NULL) { 1546 iovp->iov_base = (caddr_t)m->b_rptr; 1547 iovp->iov_len = (m->b_wptr - m->b_rptr); 1548 rcount -= iovp->iov_len; 1549 if (rcount < 0) 1550 iovp->iov_len += rcount; 1551 iovp++; 1552 if (rcount <= 0) 1553 break; 1554 m = m->b_cont; 1555 } 1556 } 1557 count += trp->wa->wa_count; 1558 trp = trp->list; 1559 } while (trp != lrp); 1560 1561 uio.uio_iov = niovp; 1562 uio.uio_iovcnt = iovcnt; 1563 uio.uio_segflg = UIO_SYSSPACE; 1564 uio.uio_extflg = UIO_COPY_DEFAULT; 1565 uio.uio_loffset = (offset_t)rp->wa->wa_offset; 1566 uio.uio_resid = count; 1567 /* 1568 * The limit is checked on the client. We 1569 * should allow any size writes here. 1570 */ 1571 uio.uio_llimit = curproc->p_fsz_ctl; 1572 rlimit = uio.uio_llimit - rp->wa->wa_offset; 1573 if (rlimit < (rlim64_t)uio.uio_resid) 1574 uio.uio_resid = (uint_t)rlimit; 1575 1576 /* 1577 * For now we assume no append mode. 1578 */ 1579 1580 /* 1581 * We're changing creds because VM may fault 1582 * and we need the cred of the current 1583 * thread to be used if quota * checking is 1584 * enabled. 1585 */ 1586 savecred = curthread->t_cred; 1587 curthread->t_cred = cr; 1588 error = VOP_WRITE(vp, &uio, 0, rp->cr, &ct); 1589 curthread->t_cred = savecred; 1590 1591 /* check if a monitor detected a delegation conflict */ 1592 if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) 1593 /* mark as wouldblock so response is dropped */ 1594 curthread->t_flag |= T_WOULDBLOCK; 1595 1596 if (niovp != iov) 1597 kmem_free(niovp, sizeof (*niovp) * iovcnt); 1598 1599 if (!error) { 1600 data_written = 1; 1601 /* 1602 * Get attributes again so we send the latest mod 1603 * time to the client side for his cache. 1604 */ 1605 va.va_mask = AT_ALL; /* now we want everything */ 1606 1607 error = VOP_GETATTR(vp, &va, 0, rp->cr, &ct); 1608 1609 if (!error) 1610 acl_perm(vp, exi, &va, rp->cr); 1611 } 1612 1613 /* 1614 * Fill in the status responses for each request 1615 * which was just handled. Also, copy the latest 1616 * attributes in to the attribute responses if 1617 * appropriate. 1618 */ 1619 t_flag = curthread->t_flag & T_WOULDBLOCK; 1620 do { 1621 rp->thread->t_flag |= t_flag; 1622 /* check for overflows */ 1623 if (!error) { 1624 error = vattr_to_nattr(&va, &rp->ns->ns_attr); 1625 } 1626 rp->ns->ns_status = puterrno(error); 1627 rp = rp->list; 1628 } while (rp != lrp); 1629 } while (rp != NULL); 1630 1631 /* 1632 * If any data was written at all, then we need to flush 1633 * the data and metadata to stable storage. 1634 */ 1635 if (data_written) { 1636 error = VOP_PUTPAGE(vp, (u_offset_t)off, len, 0, cr, &ct); 1637 1638 if (!error) { 1639 error = VOP_FSYNC(vp, FNODSYNC, cr, &ct); 1640 } 1641 } 1642 1643 VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct); 1644 1645 if (in_crit) 1646 nbl_end_crit(vp); 1647 VN_RELE(vp); 1648 1649 t_flag = curthread->t_flag & T_WOULDBLOCK; 1650 mutex_enter(&rfs_async_write_lock); 1651 for (rp = nlp->list; rp != NULL; rp = rp->list) { 1652 if (rp->ns->ns_status == RFSWRITE_INITVAL) { 1653 rp->ns->ns_status = puterrno(error); 1654 rp->thread->t_flag |= t_flag; 1655 } 1656 } 1657 cv_broadcast(&nlp->cv); 1658 mutex_exit(&rfs_async_write_lock); 1659 1660 } 1661 1662 void * 1663 rfs_write_getfh(struct nfswriteargs *wa) 1664 { 1665 return (&wa->wa_fhandle); 1666 } 1667 1668 /* 1669 * Create a file. 1670 * Creates a file with given attributes and returns those attributes 1671 * and an fhandle for the new file. 1672 */ 1673 void 1674 rfs_create(struct nfscreatargs *args, struct nfsdiropres *dr, 1675 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 1676 { 1677 int error; 1678 int lookuperr; 1679 int in_crit = 0; 1680 struct vattr va; 1681 vnode_t *vp; 1682 vnode_t *realvp; 1683 vnode_t *dvp; 1684 char *name = args->ca_da.da_name; 1685 vnode_t *tvp = NULL; 1686 int mode; 1687 int lookup_ok; 1688 bool_t trunc; 1689 struct sockaddr *ca; 1690 1691 /* 1692 * Disallow NULL paths 1693 */ 1694 if (name == NULL || *name == '\0') { 1695 dr->dr_status = NFSERR_ACCES; 1696 return; 1697 } 1698 1699 dvp = nfs_fhtovp(args->ca_da.da_fhandle, exi); 1700 if (dvp == NULL) { 1701 dr->dr_status = NFSERR_STALE; 1702 return; 1703 } 1704 1705 error = sattr_to_vattr(args->ca_sa, &va); 1706 if (error) { 1707 dr->dr_status = puterrno(error); 1708 return; 1709 } 1710 1711 /* 1712 * Must specify the mode. 1713 */ 1714 if (!(va.va_mask & AT_MODE)) { 1715 VN_RELE(dvp); 1716 dr->dr_status = NFSERR_INVAL; 1717 return; 1718 } 1719 1720 /* 1721 * This is a completely gross hack to make mknod 1722 * work over the wire until we can wack the protocol 1723 */ 1724 if ((va.va_mode & IFMT) == IFCHR) { 1725 if (args->ca_sa->sa_size == (uint_t)NFS_FIFO_DEV) 1726 va.va_type = VFIFO; /* xtra kludge for named pipe */ 1727 else { 1728 va.va_type = VCHR; 1729 /* 1730 * uncompress the received dev_t 1731 * if the top half is zero indicating a request 1732 * from an `older style' OS. 1733 */ 1734 if ((va.va_size & 0xffff0000) == 0) 1735 va.va_rdev = nfsv2_expdev(va.va_size); 1736 else 1737 va.va_rdev = (dev_t)va.va_size; 1738 } 1739 va.va_mask &= ~AT_SIZE; 1740 } else if ((va.va_mode & IFMT) == IFBLK) { 1741 va.va_type = VBLK; 1742 /* 1743 * uncompress the received dev_t 1744 * if the top half is zero indicating a request 1745 * from an `older style' OS. 1746 */ 1747 if ((va.va_size & 0xffff0000) == 0) 1748 va.va_rdev = nfsv2_expdev(va.va_size); 1749 else 1750 va.va_rdev = (dev_t)va.va_size; 1751 va.va_mask &= ~AT_SIZE; 1752 } else if ((va.va_mode & IFMT) == IFSOCK) { 1753 va.va_type = VSOCK; 1754 } else { 1755 va.va_type = VREG; 1756 } 1757 va.va_mode &= ~IFMT; 1758 va.va_mask |= AT_TYPE; 1759 1760 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 1761 name = nfscmd_convname(ca, exi, name, NFSCMD_CONV_INBOUND, 1762 MAXPATHLEN); 1763 if (name == NULL) { 1764 dr->dr_status = puterrno(EINVAL); 1765 return; 1766 } 1767 1768 /* 1769 * Why was the choice made to use VWRITE as the mode to the 1770 * call to VOP_CREATE ? This results in a bug. When a client 1771 * opens a file that already exists and is RDONLY, the second 1772 * open fails with an EACESS because of the mode. 1773 * bug ID 1054648. 1774 */ 1775 lookup_ok = 0; 1776 mode = VWRITE; 1777 if (!(va.va_mask & AT_SIZE) || va.va_type != VREG) { 1778 error = VOP_LOOKUP(dvp, name, &tvp, NULL, 0, NULL, cr, 1779 NULL, NULL, NULL); 1780 if (!error) { 1781 struct vattr at; 1782 1783 lookup_ok = 1; 1784 at.va_mask = AT_MODE; 1785 error = VOP_GETATTR(tvp, &at, 0, cr, NULL); 1786 if (!error) 1787 mode = (at.va_mode & S_IWUSR) ? VWRITE : VREAD; 1788 VN_RELE(tvp); 1789 tvp = NULL; 1790 } 1791 } 1792 1793 if (!lookup_ok) { 1794 if (rdonly(ro, dvp)) { 1795 error = EROFS; 1796 } else if (va.va_type != VREG && va.va_type != VFIFO && 1797 va.va_type != VSOCK && secpolicy_sys_devices(cr) != 0) { 1798 error = EPERM; 1799 } else { 1800 error = 0; 1801 } 1802 } 1803 1804 /* 1805 * If file size is being modified on an already existing file 1806 * make sure that there are no conflicting non-blocking mandatory 1807 * locks in the region being manipulated. Return EACCES if there 1808 * are conflicting locks. 1809 */ 1810 if (!error && (va.va_type == VREG) && (va.va_mask & AT_SIZE)) { 1811 lookuperr = VOP_LOOKUP(dvp, name, &tvp, NULL, 0, NULL, cr, 1812 NULL, NULL, NULL); 1813 1814 if (!lookuperr && 1815 rfs4_check_delegated(FWRITE, tvp, va.va_size == 0)) { 1816 VN_RELE(tvp); 1817 curthread->t_flag |= T_WOULDBLOCK; 1818 goto out; 1819 } 1820 1821 if (!lookuperr && nbl_need_check(tvp)) { 1822 /* 1823 * The file exists. Now check if it has any 1824 * conflicting non-blocking mandatory locks 1825 * in the region being changed. 1826 */ 1827 struct vattr bva; 1828 u_offset_t offset; 1829 ssize_t length; 1830 1831 nbl_start_crit(tvp, RW_READER); 1832 in_crit = 1; 1833 1834 bva.va_mask = AT_SIZE; 1835 error = VOP_GETATTR(tvp, &bva, 0, cr, NULL); 1836 if (!error) { 1837 if (va.va_size < bva.va_size) { 1838 offset = va.va_size; 1839 length = bva.va_size - va.va_size; 1840 } else { 1841 offset = bva.va_size; 1842 length = va.va_size - bva.va_size; 1843 } 1844 if (length) { 1845 if (nbl_conflict(tvp, NBL_WRITE, 1846 offset, length, 0, NULL)) { 1847 error = EACCES; 1848 } 1849 } 1850 } 1851 if (error) { 1852 nbl_end_crit(tvp); 1853 VN_RELE(tvp); 1854 in_crit = 0; 1855 } 1856 } else if (tvp != NULL) { 1857 VN_RELE(tvp); 1858 } 1859 } 1860 1861 if (!error) { 1862 /* 1863 * If filesystem is shared with nosuid the remove any 1864 * setuid/setgid bits on create. 1865 */ 1866 if (va.va_type == VREG && 1867 exi->exi_export.ex_flags & EX_NOSUID) 1868 va.va_mode &= ~(VSUID | VSGID); 1869 1870 error = VOP_CREATE(dvp, name, &va, NONEXCL, mode, &vp, cr, 0, 1871 NULL, NULL); 1872 1873 if (!error) { 1874 1875 if ((va.va_mask & AT_SIZE) && (va.va_size == 0)) 1876 trunc = TRUE; 1877 else 1878 trunc = FALSE; 1879 1880 if (rfs4_check_delegated(FWRITE, vp, trunc)) { 1881 VN_RELE(vp); 1882 curthread->t_flag |= T_WOULDBLOCK; 1883 goto out; 1884 } 1885 va.va_mask = AT_ALL; 1886 1887 error = VOP_GETATTR(vp, &va, 0, cr, NULL); 1888 1889 /* check for overflows */ 1890 if (!error) { 1891 acl_perm(vp, exi, &va, cr); 1892 error = vattr_to_nattr(&va, &dr->dr_attr); 1893 if (!error) { 1894 error = makefh(&dr->dr_fhandle, vp, 1895 exi); 1896 } 1897 } 1898 /* 1899 * Force modified metadata out to stable storage. 1900 * 1901 * if a underlying vp exists, pass it to VOP_FSYNC 1902 */ 1903 if (VOP_REALVP(vp, &realvp, NULL) == 0) 1904 (void) VOP_FSYNC(realvp, FNODSYNC, cr, NULL); 1905 else 1906 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL); 1907 VN_RELE(vp); 1908 } 1909 1910 if (in_crit) { 1911 nbl_end_crit(tvp); 1912 VN_RELE(tvp); 1913 } 1914 } 1915 1916 /* 1917 * Force modified data and metadata out to stable storage. 1918 */ 1919 (void) VOP_FSYNC(dvp, 0, cr, NULL); 1920 1921 out: 1922 1923 VN_RELE(dvp); 1924 1925 dr->dr_status = puterrno(error); 1926 1927 if (name != args->ca_da.da_name) 1928 kmem_free(name, MAXPATHLEN); 1929 } 1930 void * 1931 rfs_create_getfh(struct nfscreatargs *args) 1932 { 1933 return (args->ca_da.da_fhandle); 1934 } 1935 1936 /* 1937 * Remove a file. 1938 * Remove named file from parent directory. 1939 */ 1940 /* ARGSUSED */ 1941 void 1942 rfs_remove(struct nfsdiropargs *da, enum nfsstat *status, 1943 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 1944 { 1945 int error = 0; 1946 vnode_t *vp; 1947 vnode_t *targvp; 1948 int in_crit = 0; 1949 1950 /* 1951 * Disallow NULL paths 1952 */ 1953 if (da->da_name == NULL || *da->da_name == '\0') { 1954 *status = NFSERR_ACCES; 1955 return; 1956 } 1957 1958 vp = nfs_fhtovp(da->da_fhandle, exi); 1959 if (vp == NULL) { 1960 *status = NFSERR_STALE; 1961 return; 1962 } 1963 1964 if (rdonly(ro, vp)) { 1965 VN_RELE(vp); 1966 *status = NFSERR_ROFS; 1967 return; 1968 } 1969 1970 /* 1971 * Check for a conflict with a non-blocking mandatory share reservation. 1972 */ 1973 error = VOP_LOOKUP(vp, da->da_name, &targvp, NULL, 0, 1974 NULL, cr, NULL, NULL, NULL); 1975 if (error != 0) { 1976 VN_RELE(vp); 1977 *status = puterrno(error); 1978 return; 1979 } 1980 1981 /* 1982 * If the file is delegated to an v4 client, then initiate 1983 * recall and drop this request (by setting T_WOULDBLOCK). 1984 * The client will eventually re-transmit the request and 1985 * (hopefully), by then, the v4 client will have returned 1986 * the delegation. 1987 */ 1988 1989 if (rfs4_check_delegated(FWRITE, targvp, TRUE)) { 1990 VN_RELE(vp); 1991 VN_RELE(targvp); 1992 curthread->t_flag |= T_WOULDBLOCK; 1993 return; 1994 } 1995 1996 if (nbl_need_check(targvp)) { 1997 nbl_start_crit(targvp, RW_READER); 1998 in_crit = 1; 1999 if (nbl_conflict(targvp, NBL_REMOVE, 0, 0, 0, NULL)) { 2000 error = EACCES; 2001 goto out; 2002 } 2003 } 2004 2005 error = VOP_REMOVE(vp, da->da_name, cr, NULL, 0); 2006 2007 /* 2008 * Force modified data and metadata out to stable storage. 2009 */ 2010 (void) VOP_FSYNC(vp, 0, cr, NULL); 2011 2012 out: 2013 if (in_crit) 2014 nbl_end_crit(targvp); 2015 VN_RELE(targvp); 2016 VN_RELE(vp); 2017 2018 *status = puterrno(error); 2019 2020 } 2021 2022 void * 2023 rfs_remove_getfh(struct nfsdiropargs *da) 2024 { 2025 return (da->da_fhandle); 2026 } 2027 2028 /* 2029 * rename a file 2030 * Give a file (from) a new name (to). 2031 */ 2032 /* ARGSUSED */ 2033 void 2034 rfs_rename(struct nfsrnmargs *args, enum nfsstat *status, 2035 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 2036 { 2037 int error = 0; 2038 vnode_t *fromvp; 2039 vnode_t *tovp; 2040 struct exportinfo *to_exi; 2041 fhandle_t *fh; 2042 vnode_t *srcvp; 2043 vnode_t *targvp; 2044 int in_crit = 0; 2045 2046 fromvp = nfs_fhtovp(args->rna_from.da_fhandle, exi); 2047 if (fromvp == NULL) { 2048 *status = NFSERR_STALE; 2049 return; 2050 } 2051 2052 fh = args->rna_to.da_fhandle; 2053 to_exi = checkexport(&fh->fh_fsid, (fid_t *)&fh->fh_xlen); 2054 if (to_exi == NULL) { 2055 VN_RELE(fromvp); 2056 *status = NFSERR_ACCES; 2057 return; 2058 } 2059 exi_rele(to_exi); 2060 2061 if (to_exi != exi) { 2062 VN_RELE(fromvp); 2063 *status = NFSERR_XDEV; 2064 return; 2065 } 2066 2067 tovp = nfs_fhtovp(args->rna_to.da_fhandle, exi); 2068 if (tovp == NULL) { 2069 VN_RELE(fromvp); 2070 *status = NFSERR_STALE; 2071 return; 2072 } 2073 2074 if (fromvp->v_type != VDIR || tovp->v_type != VDIR) { 2075 VN_RELE(tovp); 2076 VN_RELE(fromvp); 2077 *status = NFSERR_NOTDIR; 2078 return; 2079 } 2080 2081 /* 2082 * Disallow NULL paths 2083 */ 2084 if (args->rna_from.da_name == NULL || *args->rna_from.da_name == '\0' || 2085 args->rna_to.da_name == NULL || *args->rna_to.da_name == '\0') { 2086 VN_RELE(tovp); 2087 VN_RELE(fromvp); 2088 *status = NFSERR_ACCES; 2089 return; 2090 } 2091 2092 if (rdonly(ro, tovp)) { 2093 VN_RELE(tovp); 2094 VN_RELE(fromvp); 2095 *status = NFSERR_ROFS; 2096 return; 2097 } 2098 2099 /* 2100 * Check for a conflict with a non-blocking mandatory share reservation. 2101 */ 2102 error = VOP_LOOKUP(fromvp, args->rna_from.da_name, &srcvp, NULL, 0, 2103 NULL, cr, NULL, NULL, NULL); 2104 if (error != 0) { 2105 VN_RELE(tovp); 2106 VN_RELE(fromvp); 2107 *status = puterrno(error); 2108 return; 2109 } 2110 2111 /* Check for delegations on the source file */ 2112 2113 if (rfs4_check_delegated(FWRITE, srcvp, FALSE)) { 2114 VN_RELE(tovp); 2115 VN_RELE(fromvp); 2116 VN_RELE(srcvp); 2117 curthread->t_flag |= T_WOULDBLOCK; 2118 return; 2119 } 2120 2121 /* Check for delegation on the file being renamed over, if it exists */ 2122 2123 if (rfs4_deleg_policy != SRV_NEVER_DELEGATE && 2124 VOP_LOOKUP(tovp, args->rna_to.da_name, &targvp, NULL, 0, NULL, cr, 2125 NULL, NULL, NULL) == 0) { 2126 2127 if (rfs4_check_delegated(FWRITE, targvp, TRUE)) { 2128 VN_RELE(tovp); 2129 VN_RELE(fromvp); 2130 VN_RELE(srcvp); 2131 VN_RELE(targvp); 2132 curthread->t_flag |= T_WOULDBLOCK; 2133 return; 2134 } 2135 VN_RELE(targvp); 2136 } 2137 2138 2139 if (nbl_need_check(srcvp)) { 2140 nbl_start_crit(srcvp, RW_READER); 2141 in_crit = 1; 2142 if (nbl_conflict(srcvp, NBL_RENAME, 0, 0, 0, NULL)) { 2143 error = EACCES; 2144 goto out; 2145 } 2146 } 2147 2148 error = VOP_RENAME(fromvp, args->rna_from.da_name, 2149 tovp, args->rna_to.da_name, cr, NULL, 0); 2150 2151 if (error == 0) 2152 vn_renamepath(tovp, srcvp, args->rna_to.da_name, 2153 strlen(args->rna_to.da_name)); 2154 2155 /* 2156 * Force modified data and metadata out to stable storage. 2157 */ 2158 (void) VOP_FSYNC(tovp, 0, cr, NULL); 2159 (void) VOP_FSYNC(fromvp, 0, cr, NULL); 2160 2161 out: 2162 if (in_crit) 2163 nbl_end_crit(srcvp); 2164 VN_RELE(srcvp); 2165 VN_RELE(tovp); 2166 VN_RELE(fromvp); 2167 2168 *status = puterrno(error); 2169 2170 } 2171 void * 2172 rfs_rename_getfh(struct nfsrnmargs *args) 2173 { 2174 return (args->rna_from.da_fhandle); 2175 } 2176 2177 /* 2178 * Link to a file. 2179 * Create a file (to) which is a hard link to the given file (from). 2180 */ 2181 /* ARGSUSED */ 2182 void 2183 rfs_link(struct nfslinkargs *args, enum nfsstat *status, 2184 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 2185 { 2186 int error; 2187 vnode_t *fromvp; 2188 vnode_t *tovp; 2189 struct exportinfo *to_exi; 2190 fhandle_t *fh; 2191 2192 fromvp = nfs_fhtovp(args->la_from, exi); 2193 if (fromvp == NULL) { 2194 *status = NFSERR_STALE; 2195 return; 2196 } 2197 2198 fh = args->la_to.da_fhandle; 2199 to_exi = checkexport(&fh->fh_fsid, (fid_t *)&fh->fh_xlen); 2200 if (to_exi == NULL) { 2201 VN_RELE(fromvp); 2202 *status = NFSERR_ACCES; 2203 return; 2204 } 2205 exi_rele(to_exi); 2206 2207 if (to_exi != exi) { 2208 VN_RELE(fromvp); 2209 *status = NFSERR_XDEV; 2210 return; 2211 } 2212 2213 tovp = nfs_fhtovp(args->la_to.da_fhandle, exi); 2214 if (tovp == NULL) { 2215 VN_RELE(fromvp); 2216 *status = NFSERR_STALE; 2217 return; 2218 } 2219 2220 if (tovp->v_type != VDIR) { 2221 VN_RELE(tovp); 2222 VN_RELE(fromvp); 2223 *status = NFSERR_NOTDIR; 2224 return; 2225 } 2226 /* 2227 * Disallow NULL paths 2228 */ 2229 if (args->la_to.da_name == NULL || *args->la_to.da_name == '\0') { 2230 VN_RELE(tovp); 2231 VN_RELE(fromvp); 2232 *status = NFSERR_ACCES; 2233 return; 2234 } 2235 2236 if (rdonly(ro, tovp)) { 2237 VN_RELE(tovp); 2238 VN_RELE(fromvp); 2239 *status = NFSERR_ROFS; 2240 return; 2241 } 2242 2243 error = VOP_LINK(tovp, fromvp, args->la_to.da_name, cr, NULL, 0); 2244 2245 /* 2246 * Force modified data and metadata out to stable storage. 2247 */ 2248 (void) VOP_FSYNC(tovp, 0, cr, NULL); 2249 (void) VOP_FSYNC(fromvp, FNODSYNC, cr, NULL); 2250 2251 VN_RELE(tovp); 2252 VN_RELE(fromvp); 2253 2254 *status = puterrno(error); 2255 2256 } 2257 void * 2258 rfs_link_getfh(struct nfslinkargs *args) 2259 { 2260 return (args->la_from); 2261 } 2262 2263 /* 2264 * Symbolicly link to a file. 2265 * Create a file (to) with the given attributes which is a symbolic link 2266 * to the given path name (to). 2267 */ 2268 void 2269 rfs_symlink(struct nfsslargs *args, enum nfsstat *status, 2270 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 2271 { 2272 int error; 2273 struct vattr va; 2274 vnode_t *vp; 2275 vnode_t *svp; 2276 int lerror; 2277 struct sockaddr *ca; 2278 char *name = NULL; 2279 2280 /* 2281 * Disallow NULL paths 2282 */ 2283 if (args->sla_from.da_name == NULL || *args->sla_from.da_name == '\0') { 2284 *status = NFSERR_ACCES; 2285 return; 2286 } 2287 2288 vp = nfs_fhtovp(args->sla_from.da_fhandle, exi); 2289 if (vp == NULL) { 2290 *status = NFSERR_STALE; 2291 return; 2292 } 2293 2294 if (rdonly(ro, vp)) { 2295 VN_RELE(vp); 2296 *status = NFSERR_ROFS; 2297 return; 2298 } 2299 2300 error = sattr_to_vattr(args->sla_sa, &va); 2301 if (error) { 2302 VN_RELE(vp); 2303 *status = puterrno(error); 2304 return; 2305 } 2306 2307 if (!(va.va_mask & AT_MODE)) { 2308 VN_RELE(vp); 2309 *status = NFSERR_INVAL; 2310 return; 2311 } 2312 2313 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2314 name = nfscmd_convname(ca, exi, args->sla_tnm, 2315 NFSCMD_CONV_INBOUND, MAXPATHLEN); 2316 2317 if (name == NULL) { 2318 *status = NFSERR_ACCES; 2319 return; 2320 } 2321 2322 va.va_type = VLNK; 2323 va.va_mask |= AT_TYPE; 2324 2325 error = VOP_SYMLINK(vp, args->sla_from.da_name, &va, name, cr, NULL, 0); 2326 2327 /* 2328 * Force new data and metadata out to stable storage. 2329 */ 2330 lerror = VOP_LOOKUP(vp, args->sla_from.da_name, &svp, NULL, 0, 2331 NULL, cr, NULL, NULL, NULL); 2332 2333 if (!lerror) { 2334 (void) VOP_FSYNC(svp, 0, cr, NULL); 2335 VN_RELE(svp); 2336 } 2337 2338 /* 2339 * Force modified data and metadata out to stable storage. 2340 */ 2341 (void) VOP_FSYNC(vp, 0, cr, NULL); 2342 2343 VN_RELE(vp); 2344 2345 *status = puterrno(error); 2346 if (name != args->sla_tnm) 2347 kmem_free(name, MAXPATHLEN); 2348 2349 } 2350 void * 2351 rfs_symlink_getfh(struct nfsslargs *args) 2352 { 2353 return (args->sla_from.da_fhandle); 2354 } 2355 2356 /* 2357 * Make a directory. 2358 * Create a directory with the given name, parent directory, and attributes. 2359 * Returns a file handle and attributes for the new directory. 2360 */ 2361 /* ARGSUSED */ 2362 void 2363 rfs_mkdir(struct nfscreatargs *args, struct nfsdiropres *dr, 2364 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 2365 { 2366 int error; 2367 struct vattr va; 2368 vnode_t *dvp = NULL; 2369 vnode_t *vp; 2370 char *name = args->ca_da.da_name; 2371 2372 /* 2373 * Disallow NULL paths 2374 */ 2375 if (name == NULL || *name == '\0') { 2376 dr->dr_status = NFSERR_ACCES; 2377 return; 2378 } 2379 2380 vp = nfs_fhtovp(args->ca_da.da_fhandle, exi); 2381 if (vp == NULL) { 2382 dr->dr_status = NFSERR_STALE; 2383 return; 2384 } 2385 2386 if (rdonly(ro, vp)) { 2387 VN_RELE(vp); 2388 dr->dr_status = NFSERR_ROFS; 2389 return; 2390 } 2391 2392 error = sattr_to_vattr(args->ca_sa, &va); 2393 if (error) { 2394 VN_RELE(vp); 2395 dr->dr_status = puterrno(error); 2396 return; 2397 } 2398 2399 if (!(va.va_mask & AT_MODE)) { 2400 VN_RELE(vp); 2401 dr->dr_status = NFSERR_INVAL; 2402 return; 2403 } 2404 2405 va.va_type = VDIR; 2406 va.va_mask |= AT_TYPE; 2407 2408 error = VOP_MKDIR(vp, name, &va, &dvp, cr, NULL, 0, NULL); 2409 2410 if (!error) { 2411 /* 2412 * Attribtutes of the newly created directory should 2413 * be returned to the client. 2414 */ 2415 va.va_mask = AT_ALL; /* We want everything */ 2416 error = VOP_GETATTR(dvp, &va, 0, cr, NULL); 2417 2418 /* check for overflows */ 2419 if (!error) { 2420 acl_perm(vp, exi, &va, cr); 2421 error = vattr_to_nattr(&va, &dr->dr_attr); 2422 if (!error) { 2423 error = makefh(&dr->dr_fhandle, dvp, exi); 2424 } 2425 } 2426 /* 2427 * Force new data and metadata out to stable storage. 2428 */ 2429 (void) VOP_FSYNC(dvp, 0, cr, NULL); 2430 VN_RELE(dvp); 2431 } 2432 2433 /* 2434 * Force modified data and metadata out to stable storage. 2435 */ 2436 (void) VOP_FSYNC(vp, 0, cr, NULL); 2437 2438 VN_RELE(vp); 2439 2440 dr->dr_status = puterrno(error); 2441 2442 } 2443 void * 2444 rfs_mkdir_getfh(struct nfscreatargs *args) 2445 { 2446 return (args->ca_da.da_fhandle); 2447 } 2448 2449 /* 2450 * Remove a directory. 2451 * Remove the given directory name from the given parent directory. 2452 */ 2453 /* ARGSUSED */ 2454 void 2455 rfs_rmdir(struct nfsdiropargs *da, enum nfsstat *status, 2456 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 2457 { 2458 int error; 2459 vnode_t *vp; 2460 2461 /* 2462 * Disallow NULL paths 2463 */ 2464 if (da->da_name == NULL || *da->da_name == '\0') { 2465 *status = NFSERR_ACCES; 2466 return; 2467 } 2468 2469 vp = nfs_fhtovp(da->da_fhandle, exi); 2470 if (vp == NULL) { 2471 *status = NFSERR_STALE; 2472 return; 2473 } 2474 2475 if (rdonly(ro, vp)) { 2476 VN_RELE(vp); 2477 *status = NFSERR_ROFS; 2478 return; 2479 } 2480 2481 /* 2482 * VOP_RMDIR takes a third argument (the current 2483 * directory of the process). That's because someone 2484 * wants to return EINVAL if one tries to remove ".". 2485 * Of course, NFS servers have no idea what their 2486 * clients' current directories are. We fake it by 2487 * supplying a vnode known to exist and illegal to 2488 * remove. 2489 */ 2490 error = VOP_RMDIR(vp, da->da_name, rootdir, cr, NULL, 0); 2491 2492 /* 2493 * Force modified data and metadata out to stable storage. 2494 */ 2495 (void) VOP_FSYNC(vp, 0, cr, NULL); 2496 2497 VN_RELE(vp); 2498 2499 /* 2500 * System V defines rmdir to return EEXIST, not ENOTEMPTY, 2501 * if the directory is not empty. A System V NFS server 2502 * needs to map NFSERR_EXIST to NFSERR_NOTEMPTY to transmit 2503 * over the wire. 2504 */ 2505 if (error == EEXIST) 2506 *status = NFSERR_NOTEMPTY; 2507 else 2508 *status = puterrno(error); 2509 2510 } 2511 void * 2512 rfs_rmdir_getfh(struct nfsdiropargs *da) 2513 { 2514 return (da->da_fhandle); 2515 } 2516 2517 /* ARGSUSED */ 2518 void 2519 rfs_readdir(struct nfsrddirargs *rda, struct nfsrddirres *rd, 2520 struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) 2521 { 2522 int error; 2523 int iseof; 2524 struct iovec iov; 2525 struct uio uio; 2526 vnode_t *vp; 2527 char *ndata = NULL; 2528 struct sockaddr *ca; 2529 size_t nents; 2530 int ret; 2531 2532 vp = nfs_fhtovp(&rda->rda_fh, exi); 2533 if (vp == NULL) { 2534 rd->rd_entries = NULL; 2535 rd->rd_status = NFSERR_STALE; 2536 return; 2537 } 2538 2539 if (vp->v_type != VDIR) { 2540 VN_RELE(vp); 2541 rd->rd_entries = NULL; 2542 rd->rd_status = NFSERR_NOTDIR; 2543 return; 2544 } 2545 2546 (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL); 2547 2548 error = VOP_ACCESS(vp, VREAD, 0, cr, NULL); 2549 2550 if (error) { 2551 rd->rd_entries = NULL; 2552 goto bad; 2553 } 2554 2555 if (rda->rda_count == 0) { 2556 rd->rd_entries = NULL; 2557 rd->rd_size = 0; 2558 rd->rd_eof = FALSE; 2559 goto bad; 2560 } 2561 2562 rda->rda_count = MIN(rda->rda_count, NFS_MAXDATA); 2563 2564 /* 2565 * Allocate data for entries. This will be freed by rfs_rddirfree. 2566 */ 2567 rd->rd_bufsize = (uint_t)rda->rda_count; 2568 rd->rd_entries = kmem_alloc(rd->rd_bufsize, KM_SLEEP); 2569 2570 /* 2571 * Set up io vector to read directory data 2572 */ 2573 iov.iov_base = (caddr_t)rd->rd_entries; 2574 iov.iov_len = rda->rda_count; 2575 uio.uio_iov = &iov; 2576 uio.uio_iovcnt = 1; 2577 uio.uio_segflg = UIO_SYSSPACE; 2578 uio.uio_extflg = UIO_COPY_CACHED; 2579 uio.uio_loffset = (offset_t)rda->rda_offset; 2580 uio.uio_resid = rda->rda_count; 2581 2582 /* 2583 * read directory 2584 */ 2585 error = VOP_READDIR(vp, &uio, cr, &iseof, NULL, 0); 2586 2587 /* 2588 * Clean up 2589 */ 2590 if (!error) { 2591 /* 2592 * set size and eof 2593 */ 2594 if (uio.uio_resid == rda->rda_count) { 2595 rd->rd_size = 0; 2596 rd->rd_eof = TRUE; 2597 } else { 2598 rd->rd_size = (uint32_t)(rda->rda_count - 2599 uio.uio_resid); 2600 rd->rd_eof = iseof ? TRUE : FALSE; 2601 } 2602 } 2603 2604 ca = (struct sockaddr *)svc_getrpccaller(req->rq_xprt)->buf; 2605 nents = nfscmd_countents((char *)rd->rd_entries, rd->rd_size); 2606 ret = nfscmd_convdirplus(ca, exi, (char *)rd->rd_entries, nents, 2607 rda->rda_count, &ndata); 2608 2609 if (ret != 0) { 2610 size_t dropbytes; 2611 /* 2612 * We had to drop one or more entries in order to fit 2613 * during the character conversion. We need to patch 2614 * up the size and eof info. 2615 */ 2616 if (rd->rd_eof) 2617 rd->rd_eof = FALSE; 2618 dropbytes = nfscmd_dropped_entrysize( 2619 (struct dirent64 *)rd->rd_entries, nents, ret); 2620 rd->rd_size -= dropbytes; 2621 } 2622 if (ndata == NULL) { 2623 ndata = (char *)rd->rd_entries; 2624 } else if (ndata != (char *)rd->rd_entries) { 2625 kmem_free(rd->rd_entries, rd->rd_bufsize); 2626 rd->rd_entries = (void *)ndata; 2627 rd->rd_bufsize = rda->rda_count; 2628 } 2629 2630 bad: 2631 VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL); 2632 2633 #if 0 /* notyet */ 2634 /* 2635 * Don't do this. It causes local disk writes when just 2636 * reading the file and the overhead is deemed larger 2637 * than the benefit. 2638 */ 2639 /* 2640 * Force modified metadata out to stable storage. 2641 */ 2642 (void) VOP_FSYNC(vp, FNODSYNC, cr, NULL); 2643 #endif 2644 2645 VN_RELE(vp); 2646 2647 rd->rd_status = puterrno(error); 2648 2649 } 2650 void * 2651 rfs_readdir_getfh(struct nfsrddirargs *rda) 2652 { 2653 return (&rda->rda_fh); 2654 } 2655 void 2656 rfs_rddirfree(struct nfsrddirres *rd) 2657 { 2658 if (rd->rd_entries != NULL) 2659 kmem_free(rd->rd_entries, rd->rd_bufsize); 2660 } 2661 2662 /* ARGSUSED */ 2663 void 2664 rfs_statfs(fhandle_t *fh, struct nfsstatfs *fs, struct exportinfo *exi, 2665 struct svc_req *req, cred_t *cr, bool_t ro) 2666 { 2667 int error; 2668 struct statvfs64 sb; 2669 vnode_t *vp; 2670 2671 vp = nfs_fhtovp(fh, exi); 2672 if (vp == NULL) { 2673 fs->fs_status = NFSERR_STALE; 2674 return; 2675 } 2676 2677 error = VFS_STATVFS(vp->v_vfsp, &sb); 2678 2679 if (!error) { 2680 fs->fs_tsize = nfstsize(); 2681 fs->fs_bsize = sb.f_frsize; 2682 fs->fs_blocks = sb.f_blocks; 2683 fs->fs_bfree = sb.f_bfree; 2684 fs->fs_bavail = sb.f_bavail; 2685 } 2686 2687 VN_RELE(vp); 2688 2689 fs->fs_status = puterrno(error); 2690 2691 } 2692 void * 2693 rfs_statfs_getfh(fhandle_t *fh) 2694 { 2695 return (fh); 2696 } 2697 2698 static int 2699 sattr_to_vattr(struct nfssattr *sa, struct vattr *vap) 2700 { 2701 vap->va_mask = 0; 2702 2703 /* 2704 * There was a sign extension bug in some VFS based systems 2705 * which stored the mode as a short. When it would get 2706 * assigned to a u_long, no sign extension would occur. 2707 * It needed to, but this wasn't noticed because sa_mode 2708 * would then get assigned back to the short, thus ignoring 2709 * the upper 16 bits of sa_mode. 2710 * 2711 * To make this implementation work for both broken 2712 * clients and good clients, we check for both versions 2713 * of the mode. 2714 */ 2715 if (sa->sa_mode != (uint32_t)((ushort_t)-1) && 2716 sa->sa_mode != (uint32_t)-1) { 2717 vap->va_mask |= AT_MODE; 2718 vap->va_mode = sa->sa_mode; 2719 } 2720 if (sa->sa_uid != (uint32_t)-1) { 2721 vap->va_mask |= AT_UID; 2722 vap->va_uid = sa->sa_uid; 2723 } 2724 if (sa->sa_gid != (uint32_t)-1) { 2725 vap->va_mask |= AT_GID; 2726 vap->va_gid = sa->sa_gid; 2727 } 2728 if (sa->sa_size != (uint32_t)-1) { 2729 vap->va_mask |= AT_SIZE; 2730 vap->va_size = sa->sa_size; 2731 } 2732 if (sa->sa_atime.tv_sec != (int32_t)-1 && 2733 sa->sa_atime.tv_usec != (int32_t)-1) { 2734 #ifndef _LP64 2735 /* return error if time overflow */ 2736 if (!NFS2_TIME_OK(sa->sa_atime.tv_sec)) 2737 return (EOVERFLOW); 2738 #endif 2739 vap->va_mask |= AT_ATIME; 2740 /* 2741 * nfs protocol defines times as unsigned so don't extend sign, 2742 * unless sysadmin set nfs_allow_preepoch_time. 2743 */ 2744 NFS_TIME_T_CONVERT(vap->va_atime.tv_sec, sa->sa_atime.tv_sec); 2745 vap->va_atime.tv_nsec = (uint32_t)(sa->sa_atime.tv_usec * 1000); 2746 } 2747 if (sa->sa_mtime.tv_sec != (int32_t)-1 && 2748 sa->sa_mtime.tv_usec != (int32_t)-1) { 2749 #ifndef _LP64 2750 /* return error if time overflow */ 2751 if (!NFS2_TIME_OK(sa->sa_mtime.tv_sec)) 2752 return (EOVERFLOW); 2753 #endif 2754 vap->va_mask |= AT_MTIME; 2755 /* 2756 * nfs protocol defines times as unsigned so don't extend sign, 2757 * unless sysadmin set nfs_allow_preepoch_time. 2758 */ 2759 NFS_TIME_T_CONVERT(vap->va_mtime.tv_sec, sa->sa_mtime.tv_sec); 2760 vap->va_mtime.tv_nsec = (uint32_t)(sa->sa_mtime.tv_usec * 1000); 2761 } 2762 return (0); 2763 } 2764 2765 static enum nfsftype vt_to_nf[] = { 2766 0, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, 0, 0, 0, NFSOC, 0 2767 }; 2768 2769 /* 2770 * check the following fields for overflow: nodeid, size, and time. 2771 * There could be a problem when converting 64-bit LP64 fields 2772 * into 32-bit ones. Return an error if there is an overflow. 2773 */ 2774 int 2775 vattr_to_nattr(struct vattr *vap, struct nfsfattr *na) 2776 { 2777 ASSERT(vap->va_type >= VNON && vap->va_type <= VBAD); 2778 na->na_type = vt_to_nf[vap->va_type]; 2779 2780 if (vap->va_mode == (unsigned short) -1) 2781 na->na_mode = (uint32_t)-1; 2782 else 2783 na->na_mode = VTTOIF(vap->va_type) | vap->va_mode; 2784 2785 if (vap->va_uid == (unsigned short)(-1)) 2786 na->na_uid = (uint32_t)(-1); 2787 else if (vap->va_uid == UID_NOBODY) 2788 na->na_uid = (uint32_t)NFS_UID_NOBODY; 2789 else 2790 na->na_uid = vap->va_uid; 2791 2792 if (vap->va_gid == (unsigned short)(-1)) 2793 na->na_gid = (uint32_t)-1; 2794 else if (vap->va_gid == GID_NOBODY) 2795 na->na_gid = (uint32_t)NFS_GID_NOBODY; 2796 else 2797 na->na_gid = vap->va_gid; 2798 2799 /* 2800 * Do we need to check fsid for overflow? It is 64-bit in the 2801 * vattr, but are bigger than 32 bit values supported? 2802 */ 2803 na->na_fsid = vap->va_fsid; 2804 2805 na->na_nodeid = vap->va_nodeid; 2806 2807 /* 2808 * Check to make sure that the nodeid is representable over the 2809 * wire without losing bits. 2810 */ 2811 if (vap->va_nodeid != (u_longlong_t)na->na_nodeid) 2812 return (EFBIG); 2813 na->na_nlink = vap->va_nlink; 2814 2815 /* 2816 * Check for big files here, instead of at the caller. See 2817 * comments in cstat for large special file explanation. 2818 */ 2819 if (vap->va_size > (u_longlong_t)MAXOFF32_T) { 2820 if ((vap->va_type == VREG) || (vap->va_type == VDIR)) 2821 return (EFBIG); 2822 if ((vap->va_type == VBLK) || (vap->va_type == VCHR)) { 2823 /* UNKNOWN_SIZE | OVERFLOW */ 2824 na->na_size = MAXOFF32_T; 2825 } else 2826 na->na_size = vap->va_size; 2827 } else 2828 na->na_size = vap->va_size; 2829 2830 /* 2831 * If the vnode times overflow the 32-bit times that NFS2 2832 * uses on the wire then return an error. 2833 */ 2834 if (!NFS_VAP_TIME_OK(vap)) { 2835 return (EOVERFLOW); 2836 } 2837 na->na_atime.tv_sec = vap->va_atime.tv_sec; 2838 na->na_atime.tv_usec = vap->va_atime.tv_nsec / 1000; 2839 2840 na->na_mtime.tv_sec = vap->va_mtime.tv_sec; 2841 na->na_mtime.tv_usec = vap->va_mtime.tv_nsec / 1000; 2842 2843 na->na_ctime.tv_sec = vap->va_ctime.tv_sec; 2844 na->na_ctime.tv_usec = vap->va_ctime.tv_nsec / 1000; 2845 2846 /* 2847 * If the dev_t will fit into 16 bits then compress 2848 * it, otherwise leave it alone. See comments in 2849 * nfs_client.c. 2850 */ 2851 if (getminor(vap->va_rdev) <= SO4_MAXMIN && 2852 getmajor(vap->va_rdev) <= SO4_MAXMAJ) 2853 na->na_rdev = nfsv2_cmpdev(vap->va_rdev); 2854 else 2855 (void) cmpldev(&na->na_rdev, vap->va_rdev); 2856 2857 na->na_blocks = vap->va_nblocks; 2858 na->na_blocksize = vap->va_blksize; 2859 2860 /* 2861 * This bit of ugliness is a *TEMPORARY* hack to preserve the 2862 * over-the-wire protocols for named-pipe vnodes. It remaps the 2863 * VFIFO type to the special over-the-wire type. (see note in nfs.h) 2864 * 2865 * BUYER BEWARE: 2866 * If you are porting the NFS to a non-Sun server, you probably 2867 * don't want to include the following block of code. The 2868 * over-the-wire special file types will be changing with the 2869 * NFS Protocol Revision. 2870 */ 2871 if (vap->va_type == VFIFO) 2872 NA_SETFIFO(na); 2873 return (0); 2874 } 2875 2876 /* 2877 * acl v2 support: returns approximate permission. 2878 * default: returns minimal permission (more restrictive) 2879 * aclok: returns maximal permission (less restrictive) 2880 * This routine changes the permissions that are alaredy in *va. 2881 * If a file has minimal ACL, i.e. aclcnt == MIN_ACL_ENTRIES, 2882 * CLASS_OBJ is always the same as GROUP_OBJ entry. 2883 */ 2884 static void 2885 acl_perm(struct vnode *vp, struct exportinfo *exi, struct vattr *va, cred_t *cr) 2886 { 2887 vsecattr_t vsa; 2888 int aclcnt; 2889 aclent_t *aclentp; 2890 mode_t mask_perm; 2891 mode_t grp_perm; 2892 mode_t other_perm; 2893 mode_t other_orig; 2894 int error; 2895 2896 /* dont care default acl */ 2897 vsa.vsa_mask = (VSA_ACL | VSA_ACLCNT); 2898 error = VOP_GETSECATTR(vp, &vsa, 0, cr, NULL); 2899 2900 if (!error) { 2901 aclcnt = vsa.vsa_aclcnt; 2902 if (aclcnt > MIN_ACL_ENTRIES) { 2903 /* non-trivial ACL */ 2904 aclentp = vsa.vsa_aclentp; 2905 if (exi->exi_export.ex_flags & EX_ACLOK) { 2906 /* maximal permissions */ 2907 grp_perm = 0; 2908 other_perm = 0; 2909 for (; aclcnt > 0; aclcnt--, aclentp++) { 2910 switch (aclentp->a_type) { 2911 case USER_OBJ: 2912 break; 2913 case USER: 2914 grp_perm |= 2915 aclentp->a_perm << 3; 2916 other_perm |= aclentp->a_perm; 2917 break; 2918 case GROUP_OBJ: 2919 grp_perm |= 2920 aclentp->a_perm << 3; 2921 break; 2922 case GROUP: 2923 other_perm |= aclentp->a_perm; 2924 break; 2925 case OTHER_OBJ: 2926 other_orig = aclentp->a_perm; 2927 break; 2928 case CLASS_OBJ: 2929 mask_perm = aclentp->a_perm; 2930 break; 2931 default: 2932 break; 2933 } 2934 } 2935 grp_perm &= mask_perm << 3; 2936 other_perm &= mask_perm; 2937 other_perm |= other_orig; 2938 2939 } else { 2940 /* minimal permissions */ 2941 grp_perm = 070; 2942 other_perm = 07; 2943 for (; aclcnt > 0; aclcnt--, aclentp++) { 2944 switch (aclentp->a_type) { 2945 case USER_OBJ: 2946 break; 2947 case USER: 2948 case CLASS_OBJ: 2949 grp_perm &= 2950 aclentp->a_perm << 3; 2951 other_perm &= 2952 aclentp->a_perm; 2953 break; 2954 case GROUP_OBJ: 2955 grp_perm &= 2956 aclentp->a_perm << 3; 2957 break; 2958 case GROUP: 2959 other_perm &= 2960 aclentp->a_perm; 2961 break; 2962 case OTHER_OBJ: 2963 other_perm &= 2964 aclentp->a_perm; 2965 break; 2966 default: 2967 break; 2968 } 2969 } 2970 } 2971 /* copy to va */ 2972 va->va_mode &= ~077; 2973 va->va_mode |= grp_perm | other_perm; 2974 } 2975 if (vsa.vsa_aclcnt) 2976 kmem_free(vsa.vsa_aclentp, 2977 vsa.vsa_aclcnt * sizeof (aclent_t)); 2978 } 2979 } 2980 2981 void 2982 rfs_srvrinit(void) 2983 { 2984 mutex_init(&rfs_async_write_lock, NULL, MUTEX_DEFAULT, NULL); 2985 nfs2_srv_caller_id = fs_new_caller_id(); 2986 } 2987 2988 void 2989 rfs_srvrfini(void) 2990 { 2991 mutex_destroy(&rfs_async_write_lock); 2992 } 2993 2994 static int 2995 rdma_setup_read_data2(struct nfsreadargs *ra, struct nfsrdresult *rr) 2996 { 2997 struct clist *wcl; 2998 int wlist_len; 2999 uint32_t count = rr->rr_count; 3000 3001 wcl = ra->ra_wlist; 3002 3003 if (rdma_setup_read_chunks(wcl, count, &wlist_len) == FALSE) { 3004 return (FALSE); 3005 } 3006 3007 wcl = ra->ra_wlist; 3008 rr->rr_ok.rrok_wlist_len = wlist_len; 3009 rr->rr_ok.rrok_wlist = wcl; 3010 3011 return (TRUE); 3012 } 3013