272 { NULL, NULL } 273}; 274static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 275 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries }; 276VNODEOP_SET(fifo_nfsv2nodeop_opv_desc); 277 278static int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt, 279 struct ucred *cred, struct proc *procp)); 280static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp, 281 struct componentname *cnp, 282 struct vattr *vap)); 283static int nfs_removerpc __P((struct vnode *dvp, char *name, int namelen, 284 struct ucred *cred, struct proc *proc)); 285static int nfs_renamerpc __P((struct vnode *fdvp, char *fnameptr, 286 int fnamelen, struct vnode *tdvp, 287 char *tnameptr, int tnamelen, 288 struct ucred *cred, struct proc *proc)); 289static int nfs_renameit __P((struct vnode *sdvp, 290 struct componentname *scnp, 291 struct sillyrename *sp)); 292 293/* 294 * Global variables 295 */ 296extern u_long nfs_true, nfs_false; 297extern struct nfsstats nfsstats; 298extern nfstype nfsv3_type[9]; 299struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 300struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON]; 301int nfs_numasync = 0; 302#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 303 304/* 305 * nfs access vnode op. 306 * For nfs version 2, just return ok. File accesses may fail later. 307 * For nfs version 3, use the access rpc to check accessibility. If file modes 308 * are changed on the server, accesses might still fail later. 309 */ 310static int 311nfs_access(ap) 312 struct vop_access_args /* { 313 struct vnode *a_vp; 314 int a_mode; 315 struct ucred *a_cred; 316 struct proc *a_p; 317 } */ *ap; 318{ 319 register struct vnode *vp = ap->a_vp; 320 register u_long *tl; 321 register caddr_t cp; 322 register int t1, t2; 323 caddr_t bpos, dpos, cp2; 324 int error = 0, attrflag; 325 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 326 u_long mode, rmode; 327 int v3 = NFS_ISV3(vp); 328 329 /* 330 * Disallow write attempts on filesystems mounted read-only; 331 * unless the file is a socket, fifo, or a block or character 332 * device resident on the filesystem. 333 */ 334 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 335 switch (vp->v_type) { 336 case VREG: case VDIR: case VLNK: 337 return (EROFS); 338 } 339 } 340 /* 341 * For nfs v3, do an access rpc, otherwise you are stuck emulating 342 * ufs_access() locally using the vattr. This may not be correct, 343 * since the server may apply other access criteria such as 344 * client uid-->server uid mapping that we do not know about, but 345 * this is better than just returning anything that is lying about 346 * in the cache. 347 */ 348 if (v3) { 349 nfsstats.rpccnt[NFSPROC_ACCESS]++; 350 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); 351 nfsm_fhtom(vp, v3); 352 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 353 if (ap->a_mode & VREAD) 354 mode = NFSV3ACCESS_READ; 355 else 356 mode = 0; 357 if (vp->v_type == VDIR) { 358 if (ap->a_mode & VWRITE) 359 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 360 NFSV3ACCESS_DELETE); 361 if (ap->a_mode & VEXEC) 362 mode |= NFSV3ACCESS_LOOKUP; 363 } else { 364 if (ap->a_mode & VWRITE) 365 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 366 if (ap->a_mode & VEXEC) 367 mode |= NFSV3ACCESS_EXECUTE; 368 } 369 *tl = txdr_unsigned(mode); 370 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred); 371 nfsm_postop_attr(vp, attrflag); 372 if (!error) { 373 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 374 rmode = fxdr_unsigned(u_long, *tl); 375 /* 376 * The NFS V3 spec does not clarify whether or not 377 * the returned access bits can be a superset of 378 * the ones requested, so... 379 */ 380 if ((rmode & mode) != mode) 381 error = EACCES; 382 } 383 nfsm_reqdone; 384 return (error); 385 } else { 386 if (error = nfsspec_access(ap)) 387 return (error); 388 389 /* 390 * Attempt to prevent a mapped root from accessing a file 391 * which it shouldn't. We try to read a byte from the file 392 * if the user is root and the file is not zero length. 393 * After calling nfsspec_access, we should have the correct 394 * file size cached. 395 */ 396 if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD) 397 && VTONFS(vp)->n_size > 0) { 398 struct iovec aiov; 399 struct uio auio; 400 char buf[1]; 401 402 aiov.iov_base = buf; 403 aiov.iov_len = 1; 404 auio.uio_iov = &aiov; 405 auio.uio_iovcnt = 1; 406 auio.uio_offset = 0; 407 auio.uio_resid = 1; 408 auio.uio_segflg = UIO_SYSSPACE; 409 auio.uio_rw = UIO_READ; 410 auio.uio_procp = ap->a_p; 411 412 if (vp->v_type == VREG) 413 error = nfs_readrpc(vp, &auio, ap->a_cred); 414 else if (vp->v_type == VDIR) { 415 char* buf; 416 buf = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK); 417 aiov.iov_base = buf; 418 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ; 419 error = nfs_readdirrpc(vp, &auio, ap->a_cred); 420 free(buf, M_TEMP); 421 } else if (vp->v_type = VLNK) 422 error = nfs_readlinkrpc(vp, &auio, ap->a_cred); 423 else 424 error = EACCES; 425 } 426 return (error); 427 } 428} 429 430/* 431 * nfs open vnode op 432 * Check to see if the type is ok 433 * and that deletion is not in progress. 434 * For paged in text files, you will need to flush the page cache 435 * if consistency is lost. 436 */ 437/* ARGSUSED */ 438static int 439nfs_open(ap) 440 struct vop_open_args /* { 441 struct vnode *a_vp; 442 int a_mode; 443 struct ucred *a_cred; 444 struct proc *a_p; 445 } */ *ap; 446{ 447 register struct vnode *vp = ap->a_vp; 448 struct nfsnode *np = VTONFS(vp); 449 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 450 struct vattr vattr; 451 int error; 452 453 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) 454{ printf("open eacces vtyp=%d\n",vp->v_type); 455 return (EACCES); 456} 457 /* 458 * Get a valid lease. If cached data is stale, flush it. 459 */ 460 if (nmp->nm_flag & NFSMNT_NQNFS) { 461 if (NQNFS_CKINVALID(vp, np, ND_READ)) { 462 do { 463 error = nqnfs_getlease(vp, ND_READ, ap->a_cred, 464 ap->a_p); 465 } while (error == NQNFS_EXPIRED); 466 if (error) 467 return (error); 468 if (np->n_lrev != np->n_brev || 469 (np->n_flag & NQNFSNONCACHE)) { 470 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 471 ap->a_p, 1)) == EINTR) 472 return (error); 473 (void) vnode_pager_uncache(vp, ap->a_p); 474 np->n_brev = np->n_lrev; 475 } 476 } 477 } else { 478 if (np->n_flag & NMODIFIED) { 479 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 480 ap->a_p, 1)) == EINTR) 481 return (error); 482 np->n_attrstamp = 0; 483 if (vp->v_type == VDIR) 484 np->n_direofoffset = 0; 485 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 486 if (error) 487 return (error); 488 np->n_mtime = vattr.va_mtime.tv_sec; 489 } else { 490 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 491 if (error) 492 return (error); 493 if (np->n_mtime != vattr.va_mtime.tv_sec) { 494 if (vp->v_type == VDIR) 495 np->n_direofoffset = 0; 496 if ((error = nfs_vinvalbuf(vp, V_SAVE, 497 ap->a_cred, ap->a_p, 1)) == EINTR) 498 return (error); 499 np->n_mtime = vattr.va_mtime.tv_sec; 500 } 501 } 502 } 503 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 504 np->n_attrstamp = 0; /* For Open/Close consistency */ 505 return (0); 506} 507 508/* 509 * nfs close vnode op 510 * What an NFS client should do upon close after writing is a debatable issue. 511 * Most NFS clients push delayed writes to the server upon close, basically for 512 * two reasons: 513 * 1 - So that any write errors may be reported back to the client process 514 * doing the close system call. By far the two most likely errors are 515 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 516 * 2 - To put a worst case upper bound on cache inconsistency between 517 * multiple clients for the file. 518 * There is also a consistency problem for Version 2 of the protocol w.r.t. 519 * not being able to tell if other clients are writing a file concurrently, 520 * since there is no way of knowing if the changed modify time in the reply 521 * is only due to the write for this client. 522 * (NFS Version 3 provides weak cache consistency data in the reply that 523 * should be sufficient to detect and handle this case.) 524 * 525 * The current code does the following: 526 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 527 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate 528 * or commit them (this satisfies 1 and 2 except for the 529 * case where the server crashes after this close but 530 * before the commit RPC, which is felt to be "good 531 * enough". Changing the last argument to nfs_flush() to 532 * a 1 would force a commit operation, if it is felt a 533 * commit is necessary now. 534 * for NQNFS - do nothing now, since 2 is dealt with via leases and 535 * 1 should be dealt with via an fsync() system call for 536 * cases where write errors are important. 537 */ 538/* ARGSUSED */ 539static int 540nfs_close(ap) 541 struct vop_close_args /* { 542 struct vnodeop_desc *a_desc; 543 struct vnode *a_vp; 544 int a_fflag; 545 struct ucred *a_cred; 546 struct proc *a_p; 547 } */ *ap; 548{ 549 register struct vnode *vp = ap->a_vp; 550 register struct nfsnode *np = VTONFS(vp); 551 int error = 0; 552 553 if (vp->v_type == VREG) { 554 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 555 (np->n_flag & NMODIFIED)) { 556 if (NFS_ISV3(vp)) { 557 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0); 558 np->n_flag &= ~NMODIFIED; 559 } else 560 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 561 np->n_attrstamp = 0; 562 } 563 if (np->n_flag & NWRITEERR) { 564 np->n_flag &= ~NWRITEERR; 565 error = np->n_error; 566 } 567 } 568 return (error); 569} 570 571/* 572 * nfs getattr call from vfs. 573 */ 574static int 575nfs_getattr(ap) 576 struct vop_getattr_args /* { 577 struct vnode *a_vp; 578 struct vattr *a_vap; 579 struct ucred *a_cred; 580 struct proc *a_p; 581 } */ *ap; 582{ 583 register struct vnode *vp = ap->a_vp; 584 register struct nfsnode *np = VTONFS(vp); 585 register caddr_t cp; 586 register u_long *tl; 587 register int t1, t2; 588 caddr_t bpos, dpos; 589 int error = 0; 590 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 591 int v3 = NFS_ISV3(vp); 592 593 /* 594 * Update local times for special files. 595 */ 596 if (np->n_flag & (NACC | NUPD)) 597 np->n_flag |= NCHG; 598 /* 599 * First look in the cache. 600 */ 601 if (nfs_getattrcache(vp, ap->a_vap) == 0) 602 return (0); 603 nfsstats.rpccnt[NFSPROC_GETATTR]++; 604 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3)); 605 nfsm_fhtom(vp, v3); 606 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 607 if (!error) 608 nfsm_loadattr(vp, ap->a_vap); 609 nfsm_reqdone; 610 return (error); 611} 612 613/* 614 * nfs setattr call. 615 */ 616static int 617nfs_setattr(ap) 618 struct vop_setattr_args /* { 619 struct vnodeop_desc *a_desc; 620 struct vnode *a_vp; 621 struct vattr *a_vap; 622 struct ucred *a_cred; 623 struct proc *a_p; 624 } */ *ap; 625{ 626 register struct vnode *vp = ap->a_vp; 627 register struct nfsnode *np = VTONFS(vp); 628 register struct vattr *vap = ap->a_vap; 629 int error = 0; 630 u_quad_t tsize; 631 632#ifndef nolint 633 tsize = (u_quad_t)0; 634#endif 635 /* 636 * Disallow write attempts if the filesystem is mounted read-only. 637 */ 638 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 639 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 640 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && 641 (vp->v_mount->mnt_flag & MNT_RDONLY)) 642 return (EROFS); 643 if (vap->va_size != VNOVAL) { 644 switch (vp->v_type) { 645 case VDIR: 646 return (EISDIR); 647 case VCHR: 648 case VBLK: 649 case VSOCK: 650 case VFIFO: 651 if (vap->va_mtime.tv_sec == VNOVAL && 652 vap->va_atime.tv_sec == VNOVAL && 653 vap->va_mode == (u_short)VNOVAL && 654 vap->va_uid == (uid_t)VNOVAL && 655 vap->va_gid == (gid_t)VNOVAL) 656 return (0); 657 vap->va_size = VNOVAL; 658 break; 659 default: 660 /* 661 * Disallow write attempts if the filesystem is 662 * mounted read-only. 663 */ 664 if (vp->v_mount->mnt_flag & MNT_RDONLY) 665 return (EROFS); 666 if (np->n_flag & NMODIFIED) { 667 if (vap->va_size == 0) 668 error = nfs_vinvalbuf(vp, 0, 669 ap->a_cred, ap->a_p, 1); 670 else 671 error = nfs_vinvalbuf(vp, V_SAVE, 672 ap->a_cred, ap->a_p, 1); 673 if (error) 674 return (error); 675 } 676 tsize = np->n_size; 677 np->n_size = np->n_vattr.va_size = vap->va_size; 678 vnode_pager_setsize(vp, (u_long)np->n_size); 679 }; 680 } else if ((vap->va_mtime.tv_sec != VNOVAL || 681 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) && 682 vp->v_type == VREG && 683 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 684 ap->a_p, 1)) == EINTR) 685 return (error); 686 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p); 687 if (error && vap->va_size != VNOVAL) { 688 np->n_size = np->n_vattr.va_size = tsize; 689 vnode_pager_setsize(vp, (u_long)np->n_size); 690 } 691 return (error); 692} 693 694/* 695 * Do an nfs setattr rpc. 696 */ 697static int 698nfs_setattrrpc(vp, vap, cred, procp) 699 register struct vnode *vp; 700 register struct vattr *vap; 701 struct ucred *cred; 702 struct proc *procp; 703{ 704 register struct nfsv2_sattr *sp; 705 register caddr_t cp; 706 register long t1, t2; 707 caddr_t bpos, dpos, cp2; 708 u_long *tl; 709 int error = 0, wccflag = NFSV3_WCCRATTR; 710 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 711 int v3 = NFS_ISV3(vp); 712 713 nfsstats.rpccnt[NFSPROC_SETATTR]++; 714 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3)); 715 nfsm_fhtom(vp, v3); 716 if (v3) { 717 if (vap->va_mode != (u_short)VNOVAL) { 718 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 719 *tl++ = nfs_true; 720 *tl = txdr_unsigned(vap->va_mode); 721 } else { 722 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 723 *tl = nfs_false; 724 } 725 if (vap->va_uid != (uid_t)VNOVAL) { 726 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 727 *tl++ = nfs_true; 728 *tl = txdr_unsigned(vap->va_uid); 729 } else { 730 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 731 *tl = nfs_false; 732 } 733 if (vap->va_gid != (gid_t)VNOVAL) { 734 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 735 *tl++ = nfs_true; 736 *tl = txdr_unsigned(vap->va_gid); 737 } else { 738 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 739 *tl = nfs_false; 740 } 741 if (vap->va_size != VNOVAL) { 742 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 743 *tl++ = nfs_true; 744 txdr_hyper(&vap->va_size, tl); 745 } else { 746 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 747 *tl = nfs_false; 748 } 749 if (vap->va_atime.tv_sec != VNOVAL) { 750 if (vap->va_atime.tv_sec != time.tv_sec) { 751 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 752 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 753 txdr_nfsv3time(&vap->va_atime, tl); 754 } else { 755 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 756 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 757 } 758 } else { 759 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 760 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 761 } 762 if (vap->va_mtime.tv_sec != VNOVAL) { 763 if (vap->va_mtime.tv_sec != time.tv_sec) { 764 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 765 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 766 txdr_nfsv3time(&vap->va_mtime, tl); 767 } else { 768 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 769 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 770 } 771 } else { 772 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 773 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 774 } 775 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 776 *tl = nfs_false; 777 } else { 778 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 779 if (vap->va_mode == (u_short)VNOVAL) 780 sp->sa_mode = VNOVAL; 781 else 782 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode); 783 if (vap->va_uid == (uid_t)VNOVAL) 784 sp->sa_uid = VNOVAL; 785 else 786 sp->sa_uid = txdr_unsigned(vap->va_uid); 787 if (vap->va_gid == (gid_t)VNOVAL) 788 sp->sa_gid = VNOVAL; 789 else 790 sp->sa_gid = txdr_unsigned(vap->va_gid); 791 sp->sa_size = txdr_unsigned(vap->va_size); 792 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 793 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 794 } 795 nfsm_request(vp, NFSPROC_SETATTR, procp, cred); 796 if (v3) { 797 nfsm_wcc_data(vp, wccflag); 798 } else 799 nfsm_loadattr(vp, (struct vattr *)0); 800 nfsm_reqdone; 801 return (error); 802} 803 804/* 805 * nfs lookup call, one step at a time... 806 * First look in cache 807 * If not found, unlock the directory nfsnode and do the rpc 808 */ 809static int 810nfs_lookup(ap) 811 struct vop_lookup_args /* { 812 struct vnodeop_desc *a_desc; 813 struct vnode *a_dvp; 814 struct vnode **a_vpp; 815 struct componentname *a_cnp; 816 } */ *ap; 817{ 818 register struct componentname *cnp = ap->a_cnp; 819 register struct vnode *dvp = ap->a_dvp; 820 register struct vnode **vpp = ap->a_vpp; 821 register int flags = cnp->cn_flags; 822 register struct vnode *newvp; 823 register u_long *tl; 824 register caddr_t cp; 825 register long t1, t2; 826 struct nfsmount *nmp; 827 caddr_t bpos, dpos, cp2; 828 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 829 long len; 830 nfsfh_t *fhp; 831 struct nfsnode *np; 832 int lockparent, wantparent, error = 0, attrflag, fhsize; 833 int v3 = NFS_ISV3(dvp); 834 struct proc *p = cnp->cn_proc; 835 836 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && 837 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 838 return (EROFS); 839 *vpp = NULLVP; 840 if (dvp->v_type != VDIR) 841 return (ENOTDIR); 842 lockparent = flags & LOCKPARENT; 843 wantparent = flags & (LOCKPARENT|WANTPARENT); 844 nmp = VFSTONFS(dvp->v_mount); 845 np = VTONFS(dvp); 846 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 847 struct vattr vattr; 848 int vpid; 849 850 if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) { 851 *vpp = NULLVP; 852 return (error); 853 } 854 855 newvp = *vpp; 856 vpid = newvp->v_id; 857 /* 858 * See the comment starting `Step through' in ufs/ufs_lookup.c 859 * for an explanation of the locking protocol 860 */ 861 if (dvp == newvp) { 862 VREF(newvp); 863 error = 0; 864 } else if (flags & ISDOTDOT) { 865 VOP_UNLOCK(dvp, 0, p); 866 error = vget(newvp, LK_EXCLUSIVE, p); 867 if (!error && lockparent && (flags & ISLASTCN)) 868 error = vn_lock(dvp, LK_EXCLUSIVE, p); 869 } else { 870 error = vget(newvp, LK_EXCLUSIVE, p); 871 if (!lockparent || error || !(flags & ISLASTCN)) 872 VOP_UNLOCK(dvp, 0, p); 873 } 874 if (!error) { 875 if (vpid == newvp->v_id) { 876 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p) 877 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { 878 nfsstats.lookupcache_hits++; 879 if (cnp->cn_nameiop != LOOKUP && 880 (flags & ISLASTCN)) 881 cnp->cn_flags |= SAVENAME; 882 return (0); 883 } 884 cache_purge(newvp); 885 } 886 vput(newvp); 887 if (lockparent && dvp != newvp && (flags & ISLASTCN)) 888 VOP_UNLOCK(dvp, 0, p); 889 } 890 error = vn_lock(dvp, LK_EXCLUSIVE, p); 891 *vpp = NULLVP; 892 if (error) 893 return (error); 894 } 895 error = 0; 896 newvp = NULLVP; 897 nfsstats.lookupcache_misses++; 898 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 899 len = cnp->cn_namelen; 900 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 901 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 902 nfsm_fhtom(dvp, v3); 903 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 904 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 905 if (error) { 906 nfsm_postop_attr(dvp, attrflag); 907 m_freem(mrep); 908 goto nfsmout; 909 } 910 nfsm_getfh(fhp, fhsize, v3); 911 912 /* 913 * Handle RENAME case... 914 */ 915 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 916 if (NFS_CMPFH(np, fhp, fhsize)) { 917 m_freem(mrep); 918 return (EISDIR); 919 } 920 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 921 m_freem(mrep); 922 return (error); 923 } 924 newvp = NFSTOV(np); 925 if (v3) { 926 nfsm_postop_attr(newvp, attrflag); 927 nfsm_postop_attr(dvp, attrflag); 928 } else 929 nfsm_loadattr(newvp, (struct vattr *)0); 930 *vpp = newvp; 931 m_freem(mrep); 932 cnp->cn_flags |= SAVENAME; 933 if (!lockparent) 934 VOP_UNLOCK(dvp, 0, p); 935 return (0); 936 } 937 938 if (flags & ISDOTDOT) { 939 VOP_UNLOCK(dvp, 0, p); 940 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 941 if (error) { 942 vn_lock(dvp, LK_EXCLUSIVE + LK_RETRY, p); 943 return (error); 944 } 945 newvp = NFSTOV(np); 946 if (lockparent && (flags & ISLASTCN) && 947 (error = vn_lock(dvp, LK_EXCLUSIVE, p))) { 948 vput(newvp); 949 return (error); 950 } 951 } else if (NFS_CMPFH(np, fhp, fhsize)) { 952 VREF(dvp); 953 newvp = dvp; 954 } else { 955 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 956 m_freem(mrep); 957 return (error); 958 } 959 if (!lockparent || !(flags & ISLASTCN)) 960 VOP_UNLOCK(dvp, 0, p); 961 newvp = NFSTOV(np); 962 } 963 if (v3) { 964 nfsm_postop_attr(newvp, attrflag); 965 nfsm_postop_attr(dvp, attrflag); 966 } else 967 nfsm_loadattr(newvp, (struct vattr *)0); 968 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 969 cnp->cn_flags |= SAVENAME; 970 if ((cnp->cn_flags & MAKEENTRY) && 971 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 972 np->n_ctime = np->n_vattr.va_ctime.tv_sec; 973 cache_enter(dvp, newvp, cnp); 974 } 975 *vpp = newvp; 976 nfsm_reqdone; 977 if (error) { 978 if (newvp != NULLVP) { 979 vrele(newvp); 980 *vpp = NULLVP; 981 } 982 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 983 (flags & ISLASTCN) && error == ENOENT) { 984 if (!lockparent) 985 VOP_UNLOCK(dvp, 0, p); 986 if (dvp->v_mount->mnt_flag & MNT_RDONLY) 987 error = EROFS; 988 else 989 error = EJUSTRETURN; 990 } 991 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 992 cnp->cn_flags |= SAVENAME; 993 } 994 return (error); 995} 996 997/* 998 * nfs read call. 999 * Just call nfs_bioread() to do the work. 1000 */ 1001static int 1002nfs_read(ap) 1003 struct vop_read_args /* { 1004 struct vnode *a_vp; 1005 struct uio *a_uio; 1006 int a_ioflag; 1007 struct ucred *a_cred; 1008 } */ *ap; 1009{ 1010 register struct vnode *vp = ap->a_vp; 1011 1012 if (vp->v_type != VREG) 1013 return (EPERM); 1014 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0)); 1015} 1016 1017/* 1018 * nfs readlink call 1019 */ 1020static int 1021nfs_readlink(ap) 1022 struct vop_readlink_args /* { 1023 struct vnode *a_vp; 1024 struct uio *a_uio; 1025 struct ucred *a_cred; 1026 } */ *ap; 1027{ 1028 register struct vnode *vp = ap->a_vp; 1029 1030 if (vp->v_type != VLNK) 1031 return (EPERM); 1032 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0)); 1033} 1034 1035/* 1036 * Do a readlink rpc. 1037 * Called by nfs_doio() from below the buffer cache. 1038 */ 1039int 1040nfs_readlinkrpc(vp, uiop, cred) 1041 register struct vnode *vp; 1042 struct uio *uiop; 1043 struct ucred *cred; 1044{ 1045 register u_long *tl; 1046 register caddr_t cp; 1047 register long t1, t2; 1048 caddr_t bpos, dpos, cp2; 1049 int error = 0, len, attrflag; 1050 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1051 int v3 = NFS_ISV3(vp); 1052 1053 nfsstats.rpccnt[NFSPROC_READLINK]++; 1054 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3)); 1055 nfsm_fhtom(vp, v3); 1056 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 1057 if (v3) 1058 nfsm_postop_attr(vp, attrflag); 1059 if (!error) { 1060 nfsm_strsiz(len, NFS_MAXPATHLEN); 1061 nfsm_mtouio(uiop, len); 1062 } 1063 nfsm_reqdone; 1064 return (error); 1065} 1066 1067/* 1068 * nfs read rpc call 1069 * Ditto above 1070 */ 1071int 1072nfs_readrpc(vp, uiop, cred) 1073 register struct vnode *vp; 1074 struct uio *uiop; 1075 struct ucred *cred; 1076{ 1077 register u_long *tl; 1078 register caddr_t cp; 1079 register long t1, t2; 1080 caddr_t bpos, dpos, cp2; 1081 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1082 struct nfsmount *nmp; 1083 int error = 0, len, retlen, tsiz, eof, attrflag; 1084 int v3 = NFS_ISV3(vp); 1085 1086#ifndef nolint 1087 eof = 0; 1088#endif 1089 nmp = VFSTONFS(vp->v_mount); 1090 tsiz = uiop->uio_resid; 1091 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 1092 return (EFBIG); 1093 while (tsiz > 0) { 1094 nfsstats.rpccnt[NFSPROC_READ]++; 1095 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 1096 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3); 1097 nfsm_fhtom(vp, v3); 1098 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3); 1099 if (v3) { 1100 txdr_hyper(&uiop->uio_offset, tl); 1101 *(tl + 2) = txdr_unsigned(len); 1102 } else { 1103 *tl++ = txdr_unsigned(uiop->uio_offset); 1104 *tl++ = txdr_unsigned(len); 1105 *tl = 0; 1106 } 1107 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 1108 if (v3) { 1109 nfsm_postop_attr(vp, attrflag); 1110 if (error) { 1111 m_freem(mrep); 1112 goto nfsmout; 1113 } 1114 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1115 eof = fxdr_unsigned(int, *(tl + 1)); 1116 } else 1117 nfsm_loadattr(vp, (struct vattr *)0); 1118 nfsm_strsiz(retlen, nmp->nm_rsize); 1119 nfsm_mtouio(uiop, retlen); 1120 m_freem(mrep); 1121 tsiz -= retlen; 1122 if (v3) { 1123 if (eof || retlen == 0) 1124 tsiz = 0; 1125 } else if (retlen < len) 1126 tsiz = 0; 1127 } 1128nfsmout: 1129 return (error); 1130} 1131 1132/* 1133 * nfs write call 1134 */ 1135int 1136nfs_writerpc(vp, uiop, cred, iomode, must_commit) 1137 register struct vnode *vp; 1138 register struct uio *uiop; 1139 struct ucred *cred; 1140 int *iomode, *must_commit; 1141{ 1142 register u_long *tl; 1143 register caddr_t cp; 1144 register int t1, t2, backup; 1145 caddr_t bpos, dpos, cp2; 1146 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1147 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1148 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit; 1149 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC; 1150 1151#ifndef DIAGNOSTIC 1152 if (uiop->uio_iovcnt != 1) 1153 panic("nfs: writerpc iovcnt > 1"); 1154#endif 1155 *must_commit = 0; 1156 tsiz = uiop->uio_resid; 1157 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 1158 return (EFBIG); 1159 while (tsiz > 0) { 1160 nfsstats.rpccnt[NFSPROC_WRITE]++; 1161 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 1162 nfsm_reqhead(vp, NFSPROC_WRITE, 1163 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 1164 nfsm_fhtom(vp, v3); 1165 if (v3) { 1166 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 1167 txdr_hyper(&uiop->uio_offset, tl); 1168 tl += 2; 1169 *tl++ = txdr_unsigned(len); 1170 *tl++ = txdr_unsigned(*iomode); 1171 } else { 1172 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED); 1173 *++tl = txdr_unsigned(uiop->uio_offset); 1174 tl += 2; 1175 } 1176 *tl = txdr_unsigned(len); 1177 nfsm_uiotom(uiop, len); 1178 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 1179 if (v3) { 1180 wccflag = NFSV3_WCCCHK; 1181 nfsm_wcc_data(vp, wccflag); 1182 if (!error) { 1183 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED + 1184 NFSX_V3WRITEVERF); 1185 rlen = fxdr_unsigned(int, *tl++); 1186 if (rlen == 0) { 1187 error = NFSERR_IO; 1188 break; 1189 } else if (rlen < len) { 1190 backup = len - rlen; 1191 uiop->uio_iov->iov_base -= backup; 1192 uiop->uio_iov->iov_len += backup; 1193 uiop->uio_offset -= backup; 1194 uiop->uio_resid += backup; 1195 len = rlen; 1196 } 1197 commit = fxdr_unsigned(int, *tl++); 1198 1199 /* 1200 * Return the lowest committment level 1201 * obtained by any of the RPCs. 1202 */ 1203 if (committed == NFSV3WRITE_FILESYNC) 1204 committed = commit; 1205 else if (committed == NFSV3WRITE_DATASYNC && 1206 commit == NFSV3WRITE_UNSTABLE) 1207 committed = commit; 1208 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) { 1209 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1210 NFSX_V3WRITEVERF); 1211 nmp->nm_flag |= NFSMNT_HASWRITEVERF; 1212 } else if (bcmp((caddr_t)tl, 1213 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) { 1214 *must_commit = 1; 1215 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1216 NFSX_V3WRITEVERF); 1217 } 1218 } 1219 } else 1220 nfsm_loadattr(vp, (struct vattr *)0); 1221 if (wccflag) 1222 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec; 1223 m_freem(mrep); 1224 tsiz -= len; 1225 } 1226nfsmout: 1227 if (vp->v_mount->mnt_flag & MNT_ASYNC) 1228 committed = NFSV3WRITE_FILESYNC; 1229 *iomode = committed; 1230 if (error) 1231 uiop->uio_resid = tsiz; 1232 return (error); 1233} 1234 1235/* 1236 * nfs mknod rpc 1237 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1238 * mode set to specify the file type and the size field for rdev. 1239 */ 1240static int 1241nfs_mknodrpc(dvp, vpp, cnp, vap) 1242 register struct vnode *dvp; 1243 register struct vnode **vpp; 1244 register struct componentname *cnp; 1245 register struct vattr *vap; 1246{ 1247 register struct nfsv2_sattr *sp; 1248 register struct nfsv3_sattr *sp3; 1249 register u_long *tl; 1250 register caddr_t cp; 1251 register long t1, t2; 1252 struct vnode *newvp = (struct vnode *)0; 1253 struct nfsnode *np = (struct nfsnode *)0; 1254 struct vattr vattr; 1255 char *cp2; 1256 caddr_t bpos, dpos; 1257 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0; 1258 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1259 u_long rdev; 1260 int v3 = NFS_ISV3(dvp); 1261 1262 if (vap->va_type == VCHR || vap->va_type == VBLK) 1263 rdev = txdr_unsigned(vap->va_rdev); 1264 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1265 rdev = 0xffffffff; 1266 else { 1267 VOP_ABORTOP(dvp, cnp); 1268 vput(dvp); 1269 return (EOPNOTSUPP); 1270 } 1271 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1272 VOP_ABORTOP(dvp, cnp); 1273 vput(dvp); 1274 return (error); 1275 } 1276 nfsstats.rpccnt[NFSPROC_MKNOD]++; 1277 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED + 1278 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1279 nfsm_fhtom(dvp, v3); 1280 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1281 if (v3) { 1282 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR); 1283 *tl++ = vtonfsv3_type(vap->va_type); 1284 sp3 = (struct nfsv3_sattr *)tl; 1285 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1286 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1287 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1288 *tl++ = txdr_unsigned(major(vap->va_rdev)); 1289 *tl = txdr_unsigned(minor(vap->va_rdev)); 1290 } 1291 } else { 1292 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1293 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1294 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1295 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1296 sp->sa_size = rdev; 1297 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1298 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1299 } 1300 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred); 1301 if (!error) { 1302 nfsm_mtofh(dvp, newvp, v3, gotvp); 1303 if (!gotvp) { 1304 if (newvp) { 1305 vput(newvp); 1306 newvp = (struct vnode *)0; 1307 } 1308 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1309 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1310 if (!error) 1311 newvp = NFSTOV(np); 1312 } 1313 } 1314 if (v3) 1315 nfsm_wcc_data(dvp, wccflag); 1316 nfsm_reqdone; 1317 if (error) { 1318 if (newvp) 1319 vput(newvp); 1320 } else { 1321 if (cnp->cn_flags & MAKEENTRY) 1322 cache_enter(dvp, newvp, cnp); 1323 *vpp = newvp; 1324 } 1325 zfree(namei_zone, cnp->cn_pnbuf); 1326 VTONFS(dvp)->n_flag |= NMODIFIED; 1327 if (!wccflag) 1328 VTONFS(dvp)->n_attrstamp = 0; 1329 vput(dvp); 1330 return (error); 1331} 1332 1333/* 1334 * nfs mknod vop 1335 * just call nfs_mknodrpc() to do the work. 1336 */ 1337/* ARGSUSED */ 1338static int 1339nfs_mknod(ap) 1340 struct vop_mknod_args /* { 1341 struct vnode *a_dvp; 1342 struct vnode **a_vpp; 1343 struct componentname *a_cnp; 1344 struct vattr *a_vap; 1345 } */ *ap; 1346{ 1347 struct vnode *newvp; 1348 int error; 1349 1350 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap); 1351 if (!error) 1352 vput(newvp); 1353 return (error); 1354} 1355 1356static u_long create_verf; 1357/* 1358 * nfs file create call 1359 */ 1360static int 1361nfs_create(ap) 1362 struct vop_create_args /* { 1363 struct vnode *a_dvp; 1364 struct vnode **a_vpp; 1365 struct componentname *a_cnp; 1366 struct vattr *a_vap; 1367 } */ *ap; 1368{ 1369 register struct vnode *dvp = ap->a_dvp; 1370 register struct vattr *vap = ap->a_vap; 1371 register struct componentname *cnp = ap->a_cnp; 1372 register struct nfsv2_sattr *sp; 1373 register struct nfsv3_sattr *sp3; 1374 register u_long *tl; 1375 register caddr_t cp; 1376 register long t1, t2; 1377 struct nfsnode *np = (struct nfsnode *)0; 1378 struct vnode *newvp = (struct vnode *)0; 1379 caddr_t bpos, dpos, cp2; 1380 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0; 1381 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1382 struct vattr vattr; 1383 int v3 = NFS_ISV3(dvp); 1384 1385 /* 1386 * Oops, not for me.. 1387 */ 1388 if (vap->va_type == VSOCK) 1389 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1390 1391 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1392 VOP_ABORTOP(dvp, cnp); 1393 vput(dvp); 1394 return (error); 1395 } 1396 if (vap->va_vaflags & VA_EXCLUSIVE) 1397 fmode |= O_EXCL; 1398again: 1399 nfsstats.rpccnt[NFSPROC_CREATE]++; 1400 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED + 1401 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1402 nfsm_fhtom(dvp, v3); 1403 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1404 if (v3) { 1405 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 1406 if (fmode & O_EXCL) { 1407 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); 1408 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF); 1409 if (!TAILQ_EMPTY(&in_ifaddrhead)) 1410 *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr; 1411 else 1412 *tl++ = create_verf; 1413 *tl = ++create_verf; 1414 } else { 1415 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED); 1416 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR); 1417 sp3 = (struct nfsv3_sattr *)tl; 1418 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1419 } 1420 } else { 1421 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1422 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1423 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1424 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1425 sp->sa_size = 0; 1426 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1427 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1428 } 1429 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1430 if (!error) { 1431 nfsm_mtofh(dvp, newvp, v3, gotvp); 1432 if (!gotvp) { 1433 if (newvp) { 1434 vput(newvp); 1435 newvp = (struct vnode *)0; 1436 } 1437 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1438 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1439 if (!error) 1440 newvp = NFSTOV(np); 1441 } 1442 } 1443 if (v3) 1444 nfsm_wcc_data(dvp, wccflag); 1445 nfsm_reqdone; 1446 if (error) { 1447 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) { 1448 fmode &= ~O_EXCL; 1449 goto again; 1450 } 1451 if (newvp) 1452 vput(newvp); 1453 } else if (v3 && (fmode & O_EXCL)) 1454 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc); 1455 if (!error) { 1456 if (cnp->cn_flags & MAKEENTRY) 1457 cache_enter(dvp, newvp, cnp); 1458 *ap->a_vpp = newvp; 1459 } 1460 zfree(namei_zone, cnp->cn_pnbuf); 1461 VTONFS(dvp)->n_flag |= NMODIFIED; 1462 if (!wccflag) 1463 VTONFS(dvp)->n_attrstamp = 0; 1464 vput(dvp); 1465 return (error); 1466} 1467 1468/* 1469 * nfs file remove call 1470 * To try and make nfs semantics closer to ufs semantics, a file that has 1471 * other processes using the vnode is renamed instead of removed and then 1472 * removed later on the last close. 1473 * - If v_usecount > 1 1474 * If a rename is not already in the works 1475 * call nfs_sillyrename() to set it up 1476 * else 1477 * do the remove rpc 1478 */ 1479static int 1480nfs_remove(ap) 1481 struct vop_remove_args /* { 1482 struct vnodeop_desc *a_desc; 1483 struct vnode * a_dvp; 1484 struct vnode * a_vp; 1485 struct componentname * a_cnp; 1486 } */ *ap; 1487{ 1488 register struct vnode *vp = ap->a_vp; 1489 register struct vnode *dvp = ap->a_dvp; 1490 register struct componentname *cnp = ap->a_cnp; 1491 register struct nfsnode *np = VTONFS(vp); 1492 int error = 0; 1493 struct vattr vattr; 1494 1495#ifndef DIAGNOSTIC 1496 if ((cnp->cn_flags & HASBUF) == 0) 1497 panic("nfs_remove: no name"); 1498 if (vp->v_usecount < 1) 1499 panic("nfs_remove: bad v_usecount"); 1500#endif 1501 if (vp->v_usecount == 1 || (np->n_sillyrename && 1502 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 && 1503 vattr.va_nlink > 1)) { 1504 /* 1505 * Purge the name cache so that the chance of a lookup for 1506 * the name succeeding while the remove is in progress is 1507 * minimized. Without node locking it can still happen, such 1508 * that an I/O op returns ESTALE, but since you get this if 1509 * another host removes the file.. 1510 */ 1511 cache_purge(vp); 1512 /* 1513 * throw away biocache buffers, mainly to avoid 1514 * unnecessary delayed writes later. 1515 */ 1516 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1517 /* Do the rpc */ 1518 if (error != EINTR) 1519 error = nfs_removerpc(dvp, cnp->cn_nameptr, 1520 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); 1521 /* 1522 * Kludge City: If the first reply to the remove rpc is lost.. 1523 * the reply to the retransmitted request will be ENOENT 1524 * since the file was in fact removed 1525 * Therefore, we cheat and return success. 1526 */ 1527 if (error == ENOENT) 1528 error = 0; 1529 } else if (!np->n_sillyrename) 1530 error = nfs_sillyrename(dvp, vp, cnp); 1531 zfree(namei_zone, cnp->cn_pnbuf); 1532 np->n_attrstamp = 0; 1533 vput(dvp); 1534 if (vp == dvp) 1535 vrele(vp); 1536 else 1537 vput(vp); 1538 return (error); 1539} 1540 1541/* 1542 * nfs file remove rpc called from nfs_inactive 1543 */ 1544int 1545nfs_removeit(sp) 1546 register struct sillyrename *sp; 1547{ 1548 1549 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, 1550 (struct proc *)0)); 1551} 1552 1553/* 1554 * Nfs remove rpc, called from nfs_remove() and nfs_removeit(). 1555 */ 1556static int 1557nfs_removerpc(dvp, name, namelen, cred, proc) 1558 register struct vnode *dvp; 1559 char *name; 1560 int namelen; 1561 struct ucred *cred; 1562 struct proc *proc; 1563{ 1564 register u_long *tl; 1565 register caddr_t cp; 1566 register long t1, t2; 1567 caddr_t bpos, dpos, cp2; 1568 int error = 0, wccflag = NFSV3_WCCRATTR; 1569 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1570 int v3 = NFS_ISV3(dvp); 1571 1572 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1573 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1574 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 1575 nfsm_fhtom(dvp, v3); 1576 nfsm_strtom(name, namelen, NFS_MAXNAMLEN); 1577 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred); 1578 if (v3) 1579 nfsm_wcc_data(dvp, wccflag); 1580 nfsm_reqdone; 1581 VTONFS(dvp)->n_flag |= NMODIFIED; 1582 if (!wccflag) 1583 VTONFS(dvp)->n_attrstamp = 0; 1584 return (error); 1585} 1586 1587/* 1588 * nfs file rename call 1589 */ 1590static int 1591nfs_rename(ap) 1592 struct vop_rename_args /* { 1593 struct vnode *a_fdvp; 1594 struct vnode *a_fvp; 1595 struct componentname *a_fcnp; 1596 struct vnode *a_tdvp; 1597 struct vnode *a_tvp; 1598 struct componentname *a_tcnp; 1599 } */ *ap; 1600{ 1601 register struct vnode *fvp = ap->a_fvp; 1602 register struct vnode *tvp = ap->a_tvp; 1603 register struct vnode *fdvp = ap->a_fdvp; 1604 register struct vnode *tdvp = ap->a_tdvp; 1605 register struct componentname *tcnp = ap->a_tcnp; 1606 register struct componentname *fcnp = ap->a_fcnp; 1607 int error; 1608 1609#ifndef DIAGNOSTIC 1610 if ((tcnp->cn_flags & HASBUF) == 0 || 1611 (fcnp->cn_flags & HASBUF) == 0) 1612 panic("nfs_rename: no name"); 1613#endif 1614 /* Check for cross-device rename */ 1615 if ((fvp->v_mount != tdvp->v_mount) || 1616 (tvp && (fvp->v_mount != tvp->v_mount))) { 1617 error = EXDEV; 1618 goto out; 1619 } 1620 1621 /* 1622 * If the tvp exists and is in use, sillyrename it before doing the 1623 * rename of the new file over it. 1624 * XXX Can't sillyrename a directory. 1625 */ 1626 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && 1627 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { 1628 vput(tvp); 1629 tvp = NULL; 1630 } 1631 1632 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1633 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1634 tcnp->cn_proc); 1635 1636 if (fvp->v_type == VDIR) { 1637 if (tvp != NULL && tvp->v_type == VDIR) 1638 cache_purge(tdvp); 1639 cache_purge(fdvp); 1640 } 1641out: 1642 if (tdvp == tvp) 1643 vrele(tdvp); 1644 else 1645 vput(tdvp); 1646 if (tvp) 1647 vput(tvp); 1648 vrele(fdvp); 1649 vrele(fvp); 1650 /* 1651 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1652 */ 1653 if (error == ENOENT) 1654 error = 0; 1655 return (error); 1656} 1657 1658/* 1659 * nfs file rename rpc called from nfs_remove() above 1660 */ 1661static int 1662nfs_renameit(sdvp, scnp, sp) 1663 struct vnode *sdvp; 1664 struct componentname *scnp; 1665 register struct sillyrename *sp; 1666{ 1667 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, 1668 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc)); 1669} 1670 1671/* 1672 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1673 */ 1674static int 1675nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc) 1676 register struct vnode *fdvp; 1677 char *fnameptr; 1678 int fnamelen; 1679 register struct vnode *tdvp; 1680 char *tnameptr; 1681 int tnamelen; 1682 struct ucred *cred; 1683 struct proc *proc; 1684{ 1685 register u_long *tl; 1686 register caddr_t cp; 1687 register long t1, t2; 1688 caddr_t bpos, dpos, cp2; 1689 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; 1690 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1691 int v3 = NFS_ISV3(fdvp); 1692 1693 nfsstats.rpccnt[NFSPROC_RENAME]++; 1694 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1695 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) + 1696 nfsm_rndup(tnamelen)); 1697 nfsm_fhtom(fdvp, v3); 1698 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); 1699 nfsm_fhtom(tdvp, v3); 1700 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); 1701 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred); 1702 if (v3) { 1703 nfsm_wcc_data(fdvp, fwccflag); 1704 nfsm_wcc_data(tdvp, twccflag); 1705 } 1706 nfsm_reqdone; 1707 VTONFS(fdvp)->n_flag |= NMODIFIED; 1708 VTONFS(tdvp)->n_flag |= NMODIFIED; 1709 if (!fwccflag) 1710 VTONFS(fdvp)->n_attrstamp = 0; 1711 if (!twccflag) 1712 VTONFS(tdvp)->n_attrstamp = 0; 1713 return (error); 1714} 1715 1716/* 1717 * nfs hard link create call 1718 */ 1719static int 1720nfs_link(ap) 1721 struct vop_link_args /* { 1722 struct vnode *a_tdvp; 1723 struct vnode *a_vp; 1724 struct componentname *a_cnp; 1725 } */ *ap; 1726{ 1727 register struct vnode *vp = ap->a_vp; 1728 register struct vnode *tdvp = ap->a_tdvp; 1729 register struct componentname *cnp = ap->a_cnp; 1730 register u_long *tl; 1731 register caddr_t cp; 1732 register long t1, t2; 1733 caddr_t bpos, dpos, cp2; 1734 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0; 1735 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1736 int v3 = NFS_ISV3(vp); 1737 1738 if (vp->v_mount != tdvp->v_mount) { 1739 VOP_ABORTOP(vp, cnp); 1740 if (tdvp == vp) 1741 vrele(tdvp); 1742 else 1743 vput(tdvp); 1744 return (EXDEV); 1745 } 1746 1747 /* 1748 * Push all writes to the server, so that the attribute cache 1749 * doesn't get "out of sync" with the server. 1750 * XXX There should be a better way! 1751 */ 1752 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1753 1754 nfsstats.rpccnt[NFSPROC_LINK]++; 1755 nfsm_reqhead(vp, NFSPROC_LINK, 1756 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1757 nfsm_fhtom(vp, v3); 1758 nfsm_fhtom(tdvp, v3); 1759 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1760 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1761 if (v3) { 1762 nfsm_postop_attr(vp, attrflag); 1763 nfsm_wcc_data(tdvp, wccflag); 1764 } 1765 nfsm_reqdone; 1766 zfree(namei_zone, cnp->cn_pnbuf); 1767 VTONFS(tdvp)->n_flag |= NMODIFIED; 1768 if (!attrflag) 1769 VTONFS(vp)->n_attrstamp = 0; 1770 if (!wccflag) 1771 VTONFS(tdvp)->n_attrstamp = 0; 1772 vput(tdvp); 1773 /* 1774 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1775 */ 1776 if (error == EEXIST) 1777 error = 0; 1778 return (error); 1779} 1780 1781/* 1782 * nfs symbolic link create call 1783 */ 1784static int 1785nfs_symlink(ap) 1786 struct vop_symlink_args /* { 1787 struct vnode *a_dvp; 1788 struct vnode **a_vpp; 1789 struct componentname *a_cnp; 1790 struct vattr *a_vap; 1791 char *a_target; 1792 } */ *ap; 1793{ 1794 register struct vnode *dvp = ap->a_dvp; 1795 register struct vattr *vap = ap->a_vap; 1796 register struct componentname *cnp = ap->a_cnp; 1797 register struct nfsv2_sattr *sp; 1798 register struct nfsv3_sattr *sp3; 1799 register u_long *tl; 1800 register caddr_t cp; 1801 register long t1, t2; 1802 caddr_t bpos, dpos, cp2; 1803 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp; 1804 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1805 struct vnode *newvp = (struct vnode *)0; 1806 int v3 = NFS_ISV3(dvp); 1807 1808 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1809 slen = strlen(ap->a_target); 1810 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED + 1811 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3)); 1812 nfsm_fhtom(dvp, v3); 1813 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1814 if (v3) { 1815 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1816 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, 1817 cnp->cn_cred->cr_gid); 1818 } 1819 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1820 if (!v3) { 1821 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1822 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode); 1823 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1824 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1825 sp->sa_size = -1; 1826 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1827 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1828 } 1829 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1830 if (v3) { 1831 if (!error) 1832 nfsm_mtofh(dvp, newvp, v3, gotvp); 1833 nfsm_wcc_data(dvp, wccflag); 1834 } 1835 nfsm_reqdone; 1836 if (newvp) 1837 vput(newvp); 1838 zfree(namei_zone, cnp->cn_pnbuf); 1839 VTONFS(dvp)->n_flag |= NMODIFIED; 1840 if (!wccflag) 1841 VTONFS(dvp)->n_attrstamp = 0; 1842 vput(dvp); 1843 /* 1844 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1845 */ 1846 if (error == EEXIST) 1847 error = 0; 1848 return (error); 1849} 1850 1851/* 1852 * nfs make dir call 1853 */ 1854static int 1855nfs_mkdir(ap) 1856 struct vop_mkdir_args /* { 1857 struct vnode *a_dvp; 1858 struct vnode **a_vpp; 1859 struct componentname *a_cnp; 1860 struct vattr *a_vap; 1861 } */ *ap; 1862{ 1863 register struct vnode *dvp = ap->a_dvp; 1864 register struct vattr *vap = ap->a_vap; 1865 register struct componentname *cnp = ap->a_cnp; 1866 register struct nfsv2_sattr *sp; 1867 register struct nfsv3_sattr *sp3; 1868 register u_long *tl; 1869 register caddr_t cp; 1870 register long t1, t2; 1871 register int len; 1872 struct nfsnode *np = (struct nfsnode *)0; 1873 struct vnode *newvp = (struct vnode *)0; 1874 caddr_t bpos, dpos, cp2; 1875 int error = 0, wccflag = NFSV3_WCCRATTR; 1876 int gotvp = 0; 1877 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1878 struct vattr vattr; 1879 int v3 = NFS_ISV3(dvp); 1880 1881 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1882 VOP_ABORTOP(dvp, cnp); 1883 vput(dvp); 1884 return (error); 1885 } 1886 len = cnp->cn_namelen; 1887 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1888 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1889 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3)); 1890 nfsm_fhtom(dvp, v3); 1891 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1892 if (v3) { 1893 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1894 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1895 } else { 1896 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1897 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); 1898 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1899 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1900 sp->sa_size = -1; 1901 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1902 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1903 } 1904 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1905 if (!error) 1906 nfsm_mtofh(dvp, newvp, v3, gotvp); 1907 if (v3) 1908 nfsm_wcc_data(dvp, wccflag); 1909 nfsm_reqdone; 1910 VTONFS(dvp)->n_flag |= NMODIFIED; 1911 if (!wccflag) 1912 VTONFS(dvp)->n_attrstamp = 0; 1913 /* 1914 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1915 * if we can succeed in looking up the directory. 1916 */ 1917 if (error == EEXIST || (!error && !gotvp)) { 1918 if (newvp) { 1919 vrele(newvp); 1920 newvp = (struct vnode *)0; 1921 } 1922 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, 1923 cnp->cn_proc, &np); 1924 if (!error) { 1925 newvp = NFSTOV(np); 1926 if (newvp->v_type != VDIR) 1927 error = EEXIST; 1928 } 1929 } 1930 if (error) { 1931 if (newvp) 1932 vrele(newvp); 1933 } else 1934 *ap->a_vpp = newvp; 1935 zfree(namei_zone, cnp->cn_pnbuf); 1936 vput(dvp); 1937 return (error); 1938} 1939 1940/* 1941 * nfs remove directory call 1942 */ 1943static int 1944nfs_rmdir(ap) 1945 struct vop_rmdir_args /* { 1946 struct vnode *a_dvp; 1947 struct vnode *a_vp; 1948 struct componentname *a_cnp; 1949 } */ *ap; 1950{ 1951 register struct vnode *vp = ap->a_vp; 1952 register struct vnode *dvp = ap->a_dvp; 1953 register struct componentname *cnp = ap->a_cnp; 1954 register u_long *tl; 1955 register caddr_t cp; 1956 register long t1, t2; 1957 caddr_t bpos, dpos, cp2; 1958 int error = 0, wccflag = NFSV3_WCCRATTR; 1959 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1960 int v3 = NFS_ISV3(dvp); 1961 1962 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1963 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1964 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1965 nfsm_fhtom(dvp, v3); 1966 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1967 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1968 if (v3) 1969 nfsm_wcc_data(dvp, wccflag); 1970 nfsm_reqdone; 1971 zfree(namei_zone, cnp->cn_pnbuf); 1972 VTONFS(dvp)->n_flag |= NMODIFIED; 1973 if (!wccflag) 1974 VTONFS(dvp)->n_attrstamp = 0; 1975 cache_purge(dvp); 1976 cache_purge(vp); 1977 vput(vp); 1978 vput(dvp); 1979 /* 1980 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1981 */ 1982 if (error == ENOENT) 1983 error = 0; 1984 return (error); 1985} 1986 1987/* 1988 * nfs readdir call 1989 */ 1990static int 1991nfs_readdir(ap) 1992 struct vop_readdir_args /* { 1993 struct vnode *a_vp; 1994 struct uio *a_uio; 1995 struct ucred *a_cred; 1996 } */ *ap; 1997{ 1998 register struct vnode *vp = ap->a_vp; 1999 register struct nfsnode *np = VTONFS(vp); 2000 register struct uio *uio = ap->a_uio; 2001 int tresid, error; 2002 struct vattr vattr; 2003 2004 if (vp->v_type != VDIR) 2005 return (EPERM); 2006 /* 2007 * First, check for hit on the EOF offset cache 2008 */ 2009 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && 2010 (np->n_flag & NMODIFIED) == 0) { 2011 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 2012 if (NQNFS_CKCACHABLE(vp, ND_READ)) { 2013 nfsstats.direofcache_hits++; 2014 return (0); 2015 } 2016 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 2017 np->n_mtime == vattr.va_mtime.tv_sec) { 2018 nfsstats.direofcache_hits++; 2019 return (0); 2020 } 2021 } 2022 2023 /* 2024 * Call nfs_bioread() to do the real work. 2025 */ 2026 tresid = uio->uio_resid; 2027 error = nfs_bioread(vp, uio, 0, ap->a_cred, 0); 2028 2029 if (!error && uio->uio_resid == tresid) 2030 nfsstats.direofcache_misses++; 2031 return (error); 2032} 2033 2034/* 2035 * Readdir rpc call. 2036 * Called from below the buffer cache by nfs_doio(). 2037 */ 2038int 2039nfs_readdirrpc(vp, uiop, cred) 2040 struct vnode *vp; 2041 register struct uio *uiop; 2042 struct ucred *cred; 2043 2044{ 2045 register int len, left; 2046 register struct dirent *dp; 2047 register u_long *tl; 2048 register caddr_t cp; 2049 register long t1, t2; 2050 register nfsuint64 *cookiep; 2051 caddr_t bpos, dpos, cp2; 2052 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2053 nfsuint64 cookie; 2054 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2055 struct nfsnode *dnp = VTONFS(vp); 2056 u_quad_t fileno; 2057 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; 2058 int attrflag; 2059 int v3 = NFS_ISV3(vp); 2060 2061#ifndef nolint 2062 dp = (struct dirent *)0; 2063#endif 2064#ifndef DIAGNOSTIC 2065 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) || 2066 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 2067 panic("nfs readdirrpc bad uio"); 2068#endif 2069 2070 /* 2071 * If there is no cookie, assume directory was stale. 2072 */ 2073 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2074 if (cookiep) 2075 cookie = *cookiep; 2076 else 2077 return (NFSERR_BAD_COOKIE); 2078 /* 2079 * Loop around doing readdir rpc's of size nm_readdirsize 2080 * truncated to a multiple of DIRBLKSIZ. 2081 * The stopping criteria is EOF or buffer full. 2082 */ 2083 while (more_dirs && bigenough) { 2084 nfsstats.rpccnt[NFSPROC_READDIR]++; 2085 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) + 2086 NFSX_READDIR(v3)); 2087 nfsm_fhtom(vp, v3); 2088 if (v3) { 2089 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 2090 *tl++ = cookie.nfsuquad[0]; 2091 *tl++ = cookie.nfsuquad[1]; 2092 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2093 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2094 } else { 2095 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 2096 *tl++ = cookie.nfsuquad[0]; 2097 } 2098 *tl = txdr_unsigned(nmp->nm_readdirsize); 2099 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 2100 if (v3) { 2101 nfsm_postop_attr(vp, attrflag); 2102 if (!error) { 2103 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2104 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2105 dnp->n_cookieverf.nfsuquad[1] = *tl; 2106 } else { 2107 m_freem(mrep); 2108 goto nfsmout; 2109 } 2110 } 2111 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2112 more_dirs = fxdr_unsigned(int, *tl); 2113 2114 /* loop thru the dir entries, doctoring them to 4bsd form */ 2115 while (more_dirs && bigenough) { 2116 if (v3) { 2117 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2118 fxdr_hyper(tl, &fileno); 2119 len = fxdr_unsigned(int, *(tl + 2)); 2120 } else { 2121 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2122 fileno = fxdr_unsigned(u_quad_t, *tl++); 2123 len = fxdr_unsigned(int, *tl); 2124 } 2125 if (len <= 0 || len > NFS_MAXNAMLEN) { 2126 error = EBADRPC; 2127 m_freem(mrep); 2128 goto nfsmout; 2129 } 2130 tlen = nfsm_rndup(len); 2131 if (tlen == len) 2132 tlen += 4; /* To ensure null termination */ 2133 left = DIRBLKSIZ - blksiz; 2134 if ((tlen + DIRHDSIZ) > left) { 2135 dp->d_reclen += left; 2136 uiop->uio_iov->iov_base += left; 2137 uiop->uio_iov->iov_len -= left; 2138 uiop->uio_offset += left; 2139 uiop->uio_resid -= left; 2140 blksiz = 0; 2141 } 2142 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2143 bigenough = 0; 2144 if (bigenough) { 2145 dp = (struct dirent *)uiop->uio_iov->iov_base; 2146 dp->d_fileno = (int)fileno; 2147 dp->d_namlen = len; 2148 dp->d_reclen = tlen + DIRHDSIZ; 2149 dp->d_type = DT_UNKNOWN; 2150 blksiz += dp->d_reclen; 2151 if (blksiz == DIRBLKSIZ) 2152 blksiz = 0; 2153 uiop->uio_offset += DIRHDSIZ; 2154 uiop->uio_resid -= DIRHDSIZ; 2155 uiop->uio_iov->iov_base += DIRHDSIZ; 2156 uiop->uio_iov->iov_len -= DIRHDSIZ; 2157 nfsm_mtouio(uiop, len); 2158 cp = uiop->uio_iov->iov_base; 2159 tlen -= len; 2160 *cp = '\0'; /* null terminate */ 2161 uiop->uio_iov->iov_base += tlen; 2162 uiop->uio_iov->iov_len -= tlen; 2163 uiop->uio_offset += tlen; 2164 uiop->uio_resid -= tlen; 2165 } else 2166 nfsm_adv(nfsm_rndup(len)); 2167 if (v3) { 2168 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2169 } else { 2170 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2171 } 2172 if (bigenough) { 2173 cookie.nfsuquad[0] = *tl++; 2174 if (v3) 2175 cookie.nfsuquad[1] = *tl++; 2176 } else if (v3) 2177 tl += 2; 2178 else 2179 tl++; 2180 more_dirs = fxdr_unsigned(int, *tl); 2181 } 2182 /* 2183 * If at end of rpc data, get the eof boolean 2184 */ 2185 if (!more_dirs) { 2186 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2187 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2188 } 2189 m_freem(mrep); 2190 } 2191 /* 2192 * Fill last record, iff any, out to a multiple of DIRBLKSIZ 2193 * by increasing d_reclen for the last record. 2194 */ 2195 if (blksiz > 0) { 2196 left = DIRBLKSIZ - blksiz; 2197 dp->d_reclen += left; 2198 uiop->uio_iov->iov_base += left; 2199 uiop->uio_iov->iov_len -= left; 2200 uiop->uio_offset += left; 2201 uiop->uio_resid -= left; 2202 } 2203 2204 /* 2205 * We are now either at the end of the directory or have filled the 2206 * block. 2207 */ 2208 if (bigenough) 2209 dnp->n_direofoffset = uiop->uio_offset; 2210 else { 2211 if (uiop->uio_resid > 0) 2212 printf("EEK! readdirrpc resid > 0\n"); 2213 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2214 *cookiep = cookie; 2215 } 2216nfsmout: 2217 return (error); 2218} 2219 2220/* 2221 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2222 */ 2223int 2224nfs_readdirplusrpc(vp, uiop, cred) 2225 struct vnode *vp; 2226 register struct uio *uiop; 2227 struct ucred *cred; 2228{ 2229 register int len, left; 2230 register struct dirent *dp; 2231 register u_long *tl; 2232 register caddr_t cp; 2233 register long t1, t2; 2234 register struct vnode *newvp; 2235 register nfsuint64 *cookiep; 2236 caddr_t bpos, dpos, cp2, dpossav1, dpossav2; 2237 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2; 2238 struct nameidata nami, *ndp = &nami; 2239 struct componentname *cnp = &ndp->ni_cnd; 2240 nfsuint64 cookie; 2241 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2242 struct nfsnode *dnp = VTONFS(vp), *np; 2243 nfsfh_t *fhp; 2244 u_quad_t fileno; 2245 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2246 int attrflag, fhsize; 2247 2248#ifndef nolint 2249 dp = (struct dirent *)0; 2250#endif 2251#ifndef DIAGNOSTIC 2252 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) || 2253 (uiop->uio_resid & (DIRBLKSIZ - 1))) 2254 panic("nfs readdirplusrpc bad uio"); 2255#endif 2256 ndp->ni_dvp = vp; 2257 newvp = NULLVP; 2258 2259 /* 2260 * If there is no cookie, assume directory was stale. 2261 */ 2262 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2263 if (cookiep) 2264 cookie = *cookiep; 2265 else 2266 return (NFSERR_BAD_COOKIE); 2267 /* 2268 * Loop around doing readdir rpc's of size nm_readdirsize 2269 * truncated to a multiple of DIRBLKSIZ. 2270 * The stopping criteria is EOF or buffer full. 2271 */ 2272 while (more_dirs && bigenough) { 2273 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2274 nfsm_reqhead(vp, NFSPROC_READDIRPLUS, 2275 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2276 nfsm_fhtom(vp, 1); 2277 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED); 2278 *tl++ = cookie.nfsuquad[0]; 2279 *tl++ = cookie.nfsuquad[1]; 2280 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2281 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2282 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2283 *tl = txdr_unsigned(nmp->nm_rsize); 2284 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred); 2285 nfsm_postop_attr(vp, attrflag); 2286 if (error) { 2287 m_freem(mrep); 2288 goto nfsmout; 2289 } 2290 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2291 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2292 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2293 more_dirs = fxdr_unsigned(int, *tl); 2294 2295 /* loop thru the dir entries, doctoring them to 4bsd form */ 2296 while (more_dirs && bigenough) { 2297 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2298 fxdr_hyper(tl, &fileno); 2299 len = fxdr_unsigned(int, *(tl + 2)); 2300 if (len <= 0 || len > NFS_MAXNAMLEN) { 2301 error = EBADRPC; 2302 m_freem(mrep); 2303 goto nfsmout; 2304 } 2305 tlen = nfsm_rndup(len); 2306 if (tlen == len) 2307 tlen += 4; /* To ensure null termination*/ 2308 left = DIRBLKSIZ - blksiz; 2309 if ((tlen + DIRHDSIZ) > left) { 2310 dp->d_reclen += left; 2311 uiop->uio_iov->iov_base += left; 2312 uiop->uio_iov->iov_len -= left; 2313 uiop->uio_offset += left; 2314 uiop->uio_resid -= left; 2315 blksiz = 0; 2316 } 2317 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2318 bigenough = 0; 2319 if (bigenough) { 2320 dp = (struct dirent *)uiop->uio_iov->iov_base; 2321 dp->d_fileno = (int)fileno; 2322 dp->d_namlen = len; 2323 dp->d_reclen = tlen + DIRHDSIZ; 2324 dp->d_type = DT_UNKNOWN; 2325 blksiz += dp->d_reclen; 2326 if (blksiz == DIRBLKSIZ) 2327 blksiz = 0; 2328 uiop->uio_offset += DIRHDSIZ; 2329 uiop->uio_resid -= DIRHDSIZ; 2330 uiop->uio_iov->iov_base += DIRHDSIZ; 2331 uiop->uio_iov->iov_len -= DIRHDSIZ; 2332 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2333 cnp->cn_namelen = len; 2334 nfsm_mtouio(uiop, len); 2335 cp = uiop->uio_iov->iov_base; 2336 tlen -= len; 2337 *cp = '\0'; 2338 uiop->uio_iov->iov_base += tlen; 2339 uiop->uio_iov->iov_len -= tlen; 2340 uiop->uio_offset += tlen; 2341 uiop->uio_resid -= tlen; 2342 } else 2343 nfsm_adv(nfsm_rndup(len)); 2344 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2345 if (bigenough) { 2346 cookie.nfsuquad[0] = *tl++; 2347 cookie.nfsuquad[1] = *tl++; 2348 } else 2349 tl += 2; 2350 2351 /* 2352 * Since the attributes are before the file handle 2353 * (sigh), we must skip over the attributes and then 2354 * come back and get them. 2355 */ 2356 attrflag = fxdr_unsigned(int, *tl); 2357 if (attrflag) { 2358 dpossav1 = dpos; 2359 mdsav1 = md; 2360 nfsm_adv(NFSX_V3FATTR); 2361 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2362 doit = fxdr_unsigned(int, *tl); 2363 if (doit) { 2364 nfsm_getfh(fhp, fhsize, 1); 2365 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2366 VREF(vp); 2367 newvp = vp; 2368 np = dnp; 2369 } else { 2370 if (error = nfs_nget(vp->v_mount, fhp, 2371 fhsize, &np)) 2372 doit = 0; 2373 else 2374 newvp = NFSTOV(np); 2375 } 2376 } 2377 if (doit) { 2378 dpossav2 = dpos; 2379 dpos = dpossav1; 2380 mdsav2 = md; 2381 md = mdsav1; 2382 nfsm_loadattr(newvp, (struct vattr *)0); 2383 dpos = dpossav2; 2384 md = mdsav2; 2385 dp->d_type = 2386 IFTODT(VTTOIF(np->n_vattr.va_type)); 2387 ndp->ni_vp = newvp; 2388 cnp->cn_hash = 0; 2389 for (cp = cnp->cn_nameptr, i = 1; i <= len; 2390 i++, cp++) 2391 cnp->cn_hash += (unsigned char)*cp * i; 2392 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 2393 } 2394 } else { 2395 /* Just skip over the file handle */ 2396 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2397 i = fxdr_unsigned(int, *tl); 2398 nfsm_adv(nfsm_rndup(i)); 2399 } 2400 if (newvp != NULLVP) { 2401 vrele(newvp); 2402 newvp = NULLVP; 2403 } 2404 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2405 more_dirs = fxdr_unsigned(int, *tl); 2406 } 2407 /* 2408 * If at end of rpc data, get the eof boolean 2409 */ 2410 if (!more_dirs) { 2411 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2412 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2413 } 2414 m_freem(mrep); 2415 } 2416 /* 2417 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 2418 * by increasing d_reclen for the last record. 2419 */ 2420 if (blksiz > 0) { 2421 left = DIRBLKSIZ - blksiz; 2422 dp->d_reclen += left; 2423 uiop->uio_iov->iov_base += left; 2424 uiop->uio_iov->iov_len -= left; 2425 uiop->uio_offset += left; 2426 uiop->uio_resid -= left; 2427 } 2428 2429 /* 2430 * We are now either at the end of the directory or have filled the 2431 * block. 2432 */ 2433 if (bigenough) 2434 dnp->n_direofoffset = uiop->uio_offset; 2435 else { 2436 if (uiop->uio_resid > 0) 2437 printf("EEK! readdirplusrpc resid > 0\n"); 2438 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2439 *cookiep = cookie; 2440 } 2441nfsmout: 2442 if (newvp != NULLVP) { 2443 if (newvp == vp) 2444 vrele(newvp); 2445 else 2446 vput(newvp); 2447 newvp = NULLVP; 2448 } 2449 return (error); 2450} 2451 2452/* 2453 * Silly rename. To make the NFS filesystem that is stateless look a little 2454 * more like the "ufs" a remove of an active vnode is translated to a rename 2455 * to a funny looking filename that is removed by nfs_inactive on the 2456 * nfsnode. There is the potential for another process on a different client 2457 * to create the same funny name between the nfs_lookitup() fails and the 2458 * nfs_rename() completes, but... 2459 */ 2460static int 2461nfs_sillyrename(dvp, vp, cnp) 2462 struct vnode *dvp, *vp; 2463 struct componentname *cnp; 2464{ 2465 register struct sillyrename *sp; 2466 struct nfsnode *np; 2467 int error; 2468 short pid; 2469 2470 cache_purge(dvp); 2471 np = VTONFS(vp); 2472#ifndef DIAGNOSTIC 2473 if (vp->v_type == VDIR) 2474 panic("nfs: sillyrename dir"); 2475#endif 2476 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2477 M_NFSREQ, M_WAITOK); 2478 sp->s_cred = crdup(cnp->cn_cred); 2479 sp->s_dvp = dvp; 2480 VREF(dvp); 2481 2482 /* Fudge together a funny name */ 2483 pid = cnp->cn_proc->p_pid; 2484 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid); 2485 2486 /* Try lookitups until we get one that isn't there */ 2487 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2488 cnp->cn_proc, (struct nfsnode **)0) == 0) { 2489 sp->s_name[4]++; 2490 if (sp->s_name[4] > 'z') { 2491 error = EINVAL; 2492 goto bad; 2493 } 2494 } 2495 if (error = nfs_renameit(dvp, cnp, sp)) 2496 goto bad; 2497 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2498 cnp->cn_proc, &np); 2499 np->n_sillyrename = sp; 2500 return (0); 2501bad: 2502 vrele(sp->s_dvp); 2503 crfree(sp->s_cred); 2504 free((caddr_t)sp, M_NFSREQ); 2505 return (error); 2506} 2507 2508/* 2509 * Look up a file name and optionally either update the file handle or 2510 * allocate an nfsnode, depending on the value of npp. 2511 * npp == NULL --> just do the lookup 2512 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2513 * handled too 2514 * *npp != NULL --> update the file handle in the vnode 2515 */ 2516static int 2517nfs_lookitup(dvp, name, len, cred, procp, npp) 2518 register struct vnode *dvp; 2519 char *name; 2520 int len; 2521 struct ucred *cred; 2522 struct proc *procp; 2523 struct nfsnode **npp; 2524{ 2525 register u_long *tl; 2526 register caddr_t cp; 2527 register long t1, t2; 2528 struct vnode *newvp = (struct vnode *)0; 2529 struct nfsnode *np, *dnp = VTONFS(dvp); 2530 caddr_t bpos, dpos, cp2; 2531 int error = 0, fhlen, attrflag; 2532 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2533 nfsfh_t *nfhp; 2534 int v3 = NFS_ISV3(dvp); 2535 2536 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2537 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 2538 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 2539 nfsm_fhtom(dvp, v3); 2540 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2541 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred); 2542 if (npp && !error) { 2543 nfsm_getfh(nfhp, fhlen, v3); 2544 if (*npp) { 2545 np = *npp; 2546 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 2547 free((caddr_t)np->n_fhp, M_NFSBIGFH); 2548 np->n_fhp = &np->n_fh; 2549 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 2550 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 2551 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); 2552 np->n_fhsize = fhlen; 2553 newvp = NFSTOV(np); 2554 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2555 VREF(dvp); 2556 newvp = dvp; 2557 } else { 2558 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2559 if (error) { 2560 m_freem(mrep); 2561 return (error); 2562 } 2563 newvp = NFSTOV(np); 2564 } 2565 if (v3) { 2566 nfsm_postop_attr(newvp, attrflag); 2567 if (!attrflag && *npp == NULL) { 2568 m_freem(mrep); 2569 if (newvp == dvp) 2570 vrele(newvp); 2571 else 2572 vput(newvp); 2573 return (ENOENT); 2574 } 2575 } else 2576 nfsm_loadattr(newvp, (struct vattr *)0); 2577 } 2578 nfsm_reqdone; 2579 if (npp && *npp == NULL) { 2580 if (error) { 2581 if (newvp) 2582 if (newvp == dvp) 2583 vrele(newvp); 2584 else 2585 vput(newvp); 2586 } else 2587 *npp = np; 2588 } 2589 return (error); 2590} 2591 2592/* 2593 * Nfs Version 3 commit rpc 2594 */ 2595static int 2596nfs_commit(vp, offset, cnt, cred, procp) 2597 register struct vnode *vp; 2598 u_quad_t offset; 2599 int cnt; 2600 struct ucred *cred; 2601 struct proc *procp; 2602{ 2603 register caddr_t cp; 2604 register u_long *tl; 2605 register int t1, t2; 2606 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2607 caddr_t bpos, dpos, cp2; 2608 int error = 0, wccflag = NFSV3_WCCRATTR; 2609 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2610 2611 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) 2612 return (0); 2613 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2614 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1)); 2615 nfsm_fhtom(vp, 1); 2616 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 2617 txdr_hyper(&offset, tl); 2618 tl += 2; 2619 *tl = txdr_unsigned(cnt); 2620 nfsm_request(vp, NFSPROC_COMMIT, procp, cred); 2621 nfsm_wcc_data(vp, wccflag); 2622 if (!error) { 2623 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF); 2624 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl, 2625 NFSX_V3WRITEVERF)) { 2626 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 2627 NFSX_V3WRITEVERF); 2628 error = NFSERR_STALEWRITEVERF; 2629 } 2630 } 2631 nfsm_reqdone; 2632 return (error); 2633} 2634 2635/* 2636 * Kludge City.. 2637 * - make nfs_bmap() essentially a no-op that does no translation 2638 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2639 * (Maybe I could use the process's page mapping, but I was concerned that 2640 * Kernel Write might not be enabled and also figured copyout() would do 2641 * a lot more work than bcopy() and also it currently happens in the 2642 * context of the swapper process (2). 2643 */ 2644static int 2645nfs_bmap(ap) 2646 struct vop_bmap_args /* { 2647 struct vnode *a_vp; 2648 daddr_t a_bn; 2649 struct vnode **a_vpp; 2650 daddr_t *a_bnp; 2651 int *a_runp; 2652 int *a_runb; 2653 } */ *ap; 2654{ 2655 register struct vnode *vp = ap->a_vp; 2656 2657 if (ap->a_vpp != NULL) 2658 *ap->a_vpp = vp; 2659 if (ap->a_bnp != NULL) 2660 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2661 if (ap->a_runp != NULL) 2662 *ap->a_runp = 0; 2663 if (ap->a_runb != NULL) 2664 *ap->a_runb = 0; 2665 return (0); 2666} 2667 2668/* 2669 * Strategy routine. 2670 * For async requests when nfsiod(s) are running, queue the request by 2671 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2672 * request. 2673 */ 2674static int 2675nfs_strategy(ap) 2676 struct vop_strategy_args *ap; 2677{ 2678 register struct buf *bp = ap->a_bp; 2679 struct ucred *cr; 2680 struct proc *p; 2681 int error = 0; 2682 2683 if (bp->b_flags & B_PHYS) 2684 panic("nfs physio"); 2685 if (bp->b_flags & B_ASYNC) 2686 p = (struct proc *)0; 2687 else 2688 p = curproc; /* XXX */ 2689 if (bp->b_flags & B_READ) 2690 cr = bp->b_rcred; 2691 else 2692 cr = bp->b_wcred; 2693 /* 2694 * If the op is asynchronous and an i/o daemon is waiting 2695 * queue the request, wake it up and wait for completion 2696 * otherwise just do it ourselves. 2697 */ 2698 if ((bp->b_flags & B_ASYNC) == 0 || 2699 nfs_asyncio(bp, NOCRED)) 2700 error = nfs_doio(bp, cr, p); 2701 return (error); 2702} 2703 2704/* 2705 * Mmap a file 2706 * 2707 * NB Currently unsupported. 2708 */ 2709/* ARGSUSED */ 2710static int 2711nfs_mmap(ap) 2712 struct vop_mmap_args /* { 2713 struct vnode *a_vp; 2714 int a_fflags; 2715 struct ucred *a_cred; 2716 struct proc *a_p; 2717 } */ *ap; 2718{ 2719 2720 return (EINVAL); 2721} 2722 2723/* 2724 * fsync vnode op. Just call nfs_flush() with commit == 1. 2725 */ 2726/* ARGSUSED */ 2727static int 2728nfs_fsync(ap) 2729 struct vop_fsync_args /* { 2730 struct vnodeop_desc *a_desc; 2731 struct vnode * a_vp; 2732 struct ucred * a_cred; 2733 int a_waitfor; 2734 struct proc * a_p; 2735 } */ *ap; 2736{ 2737 2738 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2739} 2740 2741/* 2742 * Flush all the blocks associated with a vnode. 2743 * Walk through the buffer pool and push any dirty pages 2744 * associated with the vnode. 2745 */ 2746static int 2747nfs_flush(vp, cred, waitfor, p, commit) 2748 register struct vnode *vp; 2749 struct ucred *cred; 2750 int waitfor; 2751 struct proc *p; 2752 int commit; 2753{ 2754 register struct nfsnode *np = VTONFS(vp); 2755 register struct buf *bp; 2756 register int i; 2757 struct buf *nbp; 2758 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2759 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2760 int passone = 1; 2761 u_quad_t off, endoff, toff; 2762 struct ucred* wcred = NULL; 2763 struct buf **bvec = NULL; 2764#ifndef NFS_COMMITBVECSIZ 2765#define NFS_COMMITBVECSIZ 20 2766#endif 2767 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; 2768 int bvecsize = 0, bveccount; 2769 2770 if (nmp->nm_flag & NFSMNT_INT) 2771 slpflag = PCATCH; 2772 if (!commit) 2773 passone = 0; 2774 /* 2775 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2776 * server, but nas not been committed to stable storage on the server 2777 * yet. On the first pass, the byte range is worked out and the commit 2778 * rpc is done. On the second pass, nfs_writebp() is called to do the 2779 * job. 2780 */ 2781again: 2782 off = (u_quad_t)-1; 2783 endoff = 0; 2784 bvecpos = 0; 2785 if (NFS_ISV3(vp) && commit) { 2786 s = splbio(); 2787 /* 2788 * Count up how many buffers waiting for a commit. 2789 */ 2790 bveccount = 0; 2791 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2792 nbp = bp->b_vnbufs.le_next; 2793 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2794 == (B_DELWRI | B_NEEDCOMMIT)) 2795 bveccount++; 2796 } 2797 /* 2798 * Allocate space to remember the list of bufs to commit. It is 2799 * important to use M_NOWAIT here to avoid a race with nfs_write. 2800 * If we can't get memory (for whatever reason), we will end up 2801 * committing the buffers one-by-one in the loop below. 2802 */ 2803 if (bveccount > NFS_COMMITBVECSIZ) { 2804 if (bvec != NULL && bvec != bvec_on_stack) 2805 free(bvec, M_TEMP); 2806 bvec = (struct buf **) 2807 malloc(bveccount * sizeof(struct buf *), 2808 M_TEMP, M_NOWAIT); 2809 if (bvec == NULL) { 2810 bvec = bvec_on_stack; 2811 bvecsize = NFS_COMMITBVECSIZ; 2812 } else 2813 bvecsize = bveccount; 2814 } else { 2815 bvec = bvec_on_stack; 2816 bvecsize = NFS_COMMITBVECSIZ; 2817 } 2818 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2819 nbp = bp->b_vnbufs.le_next; 2820 if (bvecpos >= bvecsize) 2821 break; 2822 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2823 != (B_DELWRI | B_NEEDCOMMIT)) 2824 continue; 2825 bremfree(bp); 2826 /* 2827 * Work out if all buffers are using the same cred 2828 * so we can deal with them all with one commit. 2829 */ 2830 if (wcred == NULL) 2831 wcred = bp->b_wcred; 2832 else if (wcred != bp->b_wcred) 2833 wcred = NOCRED; 2834 bp->b_flags |= (B_BUSY | B_WRITEINPROG); 2835 vfs_busy_pages(bp, 1); 2836 /* 2837 * A list of these buffers is kept so that the 2838 * second loop knows which buffers have actually 2839 * been committed. This is necessary, since there 2840 * may be a race between the commit rpc and new 2841 * uncommitted writes on the file. 2842 */ 2843 bvec[bvecpos++] = bp; 2844 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2845 bp->b_dirtyoff; 2846 if (toff < off) 2847 off = toff; 2848 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2849 if (toff > endoff) 2850 endoff = toff; 2851 } 2852 splx(s); 2853 } 2854 if (bvecpos > 0) { 2855 /* 2856 * Commit data on the server, as required. 2857 * If all bufs are using the same wcred, then use that with 2858 * one call for all of them, otherwise commit each one 2859 * separately. 2860 */ 2861 if (wcred != NOCRED) 2862 retv = nfs_commit(vp, off, (int)(endoff - off), 2863 wcred, p); 2864 else { 2865 retv = 0; 2866 for (i = 0; i < bvecpos; i++) { 2867 off_t off, size; 2868 bp = bvec[i]; 2869 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2870 bp->b_dirtyoff; 2871 size = (u_quad_t)(bp->b_dirtyend 2872 - bp->b_dirtyoff); 2873 retv = nfs_commit(vp, off, (int)size, 2874 bp->b_wcred, p); 2875 if (retv) break; 2876 } 2877 } 2878 2879 if (retv == NFSERR_STALEWRITEVERF) 2880 nfs_clearcommit(vp->v_mount); 2881 /* 2882 * Now, either mark the blocks I/O done or mark the 2883 * blocks dirty, depending on whether the commit 2884 * succeeded. 2885 */ 2886 for (i = 0; i < bvecpos; i++) { 2887 bp = bvec[i]; 2888 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2889 if (retv) { 2890 vfs_unbusy_pages(bp); 2891 brelse(bp); 2892 } else { 2893 vp->v_numoutput++; 2894 bp->b_flags |= B_ASYNC; 2895 if (bp->b_flags & B_DELWRI) { 2896 --numdirtybuffers; 2897 if (needsbuffer) { 2898 vfs_bio_need_satisfy(); 2899 } 2900 } 2901 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2902 bp->b_dirtyoff = bp->b_dirtyend = 0; 2903 reassignbuf(bp, vp); 2904 biodone(bp); 2905 } 2906 } 2907 } 2908 2909 /* 2910 * Start/do any write(s) that are required. 2911 */ 2912loop: 2913 s = splbio(); 2914 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2915 nbp = bp->b_vnbufs.le_next; 2916 if (bp->b_flags & B_BUSY) { 2917 if (waitfor != MNT_WAIT || passone) 2918 continue; 2919 bp->b_flags |= B_WANTED; 2920 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2921 "nfsfsync", slptimeo); 2922 splx(s); 2923 if (error) { 2924 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2925 error = EINTR; 2926 goto done; 2927 } 2928 if (slpflag == PCATCH) { 2929 slpflag = 0; 2930 slptimeo = 2 * hz; 2931 } 2932 } 2933 goto loop; 2934 } 2935 if ((bp->b_flags & B_DELWRI) == 0) 2936 panic("nfs_fsync: not dirty"); 2937 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2938 continue; 2939 bremfree(bp); 2940 if (passone || !commit) 2941 bp->b_flags |= (B_BUSY|B_ASYNC); 2942 else 2943 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2944 splx(s); 2945 VOP_BWRITE(bp); 2946 goto loop; 2947 } 2948 splx(s); 2949 if (passone) { 2950 passone = 0; 2951 goto again; 2952 } 2953 if (waitfor == MNT_WAIT) { 2954 while (vp->v_numoutput) { 2955 vp->v_flag |= VBWAIT; 2956 error = tsleep((caddr_t)&vp->v_numoutput, 2957 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2958 if (error) { 2959 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2960 error = EINTR; 2961 goto done; 2962 } 2963 if (slpflag == PCATCH) { 2964 slpflag = 0; 2965 slptimeo = 2 * hz; 2966 } 2967 } 2968 } 2969 if (vp->v_dirtyblkhd.lh_first && commit) { 2970 goto loop; 2971 } 2972 } 2973 if (np->n_flag & NWRITEERR) { 2974 error = np->n_error; 2975 np->n_flag &= ~NWRITEERR; 2976 } 2977done: 2978 if (bvec != NULL && bvec != bvec_on_stack) 2979 free(bvec, M_TEMP); 2980 return (error); 2981} 2982 2983/* 2984 * Return POSIX pathconf information applicable to nfs. 2985 * 2986 * The NFS V2 protocol doesn't support this, so just return EINVAL 2987 * for V2. 2988 */ 2989/* ARGSUSED */ 2990static int 2991nfs_pathconf(ap) 2992 struct vop_pathconf_args /* { 2993 struct vnode *a_vp; 2994 int a_name; 2995 int *a_retval; 2996 } */ *ap; 2997{ 2998 2999 return (EINVAL); 3000} 3001 3002/* 3003 * NFS advisory byte-level locks. 3004 * Currently unsupported. 3005 */ 3006static int 3007nfs_advlock(ap) 3008 struct vop_advlock_args /* { 3009 struct vnode *a_vp; 3010 caddr_t a_id; 3011 int a_op; 3012 struct flock *a_fl; 3013 int a_flags; 3014 } */ *ap; 3015{ 3016 register struct nfsnode *np = VTONFS(ap->a_vp); 3017 3018 /* 3019 * The following kludge is to allow diskless support to work 3020 * until a real NFS lockd is implemented. Basically, just pretend 3021 * that this is a local lock. 3022 */ 3023 return (lf_advlock(ap, &(np->n_lockf), np->n_size)); 3024} 3025 3026/* 3027 * Print out the contents of an nfsnode. 3028 */ 3029static int 3030nfs_print(ap) 3031 struct vop_print_args /* { 3032 struct vnode *a_vp; 3033 } */ *ap; 3034{ 3035 register struct vnode *vp = ap->a_vp; 3036 register struct nfsnode *np = VTONFS(vp); 3037 3038 printf("tag VT_NFS, fileid %ld fsid 0x%lx", 3039 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 3040 if (vp->v_type == VFIFO) 3041 fifo_printinfo(vp); 3042 printf("\n"); 3043 return (0); 3044} 3045 3046/* 3047 * Just call nfs_writebp() with the force argument set to 1. 3048 */ 3049static int 3050nfs_bwrite(ap) 3051 struct vop_bwrite_args /* { 3052 struct vnode *a_bp; 3053 } */ *ap; 3054{ 3055 3056 return (nfs_writebp(ap->a_bp, 1)); 3057} 3058 3059/* 3060 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless 3061 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 3062 */ 3063int 3064nfs_writebp(bp, force) 3065 register struct buf *bp; 3066 int force; 3067{ 3068 register int oldflags = bp->b_flags, retv = 1; 3069 off_t off; 3070 3071 if(!(bp->b_flags & B_BUSY)) 3072 panic("bwrite: buffer is not busy???"); 3073 3074 if (bp->b_flags & B_DELWRI) { 3075 --numdirtybuffers; 3076 if (needsbuffer) 3077 vfs_bio_need_satisfy(); 3078 } 3079 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 3080 3081 if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) { 3082 reassignbuf(bp, bp->b_vp); 3083 } 3084 3085 bp->b_vp->v_numoutput++; 3086 curproc->p_stats->p_ru.ru_oublock++; 3087 3088 /* 3089 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 3090 * an actual write will have to be scheduled via. VOP_STRATEGY(). 3091 * If B_WRITEINPROG is already set, then push it with a write anyhow. 3092 */ 3093 vfs_busy_pages(bp, 1); 3094 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) { 3095 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 3096 bp->b_flags |= B_WRITEINPROG; 3097 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, 3098 bp->b_wcred, bp->b_proc); 3099 bp->b_flags &= ~B_WRITEINPROG; 3100 if (!retv) { 3101 bp->b_dirtyoff = bp->b_dirtyend = 0; 3102 bp->b_flags &= ~B_NEEDCOMMIT; 3103 biodone(bp); 3104 } else if (retv == NFSERR_STALEWRITEVERF) 3105 nfs_clearcommit(bp->b_vp->v_mount); 3106 } 3107 if (retv) { 3108 if (force) 3109 bp->b_flags |= B_WRITEINPROG; 3110 VOP_STRATEGY(bp); 3111 } 3112 3113 if( (oldflags & B_ASYNC) == 0) { 3114 int rtval = biowait(bp); 3115 3116 if (oldflags & B_DELWRI) { 3117 reassignbuf(bp, bp->b_vp); 3118 } 3119 brelse(bp); 3120 return (rtval); 3121 } 3122 3123 return (0); 3124} 3125 3126/* 3127 * nfs special file access vnode op. 3128 * Essentially just get vattr and then imitate iaccess() since the device is 3129 * local to the client. 3130 */ 3131static int 3132nfsspec_access(ap) 3133 struct vop_access_args /* { 3134 struct vnode *a_vp; 3135 int a_mode; 3136 struct ucred *a_cred; 3137 struct proc *a_p; 3138 } */ *ap; 3139{ 3140 register struct vattr *vap; 3141 register gid_t *gp; 3142 register struct ucred *cred = ap->a_cred; 3143 struct vnode *vp = ap->a_vp; 3144 mode_t mode = ap->a_mode; 3145 struct vattr vattr; 3146 register int i; 3147 int error; 3148 3149 /* 3150 * Disallow write attempts on filesystems mounted read-only; 3151 * unless the file is a socket, fifo, or a block or character 3152 * device resident on the filesystem. 3153 */ 3154 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3155 switch (vp->v_type) { 3156 case VREG: case VDIR: case VLNK: 3157 return (EROFS); 3158 } 3159 } 3160 /* 3161 * If you're the super-user, 3162 * you always get access. 3163 */ 3164 if (cred->cr_uid == 0) 3165 return (0); 3166 vap = &vattr; 3167 error = VOP_GETATTR(vp, vap, cred, ap->a_p); 3168 if (error) 3169 return (error); 3170 /* 3171 * Access check is based on only one of owner, group, public. 3172 * If not owner, then check group. If not a member of the 3173 * group, then check public access. 3174 */ 3175 if (cred->cr_uid != vap->va_uid) { 3176 mode >>= 3; 3177 gp = cred->cr_groups; 3178 for (i = 0; i < cred->cr_ngroups; i++, gp++) 3179 if (vap->va_gid == *gp) 3180 goto found; 3181 mode >>= 3; 3182found: 3183 ; 3184 } 3185 error = (vap->va_mode & mode) == mode ? 0 : EACCES; 3186 return (error); 3187} 3188 3189/* 3190 * Read wrapper for special devices. 3191 */ 3192static int 3193nfsspec_read(ap) 3194 struct vop_read_args /* { 3195 struct vnode *a_vp; 3196 struct uio *a_uio; 3197 int a_ioflag; 3198 struct ucred *a_cred; 3199 } */ *ap; 3200{ 3201 register struct nfsnode *np = VTONFS(ap->a_vp); 3202 struct timeval tv; 3203 3204 /* 3205 * Set access flag. 3206 */ 3207 np->n_flag |= NACC; 3208 gettime(&tv); 3209 np->n_atim.tv_sec = tv.tv_sec; 3210 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3211 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3212} 3213 3214/* 3215 * Write wrapper for special devices. 3216 */ 3217static int 3218nfsspec_write(ap) 3219 struct vop_write_args /* { 3220 struct vnode *a_vp; 3221 struct uio *a_uio; 3222 int a_ioflag; 3223 struct ucred *a_cred; 3224 } */ *ap; 3225{ 3226 register struct nfsnode *np = VTONFS(ap->a_vp); 3227 struct timeval tv; 3228 3229 /* 3230 * Set update flag. 3231 */ 3232 np->n_flag |= NUPD; 3233 gettime(&tv); 3234 np->n_mtim.tv_sec = tv.tv_sec; 3235 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3236 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3237} 3238 3239/* 3240 * Close wrapper for special devices. 3241 * 3242 * Update the times on the nfsnode then do device close. 3243 */ 3244static int 3245nfsspec_close(ap) 3246 struct vop_close_args /* { 3247 struct vnode *a_vp; 3248 int a_fflag; 3249 struct ucred *a_cred; 3250 struct proc *a_p; 3251 } */ *ap; 3252{ 3253 register struct vnode *vp = ap->a_vp; 3254 register struct nfsnode *np = VTONFS(vp); 3255 struct vattr vattr; 3256 3257 if (np->n_flag & (NACC | NUPD)) { 3258 np->n_flag |= NCHG; 3259 if (vp->v_usecount == 1 && 3260 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3261 VATTR_NULL(&vattr); 3262 if (np->n_flag & NACC) 3263 vattr.va_atime = np->n_atim; 3264 if (np->n_flag & NUPD) 3265 vattr.va_mtime = np->n_mtim; 3266 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3267 } 3268 } 3269 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3270} 3271 3272/* 3273 * Read wrapper for fifos. 3274 */ 3275static int 3276nfsfifo_read(ap) 3277 struct vop_read_args /* { 3278 struct vnode *a_vp; 3279 struct uio *a_uio; 3280 int a_ioflag; 3281 struct ucred *a_cred; 3282 } */ *ap; 3283{ 3284 register struct nfsnode *np = VTONFS(ap->a_vp); 3285 struct timeval tv; 3286 3287 /* 3288 * Set access flag. 3289 */ 3290 np->n_flag |= NACC; 3291 gettime(&tv); 3292 np->n_atim.tv_sec = tv.tv_sec; 3293 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3294 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3295} 3296 3297/* 3298 * Write wrapper for fifos. 3299 */ 3300static int 3301nfsfifo_write(ap) 3302 struct vop_write_args /* { 3303 struct vnode *a_vp; 3304 struct uio *a_uio; 3305 int a_ioflag; 3306 struct ucred *a_cred; 3307 } */ *ap; 3308{ 3309 register struct nfsnode *np = VTONFS(ap->a_vp); 3310 struct timeval tv; 3311 3312 /* 3313 * Set update flag. 3314 */ 3315 np->n_flag |= NUPD; 3316 gettime(&tv); 3317 np->n_mtim.tv_sec = tv.tv_sec; 3318 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3319 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3320} 3321 3322/* 3323 * Close wrapper for fifos. 3324 * 3325 * Update the times on the nfsnode then do fifo close. 3326 */ 3327static int 3328nfsfifo_close(ap) 3329 struct vop_close_args /* { 3330 struct vnode *a_vp; 3331 int a_fflag; 3332 struct ucred *a_cred; 3333 struct proc *a_p; 3334 } */ *ap; 3335{ 3336 register struct vnode *vp = ap->a_vp; 3337 register struct nfsnode *np = VTONFS(vp); 3338 struct timeval tv; 3339 struct vattr vattr; 3340 3341 if (np->n_flag & (NACC | NUPD)) { 3342 gettime(&tv); 3343 if (np->n_flag & NACC) { 3344 np->n_atim.tv_sec = tv.tv_sec; 3345 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3346 } 3347 if (np->n_flag & NUPD) { 3348 np->n_mtim.tv_sec = tv.tv_sec; 3349 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3350 } 3351 np->n_flag |= NCHG; 3352 if (vp->v_usecount == 1 && 3353 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3354 VATTR_NULL(&vattr); 3355 if (np->n_flag & NACC) 3356 vattr.va_atime = np->n_atim; 3357 if (np->n_flag & NUPD) 3358 vattr.va_mtime = np->n_mtim; 3359 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3360 } 3361 } 3362 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3363} 3364 3365static int 3366nfs_ioctl(ap) 3367 struct vop_ioctl_args *ap; 3368{ 3369 3370 /* 3371 * XXX we were once bogusly enoictl() which returned this (ENOTTY). 3372 * Probably we should return ENODEV. 3373 */ 3374 return (ENOTTY); 3375}
|