nfs_vnops.c revision 35823
1215334Sdougb/* 21638Srgrimes * Copyright (c) 1989, 1993 31638Srgrimes * The Regents of the University of California. All rights reserved. 41638Srgrimes * 51638Srgrimes * This code is derived from software contributed to Berkeley by 61638Srgrimes * Rick Macklem at The University of Guelph. 71638Srgrimes * 81638Srgrimes * Redistribution and use in source and binary forms, with or without 91638Srgrimes * modification, are permitted provided that the following conditions 101638Srgrimes * are met: 111638Srgrimes * 1. Redistributions of source code must retain the above copyright 121638Srgrimes * notice, this list of conditions and the following disclaimer. 131638Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141638Srgrimes * notice, this list of conditions and the following disclaimer in the 151638Srgrimes * documentation and/or other materials provided with the distribution. 161638Srgrimes * 3. All advertising materials mentioning features or use of this software 171638Srgrimes * must display the following acknowledgement: 181638Srgrimes * This product includes software developed by the University of 191638Srgrimes * California, Berkeley and its contributors. 201638Srgrimes * 4. Neither the name of the University nor the names of its contributors 211638Srgrimes * may be used to endorse or promote products derived from this software 221638Srgrimes * without specific prior written permission. 231638Srgrimes * 241638Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251638Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261638Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271638Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281638Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291638Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301638Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311638Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321638Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331638Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341638Srgrimes * SUCH DAMAGE. 351638Srgrimes * 361638Srgrimes * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 371638Srgrimes * $Id: nfs_vnops.c,v 1.83 1998/03/30 09:54:32 phk Exp $ 381638Srgrimes */ 391638Srgrimes 401638Srgrimes 411638Srgrimes/* 421638Srgrimes * vnode op calls for Sun NFS version 2 and 3 431638Srgrimes */ 441638Srgrimes 451638Srgrimes#include "opt_inet.h" 461638Srgrimes 471638Srgrimes#include <sys/param.h> 481638Srgrimes#include <sys/kernel.h> 491638Srgrimes#include <sys/systm.h> 501638Srgrimes#include <sys/resourcevar.h> 511638Srgrimes#include <sys/proc.h> 521638Srgrimes#include <sys/mount.h> 531638Srgrimes#include <sys/buf.h> 541638Srgrimes#include <sys/malloc.h> 551638Srgrimes#include <sys/mbuf.h> 561638Srgrimes#include <sys/namei.h> 571638Srgrimes#include <sys/socket.h> 581638Srgrimes#include <sys/vnode.h> 591638Srgrimes#include <sys/dirent.h> 601638Srgrimes#include <sys/fcntl.h> 611638Srgrimes#include <sys/lockf.h> 621638Srgrimes 631638Srgrimes#include <vm/vm.h> 641638Srgrimes#include <vm/vm_extern.h> 651638Srgrimes#include <vm/vm_zone.h> 661638Srgrimes 671638Srgrimes#include <miscfs/fifofs/fifo.h> 681638Srgrimes#include <miscfs/specfs/specdev.h> 691638Srgrimes 701638Srgrimes#include <nfs/rpcv2.h> 711638Srgrimes#include <nfs/nfsproto.h> 721638Srgrimes#include <nfs/nfs.h> 731638Srgrimes#include <nfs/nfsnode.h> 741638Srgrimes#include <nfs/nfsmount.h> 751638Srgrimes#include <nfs/xdr_subs.h> 761638Srgrimes#include <nfs/nfsm_subs.h> 771638Srgrimes#include <nfs/nqnfs.h> 781638Srgrimes 791638Srgrimes#include <net/if.h> 801638Srgrimes#include <netinet/in.h> 811638Srgrimes#include <netinet/in_var.h> 821638Srgrimes 831638Srgrimes/* Defs */ 841638Srgrimes#define TRUE 1 851638Srgrimes#define FALSE 0 861638Srgrimes 871638Srgrimes/* 881638Srgrimes * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these 891638Srgrimes * calls are not in getblk() and brelse() so that they would not be necessary 901638Srgrimes * here. 911638Srgrimes */ 921638Srgrimes#ifndef B_VMIO 931638Srgrimes#define vfs_busy_pages(bp, f) 941638Srgrimes#endif 951638Srgrimes 961638Srgrimesstatic int nfsspec_read __P((struct vop_read_args *)); 971638Srgrimesstatic int nfsspec_write __P((struct vop_write_args *)); 981638Srgrimesstatic int nfsfifo_read __P((struct vop_read_args *)); 991638Srgrimesstatic int nfsfifo_write __P((struct vop_write_args *)); 1001638Srgrimesstatic int nfsspec_close __P((struct vop_close_args *)); 1011638Srgrimesstatic int nfsfifo_close __P((struct vop_close_args *)); 1021638Srgrimes#define nfs_poll vop_nopoll 1031638Srgrimesstatic int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int)); 1041638Srgrimesstatic int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *)); 1051638Srgrimesstatic int nfs_lookup __P((struct vop_lookup_args *)); 1061638Srgrimesstatic int nfs_create __P((struct vop_create_args *)); 1071638Srgrimesstatic int nfs_mknod __P((struct vop_mknod_args *)); 1081638Srgrimesstatic int nfs_open __P((struct vop_open_args *)); 1091638Srgrimesstatic int nfs_close __P((struct vop_close_args *)); 1101638Srgrimesstatic int nfs_access __P((struct vop_access_args *)); 1111638Srgrimesstatic int nfs_getattr __P((struct vop_getattr_args *)); 1121638Srgrimesstatic int nfs_setattr __P((struct vop_setattr_args *)); 1131638Srgrimesstatic int nfs_read __P((struct vop_read_args *)); 1141638Srgrimesstatic int nfs_mmap __P((struct vop_mmap_args *)); 1151638Srgrimesstatic int nfs_fsync __P((struct vop_fsync_args *)); 1161638Srgrimesstatic int nfs_remove __P((struct vop_remove_args *)); 1171638Srgrimesstatic int nfs_link __P((struct vop_link_args *)); 1181638Srgrimesstatic int nfs_rename __P((struct vop_rename_args *)); 1191638Srgrimesstatic int nfs_mkdir __P((struct vop_mkdir_args *)); 1201638Srgrimesstatic int nfs_rmdir __P((struct vop_rmdir_args *)); 1211638Srgrimesstatic int nfs_symlink __P((struct vop_symlink_args *)); 1221638Srgrimesstatic int nfs_readdir __P((struct vop_readdir_args *)); 1231638Srgrimesstatic int nfs_bmap __P((struct vop_bmap_args *)); 1241638Srgrimesstatic int nfs_strategy __P((struct vop_strategy_args *)); 1251638Srgrimesstatic int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **)); 1261638Srgrimesstatic int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *)); 1271638Srgrimesstatic int nfsspec_access __P((struct vop_access_args *)); 1281638Srgrimesstatic int nfs_readlink __P((struct vop_readlink_args *)); 1291638Srgrimesstatic int nfs_print __P((struct vop_print_args *)); 1301638Srgrimesstatic int nfs_advlock __P((struct vop_advlock_args *)); 1311638Srgrimesstatic int nfs_bwrite __P((struct vop_bwrite_args *)); 1321638Srgrimes/* 1331638Srgrimes * Global vfs data structures for nfs 1341638Srgrimes */ 1351638Srgrimesvop_t **nfsv2_vnodeop_p; 1361638Srgrimesstatic struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { 1371638Srgrimes { &vop_default_desc, (vop_t *) vop_defaultop }, 1381638Srgrimes { &vop_abortop_desc, (vop_t *) nfs_abortop }, 1391638Srgrimes { &vop_access_desc, (vop_t *) nfs_access }, 1401638Srgrimes { &vop_advlock_desc, (vop_t *) nfs_advlock }, 1411638Srgrimes { &vop_bmap_desc, (vop_t *) nfs_bmap }, 1421638Srgrimes { &vop_bwrite_desc, (vop_t *) nfs_bwrite }, 1431638Srgrimes { &vop_close_desc, (vop_t *) nfs_close }, 1441638Srgrimes { &vop_create_desc, (vop_t *) nfs_create }, 1451638Srgrimes { &vop_fsync_desc, (vop_t *) nfs_fsync }, 1461638Srgrimes { &vop_getattr_desc, (vop_t *) nfs_getattr }, 1471638Srgrimes { &vop_getpages_desc, (vop_t *) nfs_getpages }, 1481638Srgrimes { &vop_putpages_desc, (vop_t *) nfs_putpages }, 1491638Srgrimes { &vop_inactive_desc, (vop_t *) nfs_inactive }, 1501638Srgrimes { &vop_lease_desc, (vop_t *) vop_null }, 1511638Srgrimes { &vop_link_desc, (vop_t *) nfs_link }, 1521638Srgrimes { &vop_lock_desc, (vop_t *) vop_sharedlock }, 1531638Srgrimes { &vop_lookup_desc, (vop_t *) nfs_lookup }, 1541638Srgrimes { &vop_mkdir_desc, (vop_t *) nfs_mkdir }, 1551638Srgrimes { &vop_mknod_desc, (vop_t *) nfs_mknod }, 1561638Srgrimes { &vop_mmap_desc, (vop_t *) nfs_mmap }, 1571638Srgrimes { &vop_open_desc, (vop_t *) nfs_open }, 1581638Srgrimes { &vop_poll_desc, (vop_t *) nfs_poll }, 1591638Srgrimes { &vop_print_desc, (vop_t *) nfs_print }, 1601638Srgrimes { &vop_read_desc, (vop_t *) nfs_read }, 1611638Srgrimes { &vop_readdir_desc, (vop_t *) nfs_readdir }, 1621638Srgrimes { &vop_readlink_desc, (vop_t *) nfs_readlink }, 1631638Srgrimes { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 1641638Srgrimes { &vop_remove_desc, (vop_t *) nfs_remove }, 1651638Srgrimes { &vop_rename_desc, (vop_t *) nfs_rename }, 1661638Srgrimes { &vop_rmdir_desc, (vop_t *) nfs_rmdir }, 1671638Srgrimes { &vop_setattr_desc, (vop_t *) nfs_setattr }, 1681638Srgrimes { &vop_strategy_desc, (vop_t *) nfs_strategy }, 1691638Srgrimes { &vop_symlink_desc, (vop_t *) nfs_symlink }, 1701638Srgrimes { &vop_write_desc, (vop_t *) nfs_write }, 1711638Srgrimes { NULL, NULL } 1721638Srgrimes}; 1731638Srgrimesstatic struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 1741638Srgrimes { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 1751638SrgrimesVNODEOP_SET(nfsv2_vnodeop_opv_desc); 1761638Srgrimes 1771638Srgrimes/* 1781638Srgrimes * Special device vnode ops 1791638Srgrimes */ 1801638Srgrimesvop_t **spec_nfsv2nodeop_p; 1811638Srgrimesstatic struct vnodeopv_entry_desc nfsv2_specop_entries[] = { 1821638Srgrimes { &vop_default_desc, (vop_t *) spec_vnoperate }, 1831638Srgrimes { &vop_access_desc, (vop_t *) nfsspec_access }, 1841638Srgrimes { &vop_close_desc, (vop_t *) nfsspec_close }, 1851638Srgrimes { &vop_fsync_desc, (vop_t *) nfs_fsync }, 1861638Srgrimes { &vop_getattr_desc, (vop_t *) nfs_getattr }, 1871638Srgrimes { &vop_inactive_desc, (vop_t *) nfs_inactive }, 1881638Srgrimes { &vop_lock_desc, (vop_t *) vop_sharedlock }, 1891638Srgrimes { &vop_print_desc, (vop_t *) nfs_print }, 1901638Srgrimes { &vop_read_desc, (vop_t *) nfsspec_read }, 1911638Srgrimes { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 1921638Srgrimes { &vop_setattr_desc, (vop_t *) nfs_setattr }, 1931638Srgrimes { &vop_write_desc, (vop_t *) nfsspec_write }, 1941638Srgrimes { NULL, NULL } 1951638Srgrimes}; 1961638Srgrimesstatic struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 1971638Srgrimes { &spec_nfsv2nodeop_p, nfsv2_specop_entries }; 1981638SrgrimesVNODEOP_SET(spec_nfsv2nodeop_opv_desc); 1991638Srgrimes 2001638Srgrimesvop_t **fifo_nfsv2nodeop_p; 2011638Srgrimesstatic struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = { 2021638Srgrimes { &vop_default_desc, (vop_t *) fifo_vnoperate }, 2031638Srgrimes { &vop_access_desc, (vop_t *) nfsspec_access }, 2041638Srgrimes { &vop_close_desc, (vop_t *) nfsfifo_close }, 2051638Srgrimes { &vop_fsync_desc, (vop_t *) nfs_fsync }, 2061638Srgrimes { &vop_getattr_desc, (vop_t *) nfs_getattr }, 2071638Srgrimes { &vop_inactive_desc, (vop_t *) nfs_inactive }, 2081638Srgrimes { &vop_lock_desc, (vop_t *) vop_sharedlock }, 2091638Srgrimes { &vop_print_desc, (vop_t *) nfs_print }, 2101638Srgrimes { &vop_read_desc, (vop_t *) nfsfifo_read }, 2111638Srgrimes { &vop_reclaim_desc, (vop_t *) nfs_reclaim }, 2121638Srgrimes { &vop_setattr_desc, (vop_t *) nfs_setattr }, 2131638Srgrimes { &vop_write_desc, (vop_t *) nfsfifo_write }, 2141638Srgrimes { NULL, NULL } 2151638Srgrimes}; 2161638Srgrimesstatic struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 2171638Srgrimes { &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries }; 2181638SrgrimesVNODEOP_SET(fifo_nfsv2nodeop_opv_desc); 2191638Srgrimes 2201638Srgrimesstatic int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt, 2211638Srgrimes struct ucred *cred, struct proc *procp)); 2221638Srgrimesstatic int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp, 2231638Srgrimes struct componentname *cnp, 2241638Srgrimes struct vattr *vap)); 2251638Srgrimesstatic int nfs_removerpc __P((struct vnode *dvp, char *name, int namelen, 2261638Srgrimes struct ucred *cred, struct proc *proc)); 2271638Srgrimesstatic int nfs_renamerpc __P((struct vnode *fdvp, char *fnameptr, 2281638Srgrimes int fnamelen, struct vnode *tdvp, 2291638Srgrimes char *tnameptr, int tnamelen, 2301638Srgrimes struct ucred *cred, struct proc *proc)); 2311638Srgrimesstatic int nfs_renameit __P((struct vnode *sdvp, 2321638Srgrimes struct componentname *scnp, 2331638Srgrimes struct sillyrename *sp)); 2341638Srgrimes 2351638Srgrimes/* 2361638Srgrimes * Global variables 2371638Srgrimes */ 2381638Srgrimesextern u_long nfs_true, nfs_false; 2391638Srgrimesextern struct nfsstats nfsstats; 2401638Srgrimesextern nfstype nfsv3_type[9]; 2411638Srgrimesstruct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 2421638Srgrimesstruct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON]; 2431638Srgrimesint nfs_numasync = 0; 2441638Srgrimes#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 2451638Srgrimes 2461638Srgrimes/* 2471638Srgrimes * nfs access vnode op. 2481638Srgrimes * For nfs version 2, just return ok. File accesses may fail later. 2491638Srgrimes * For nfs version 3, use the access rpc to check accessibility. If file modes 2501638Srgrimes * are changed on the server, accesses might still fail later. 2511638Srgrimes */ 2521638Srgrimesstatic int 2531638Srgrimesnfs_access(ap) 2541638Srgrimes struct vop_access_args /* { 2551638Srgrimes struct vnode *a_vp; 2561638Srgrimes int a_mode; 2571638Srgrimes struct ucred *a_cred; 2581638Srgrimes struct proc *a_p; 2591638Srgrimes } */ *ap; 2601638Srgrimes{ 2611638Srgrimes register struct vnode *vp = ap->a_vp; 2621638Srgrimes register u_long *tl; 2631638Srgrimes register caddr_t cp; 2641638Srgrimes register int t1, t2; 2651638Srgrimes caddr_t bpos, dpos, cp2; 2661638Srgrimes int error = 0, attrflag; 2671638Srgrimes struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2681638Srgrimes u_long mode, rmode; 2691638Srgrimes int v3 = NFS_ISV3(vp); 2701638Srgrimes 2711638Srgrimes /* 2721638Srgrimes * Disallow write attempts on filesystems mounted read-only; 2731638Srgrimes * unless the file is a socket, fifo, or a block or character 2741638Srgrimes * device resident on the filesystem. 2751638Srgrimes */ 2761638Srgrimes if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 2771638Srgrimes switch (vp->v_type) { 2781638Srgrimes case VREG: case VDIR: case VLNK: 2791638Srgrimes return (EROFS); 2801638Srgrimes } 2811638Srgrimes } 2821638Srgrimes /* 2831638Srgrimes * For nfs v3, do an access rpc, otherwise you are stuck emulating 2841638Srgrimes * ufs_access() locally using the vattr. This may not be correct, 2851638Srgrimes * since the server may apply other access criteria such as 2861638Srgrimes * client uid-->server uid mapping that we do not know about, but 2871638Srgrimes * this is better than just returning anything that is lying about 2881638Srgrimes * in the cache. 2891638Srgrimes */ 2901638Srgrimes if (v3) { 2911638Srgrimes nfsstats.rpccnt[NFSPROC_ACCESS]++; 2921638Srgrimes nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); 2931638Srgrimes nfsm_fhtom(vp, v3); 2941638Srgrimes nfsm_build(tl, u_long *, NFSX_UNSIGNED); 2951638Srgrimes if (ap->a_mode & VREAD) 2961638Srgrimes mode = NFSV3ACCESS_READ; 2971856Sdg else 2981638Srgrimes mode = 0; 2991638Srgrimes if (vp->v_type == VDIR) { 3001638Srgrimes if (ap->a_mode & VWRITE) 3011638Srgrimes mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 3021638Srgrimes NFSV3ACCESS_DELETE); 3031638Srgrimes if (ap->a_mode & VEXEC) 3041638Srgrimes mode |= NFSV3ACCESS_LOOKUP; 3051638Srgrimes } else { 3061638Srgrimes if (ap->a_mode & VWRITE) 3071638Srgrimes mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 3081638Srgrimes if (ap->a_mode & VEXEC) 3091638Srgrimes mode |= NFSV3ACCESS_EXECUTE; 3101638Srgrimes } 3111638Srgrimes *tl = txdr_unsigned(mode); 3121638Srgrimes nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred); 3131638Srgrimes nfsm_postop_attr(vp, attrflag); 3141638Srgrimes if (!error) { 3151638Srgrimes nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 3161638Srgrimes rmode = fxdr_unsigned(u_long, *tl); 3171638Srgrimes /* 3181638Srgrimes * The NFS V3 spec does not clarify whether or not 3191638Srgrimes * the returned access bits can be a superset of 3201638Srgrimes * the ones requested, so... 3211638Srgrimes */ 3221638Srgrimes if ((rmode & mode) != mode) 3231638Srgrimes error = EACCES; 3241638Srgrimes } 3251638Srgrimes nfsm_reqdone; 3261638Srgrimes return (error); 3271638Srgrimes } else { 3281638Srgrimes if (error = nfsspec_access(ap)) 3291638Srgrimes return (error); 3301638Srgrimes 3311638Srgrimes /* 3321638Srgrimes * Attempt to prevent a mapped root from accessing a file 3331638Srgrimes * which it shouldn't. We try to read a byte from the file 3341638Srgrimes * if the user is root and the file is not zero length. 3351638Srgrimes * After calling nfsspec_access, we should have the correct 3361638Srgrimes * file size cached. 3371638Srgrimes */ 3381638Srgrimes if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD) 3391638Srgrimes && VTONFS(vp)->n_size > 0) { 3401638Srgrimes struct iovec aiov; 3411638Srgrimes struct uio auio; 3421638Srgrimes char buf[1]; 3431638Srgrimes 3441638Srgrimes aiov.iov_base = buf; 3451638Srgrimes aiov.iov_len = 1; 3461638Srgrimes auio.uio_iov = &aiov; 3471638Srgrimes auio.uio_iovcnt = 1; 3481638Srgrimes auio.uio_offset = 0; 3491638Srgrimes auio.uio_resid = 1; 3501638Srgrimes auio.uio_segflg = UIO_SYSSPACE; 3511638Srgrimes auio.uio_rw = UIO_READ; 3521638Srgrimes auio.uio_procp = ap->a_p; 3531638Srgrimes 3541638Srgrimes if (vp->v_type == VREG) 3551638Srgrimes error = nfs_readrpc(vp, &auio, ap->a_cred); 3561638Srgrimes else if (vp->v_type == VDIR) { 3571638Srgrimes char* bp; 3581638Srgrimes bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK); 3591638Srgrimes aiov.iov_base = bp; 3601638Srgrimes aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ; 3611638Srgrimes error = nfs_readdirrpc(vp, &auio, ap->a_cred); 3621638Srgrimes free(bp, M_TEMP); 3631638Srgrimes } else if (vp->v_type = VLNK) 3641638Srgrimes error = nfs_readlinkrpc(vp, &auio, ap->a_cred); 3651638Srgrimes else 3661638Srgrimes error = EACCES; 3671638Srgrimes } 3681638Srgrimes return (error); 3691638Srgrimes } 3701638Srgrimes} 3711638Srgrimes 3721638Srgrimes/* 3731638Srgrimes * nfs open vnode op 3741638Srgrimes * Check to see if the type is ok 3751638Srgrimes * and that deletion is not in progress. 3761638Srgrimes * For paged in text files, you will need to flush the page cache 3771638Srgrimes * if consistency is lost. 3781638Srgrimes */ 3791638Srgrimes/* ARGSUSED */ 3801638Srgrimesstatic int 3811638Srgrimesnfs_open(ap) 3821638Srgrimes struct vop_open_args /* { 3831638Srgrimes struct vnode *a_vp; 3841638Srgrimes int a_mode; 3851638Srgrimes struct ucred *a_cred; 3861638Srgrimes struct proc *a_p; 3871638Srgrimes } */ *ap; 3881638Srgrimes{ 3891638Srgrimes register struct vnode *vp = ap->a_vp; 3901638Srgrimes struct nfsnode *np = VTONFS(vp); 3911638Srgrimes struct nfsmount *nmp = VFSTONFS(vp->v_mount); 3921638Srgrimes struct vattr vattr; 3931638Srgrimes int error; 3941638Srgrimes 3951638Srgrimes if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) 3961638Srgrimes{ printf("open eacces vtyp=%d\n",vp->v_type); 3971638Srgrimes return (EACCES); 3981638Srgrimes} 3991638Srgrimes /* 4001638Srgrimes * Get a valid lease. If cached data is stale, flush it. 4011638Srgrimes */ 4021638Srgrimes if (nmp->nm_flag & NFSMNT_NQNFS) { 4031638Srgrimes if (NQNFS_CKINVALID(vp, np, ND_READ)) { 4041638Srgrimes do { 4051638Srgrimes error = nqnfs_getlease(vp, ND_READ, ap->a_cred, 4061638Srgrimes ap->a_p); 4071638Srgrimes } while (error == NQNFS_EXPIRED); 4081638Srgrimes if (error) { 4091638Srgrimes return (error); 4101638Srgrimes } 4111638Srgrimes if (np->n_lrev != np->n_brev || 4121638Srgrimes (np->n_flag & NQNFSNONCACHE)) { 4131638Srgrimes if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 4141856Sdg ap->a_p, 1)) == EINTR) { 4151638Srgrimes return (error); 4161638Srgrimes } 4171638Srgrimes np->n_brev = np->n_lrev; 4181638Srgrimes } 4191638Srgrimes } 4201638Srgrimes } else { 4211638Srgrimes if (np->n_flag & NMODIFIED) { 4221638Srgrimes if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 4231638Srgrimes ap->a_p, 1)) == EINTR) { 4241638Srgrimes return (error); 4251638Srgrimes } 4261638Srgrimes np->n_attrstamp = 0; 4271638Srgrimes if (vp->v_type == VDIR) 4281638Srgrimes np->n_direofoffset = 0; 4291638Srgrimes error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 4301638Srgrimes if (error) { 4311638Srgrimes return (error); 4321638Srgrimes } 4331638Srgrimes np->n_mtime = vattr.va_mtime.tv_sec; 4341638Srgrimes } else { 4351638Srgrimes error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 4361638Srgrimes if (error) { 4371638Srgrimes return (error); 4381638Srgrimes } 4391638Srgrimes if (np->n_mtime != vattr.va_mtime.tv_sec) { 4401638Srgrimes if (vp->v_type == VDIR) 4411638Srgrimes np->n_direofoffset = 0; 4421638Srgrimes if ((error = nfs_vinvalbuf(vp, V_SAVE, 4431638Srgrimes ap->a_cred, ap->a_p, 1)) == EINTR) { 4441638Srgrimes return (error); 4451638Srgrimes } 4461638Srgrimes np->n_mtime = vattr.va_mtime.tv_sec; 4471638Srgrimes } 4481638Srgrimes } 4491638Srgrimes } 4501638Srgrimes if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 4511638Srgrimes np->n_attrstamp = 0; /* For Open/Close consistency */ 4521638Srgrimes return (0); 4531638Srgrimes} 4541638Srgrimes 4551638Srgrimes/* 4561638Srgrimes * nfs close vnode op 4571638Srgrimes * What an NFS client should do upon close after writing is a debatable issue. 4581638Srgrimes * Most NFS clients push delayed writes to the server upon close, basically for 4591638Srgrimes * two reasons: 4601638Srgrimes * 1 - So that any write errors may be reported back to the client process 4611638Srgrimes * doing the close system call. By far the two most likely errors are 4621638Srgrimes * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 4631638Srgrimes * 2 - To put a worst case upper bound on cache inconsistency between 4641638Srgrimes * multiple clients for the file. 4651638Srgrimes * There is also a consistency problem for Version 2 of the protocol w.r.t. 4661638Srgrimes * not being able to tell if other clients are writing a file concurrently, 4671638Srgrimes * since there is no way of knowing if the changed modify time in the reply 4681638Srgrimes * is only due to the write for this client. 4691638Srgrimes * (NFS Version 3 provides weak cache consistency data in the reply that 4701638Srgrimes * should be sufficient to detect and handle this case.) 4711638Srgrimes * 4721638Srgrimes * The current code does the following: 4731638Srgrimes * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 4741638Srgrimes * for NFS Version 3 - flush dirty buffers to the server but don't invalidate 4751638Srgrimes * or commit them (this satisfies 1 and 2 except for the 4761638Srgrimes * case where the server crashes after this close but 4771638Srgrimes * before the commit RPC, which is felt to be "good 4781638Srgrimes * enough". Changing the last argument to nfs_flush() to 4791638Srgrimes * a 1 would force a commit operation, if it is felt a 4801638Srgrimes * commit is necessary now. 4811638Srgrimes * for NQNFS - do nothing now, since 2 is dealt with via leases and 4821638Srgrimes * 1 should be dealt with via an fsync() system call for 4831638Srgrimes * cases where write errors are important. 4841638Srgrimes */ 4851638Srgrimes/* ARGSUSED */ 4861638Srgrimesstatic int 4871638Srgrimesnfs_close(ap) 4881638Srgrimes struct vop_close_args /* { 4891638Srgrimes struct vnodeop_desc *a_desc; 4901638Srgrimes struct vnode *a_vp; 4911638Srgrimes int a_fflag; 4921638Srgrimes struct ucred *a_cred; 4931638Srgrimes struct proc *a_p; 4941638Srgrimes } */ *ap; 4951638Srgrimes{ 4961638Srgrimes register struct vnode *vp = ap->a_vp; 4971638Srgrimes register struct nfsnode *np = VTONFS(vp); 4981638Srgrimes int error = 0; 4991638Srgrimes 5001638Srgrimes if (vp->v_type == VREG) { 5011638Srgrimes if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 5021638Srgrimes (np->n_flag & NMODIFIED)) { 5031638Srgrimes if (NFS_ISV3(vp)) { 5041638Srgrimes error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0); 5051638Srgrimes np->n_flag &= ~NMODIFIED; 5061638Srgrimes } else 5071638Srgrimes error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 5081638Srgrimes np->n_attrstamp = 0; 5091638Srgrimes } 5101638Srgrimes if (np->n_flag & NWRITEERR) { 5111638Srgrimes np->n_flag &= ~NWRITEERR; 5121638Srgrimes error = np->n_error; 5131638Srgrimes } 5141638Srgrimes } 5151638Srgrimes return (error); 5161638Srgrimes} 5171638Srgrimes 5181638Srgrimes/* 5191638Srgrimes * nfs getattr call from vfs. 5201638Srgrimes */ 5211638Srgrimesstatic int 5221638Srgrimesnfs_getattr(ap) 5231638Srgrimes struct vop_getattr_args /* { 5241638Srgrimes struct vnode *a_vp; 5251638Srgrimes struct vattr *a_vap; 5261638Srgrimes struct ucred *a_cred; 5271638Srgrimes struct proc *a_p; 5281638Srgrimes } */ *ap; 5291638Srgrimes{ 5301638Srgrimes register struct vnode *vp = ap->a_vp; 5311638Srgrimes register struct nfsnode *np = VTONFS(vp); 5321638Srgrimes register caddr_t cp; 5331638Srgrimes register u_long *tl; 5341638Srgrimes register int t1, t2; 5351638Srgrimes caddr_t bpos, dpos; 5361638Srgrimes int error = 0; 5371638Srgrimes struct mbuf *mreq, *mrep, *md, *mb, *mb2; 5381638Srgrimes int v3 = NFS_ISV3(vp); 5391638Srgrimes 5401638Srgrimes /* 5411638Srgrimes * Update local times for special files. 5421638Srgrimes */ 5431638Srgrimes if (np->n_flag & (NACC | NUPD)) 5441638Srgrimes np->n_flag |= NCHG; 5451638Srgrimes /* 5461638Srgrimes * First look in the cache. 5471638Srgrimes */ 5481638Srgrimes if (nfs_getattrcache(vp, ap->a_vap) == 0) 5491638Srgrimes return (0); 5501638Srgrimes nfsstats.rpccnt[NFSPROC_GETATTR]++; 5511638Srgrimes nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3)); 5521638Srgrimes nfsm_fhtom(vp, v3); 5531638Srgrimes nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 5541638Srgrimes if (!error) 5551638Srgrimes nfsm_loadattr(vp, ap->a_vap); 5561638Srgrimes nfsm_reqdone; 5571638Srgrimes return (error); 5581638Srgrimes} 5591638Srgrimes 5601638Srgrimes/* 5611638Srgrimes * nfs setattr call. 5621638Srgrimes */ 5631638Srgrimesstatic int 5641638Srgrimesnfs_setattr(ap) 5651638Srgrimes struct vop_setattr_args /* { 5661638Srgrimes struct vnodeop_desc *a_desc; 5671638Srgrimes struct vnode *a_vp; 5681638Srgrimes struct vattr *a_vap; 5691638Srgrimes struct ucred *a_cred; 5701638Srgrimes struct proc *a_p; 5711638Srgrimes } */ *ap; 5721638Srgrimes{ 5731638Srgrimes register struct vnode *vp = ap->a_vp; 5741638Srgrimes register struct nfsnode *np = VTONFS(vp); 5751638Srgrimes register struct vattr *vap = ap->a_vap; 5761638Srgrimes int error = 0; 5771638Srgrimes u_quad_t tsize; 5781638Srgrimes 5791638Srgrimes#ifndef nolint 5801638Srgrimes tsize = (u_quad_t)0; 5811638Srgrimes#endif 5821638Srgrimes /* 5831638Srgrimes * Disallow write attempts if the filesystem is mounted read-only. 5841638Srgrimes */ 5851638Srgrimes if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 5861638Srgrimes vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 5871638Srgrimes vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && 5881638Srgrimes (vp->v_mount->mnt_flag & MNT_RDONLY)) 5891638Srgrimes return (EROFS); 5901638Srgrimes if (vap->va_size != VNOVAL) { 5911638Srgrimes switch (vp->v_type) { 5921638Srgrimes case VDIR: 5931856Sdg return (EISDIR); 5941856Sdg case VCHR: 5951856Sdg case VBLK: 5961638Srgrimes case VSOCK: 5971638Srgrimes case VFIFO: 5981638Srgrimes if (vap->va_mtime.tv_sec == VNOVAL && 5991638Srgrimes vap->va_atime.tv_sec == VNOVAL && 6001638Srgrimes vap->va_mode == (u_short)VNOVAL && 6011638Srgrimes vap->va_uid == (uid_t)VNOVAL && 6021638Srgrimes vap->va_gid == (gid_t)VNOVAL) 6031638Srgrimes return (0); 6041638Srgrimes vap->va_size = VNOVAL; 6051638Srgrimes break; 6061638Srgrimes default: 6071638Srgrimes /* 6081638Srgrimes * Disallow write attempts if the filesystem is 6091638Srgrimes * mounted read-only. 6101638Srgrimes */ 6111638Srgrimes if (vp->v_mount->mnt_flag & MNT_RDONLY) 6121638Srgrimes return (EROFS); 6131638Srgrimes if (np->n_flag & NMODIFIED) { 6141638Srgrimes if (vap->va_size == 0) 6151638Srgrimes error = nfs_vinvalbuf(vp, 0, 6161638Srgrimes ap->a_cred, ap->a_p, 1); 6171638Srgrimes else 6181638Srgrimes error = nfs_vinvalbuf(vp, V_SAVE, 619 ap->a_cred, ap->a_p, 1); 620 if (error) 621 return (error); 622 } 623 tsize = np->n_size; 624 np->n_size = np->n_vattr.va_size = vap->va_size; 625 vnode_pager_setsize(vp, (u_long)np->n_size); 626 }; 627 } else if ((vap->va_mtime.tv_sec != VNOVAL || 628 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) && 629 vp->v_type == VREG && 630 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 631 ap->a_p, 1)) == EINTR) 632 return (error); 633 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p); 634 if (error && vap->va_size != VNOVAL) { 635 np->n_size = np->n_vattr.va_size = tsize; 636 vnode_pager_setsize(vp, (u_long)np->n_size); 637 } 638 return (error); 639} 640 641/* 642 * Do an nfs setattr rpc. 643 */ 644static int 645nfs_setattrrpc(vp, vap, cred, procp) 646 register struct vnode *vp; 647 register struct vattr *vap; 648 struct ucred *cred; 649 struct proc *procp; 650{ 651 register struct nfsv2_sattr *sp; 652 register caddr_t cp; 653 register long t1, t2; 654 caddr_t bpos, dpos, cp2; 655 u_long *tl; 656 int error = 0, wccflag = NFSV3_WCCRATTR; 657 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 658 int v3 = NFS_ISV3(vp); 659 660 nfsstats.rpccnt[NFSPROC_SETATTR]++; 661 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3)); 662 nfsm_fhtom(vp, v3); 663 if (v3) { 664 if (vap->va_mode != (u_short)VNOVAL) { 665 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 666 *tl++ = nfs_true; 667 *tl = txdr_unsigned(vap->va_mode); 668 } else { 669 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 670 *tl = nfs_false; 671 } 672 if (vap->va_uid != (uid_t)VNOVAL) { 673 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 674 *tl++ = nfs_true; 675 *tl = txdr_unsigned(vap->va_uid); 676 } else { 677 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 678 *tl = nfs_false; 679 } 680 if (vap->va_gid != (gid_t)VNOVAL) { 681 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 682 *tl++ = nfs_true; 683 *tl = txdr_unsigned(vap->va_gid); 684 } else { 685 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 686 *tl = nfs_false; 687 } 688 if (vap->va_size != VNOVAL) { 689 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 690 *tl++ = nfs_true; 691 txdr_hyper(&vap->va_size, tl); 692 } else { 693 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 694 *tl = nfs_false; 695 } 696 if (vap->va_atime.tv_sec != VNOVAL) { 697 if (vap->va_atime.tv_sec != time_second) { 698 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 699 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 700 txdr_nfsv3time(&vap->va_atime, tl); 701 } else { 702 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 703 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 704 } 705 } else { 706 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 707 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 708 } 709 if (vap->va_mtime.tv_sec != VNOVAL) { 710 if (vap->va_mtime.tv_sec != time_second) { 711 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 712 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 713 txdr_nfsv3time(&vap->va_mtime, tl); 714 } else { 715 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 716 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 717 } 718 } else { 719 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 720 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 721 } 722 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 723 *tl = nfs_false; 724 } else { 725 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 726 if (vap->va_mode == (u_short)VNOVAL) 727 sp->sa_mode = VNOVAL; 728 else 729 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode); 730 if (vap->va_uid == (uid_t)VNOVAL) 731 sp->sa_uid = VNOVAL; 732 else 733 sp->sa_uid = txdr_unsigned(vap->va_uid); 734 if (vap->va_gid == (gid_t)VNOVAL) 735 sp->sa_gid = VNOVAL; 736 else 737 sp->sa_gid = txdr_unsigned(vap->va_gid); 738 sp->sa_size = txdr_unsigned(vap->va_size); 739 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 740 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 741 } 742 nfsm_request(vp, NFSPROC_SETATTR, procp, cred); 743 if (v3) { 744 nfsm_wcc_data(vp, wccflag); 745 } else 746 nfsm_loadattr(vp, (struct vattr *)0); 747 nfsm_reqdone; 748 return (error); 749} 750 751/* 752 * nfs lookup call, one step at a time... 753 * First look in cache 754 * If not found, unlock the directory nfsnode and do the rpc 755 */ 756static int 757nfs_lookup(ap) 758 struct vop_lookup_args /* { 759 struct vnodeop_desc *a_desc; 760 struct vnode *a_dvp; 761 struct vnode **a_vpp; 762 struct componentname *a_cnp; 763 } */ *ap; 764{ 765 register struct componentname *cnp = ap->a_cnp; 766 register struct vnode *dvp = ap->a_dvp; 767 register struct vnode **vpp = ap->a_vpp; 768 register int flags = cnp->cn_flags; 769 register struct vnode *newvp; 770 register u_long *tl; 771 register caddr_t cp; 772 register long t1, t2; 773 struct nfsmount *nmp; 774 caddr_t bpos, dpos, cp2; 775 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 776 long len; 777 nfsfh_t *fhp; 778 struct nfsnode *np; 779 int lockparent, wantparent, error = 0, attrflag, fhsize; 780 int v3 = NFS_ISV3(dvp); 781 struct proc *p = cnp->cn_proc; 782 783 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && 784 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 785 return (EROFS); 786 *vpp = NULLVP; 787 if (dvp->v_type != VDIR) 788 return (ENOTDIR); 789 lockparent = flags & LOCKPARENT; 790 wantparent = flags & (LOCKPARENT|WANTPARENT); 791 nmp = VFSTONFS(dvp->v_mount); 792 np = VTONFS(dvp); 793 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 794 struct vattr vattr; 795 int vpid; 796 797 if (error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p)) { 798 *vpp = NULLVP; 799 return (error); 800 } 801 802 newvp = *vpp; 803 vpid = newvp->v_id; 804 /* 805 * See the comment starting `Step through' in ufs/ufs_lookup.c 806 * for an explanation of the locking protocol 807 */ 808 if (dvp == newvp) { 809 VREF(newvp); 810 error = 0; 811 } else if (flags & ISDOTDOT) { 812 VOP_UNLOCK(dvp, 0, p); 813 error = vget(newvp, LK_EXCLUSIVE, p); 814 if (!error && lockparent && (flags & ISLASTCN)) 815 error = vn_lock(dvp, LK_EXCLUSIVE, p); 816 } else { 817 error = vget(newvp, LK_EXCLUSIVE, p); 818 if (!lockparent || error || !(flags & ISLASTCN)) 819 VOP_UNLOCK(dvp, 0, p); 820 } 821 if (!error) { 822 if (vpid == newvp->v_id) { 823 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p) 824 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { 825 nfsstats.lookupcache_hits++; 826 if (cnp->cn_nameiop != LOOKUP && 827 (flags & ISLASTCN)) 828 cnp->cn_flags |= SAVENAME; 829 return (0); 830 } 831 cache_purge(newvp); 832 } 833 vput(newvp); 834 if (lockparent && dvp != newvp && (flags & ISLASTCN)) 835 VOP_UNLOCK(dvp, 0, p); 836 } 837 error = vn_lock(dvp, LK_EXCLUSIVE, p); 838 *vpp = NULLVP; 839 if (error) 840 return (error); 841 } 842 error = 0; 843 newvp = NULLVP; 844 nfsstats.lookupcache_misses++; 845 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 846 len = cnp->cn_namelen; 847 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 848 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 849 nfsm_fhtom(dvp, v3); 850 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 851 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 852 if (error) { 853 nfsm_postop_attr(dvp, attrflag); 854 m_freem(mrep); 855 goto nfsmout; 856 } 857 nfsm_getfh(fhp, fhsize, v3); 858 859 /* 860 * Handle RENAME case... 861 */ 862 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 863 if (NFS_CMPFH(np, fhp, fhsize)) { 864 m_freem(mrep); 865 return (EISDIR); 866 } 867 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 868 m_freem(mrep); 869 return (error); 870 } 871 newvp = NFSTOV(np); 872 if (v3) { 873 nfsm_postop_attr(newvp, attrflag); 874 nfsm_postop_attr(dvp, attrflag); 875 } else 876 nfsm_loadattr(newvp, (struct vattr *)0); 877 *vpp = newvp; 878 m_freem(mrep); 879 cnp->cn_flags |= SAVENAME; 880 if (!lockparent) 881 VOP_UNLOCK(dvp, 0, p); 882 return (0); 883 } 884 885 if (flags & ISDOTDOT) { 886 VOP_UNLOCK(dvp, 0, p); 887 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 888 if (error) { 889 vn_lock(dvp, LK_EXCLUSIVE + LK_RETRY, p); 890 return (error); 891 } 892 newvp = NFSTOV(np); 893 if (lockparent && (flags & ISLASTCN) && 894 (error = vn_lock(dvp, LK_EXCLUSIVE, p))) { 895 vput(newvp); 896 return (error); 897 } 898 } else if (NFS_CMPFH(np, fhp, fhsize)) { 899 VREF(dvp); 900 newvp = dvp; 901 } else { 902 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 903 m_freem(mrep); 904 return (error); 905 } 906 if (!lockparent || !(flags & ISLASTCN)) 907 VOP_UNLOCK(dvp, 0, p); 908 newvp = NFSTOV(np); 909 } 910 if (v3) { 911 nfsm_postop_attr(newvp, attrflag); 912 nfsm_postop_attr(dvp, attrflag); 913 } else 914 nfsm_loadattr(newvp, (struct vattr *)0); 915 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 916 cnp->cn_flags |= SAVENAME; 917 if ((cnp->cn_flags & MAKEENTRY) && 918 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 919 np->n_ctime = np->n_vattr.va_ctime.tv_sec; 920 cache_enter(dvp, newvp, cnp); 921 } 922 *vpp = newvp; 923 nfsm_reqdone; 924 if (error) { 925 if (newvp != NULLVP) { 926 vrele(newvp); 927 *vpp = NULLVP; 928 } 929 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 930 (flags & ISLASTCN) && error == ENOENT) { 931 if (!lockparent) 932 VOP_UNLOCK(dvp, 0, p); 933 if (dvp->v_mount->mnt_flag & MNT_RDONLY) 934 error = EROFS; 935 else 936 error = EJUSTRETURN; 937 } 938 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 939 cnp->cn_flags |= SAVENAME; 940 } 941 return (error); 942} 943 944/* 945 * nfs read call. 946 * Just call nfs_bioread() to do the work. 947 */ 948static int 949nfs_read(ap) 950 struct vop_read_args /* { 951 struct vnode *a_vp; 952 struct uio *a_uio; 953 int a_ioflag; 954 struct ucred *a_cred; 955 } */ *ap; 956{ 957 register struct vnode *vp = ap->a_vp; 958 959 if (vp->v_type != VREG) 960 return (EPERM); 961 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0)); 962} 963 964/* 965 * nfs readlink call 966 */ 967static int 968nfs_readlink(ap) 969 struct vop_readlink_args /* { 970 struct vnode *a_vp; 971 struct uio *a_uio; 972 struct ucred *a_cred; 973 } */ *ap; 974{ 975 register struct vnode *vp = ap->a_vp; 976 977 if (vp->v_type != VLNK) 978 return (EPERM); 979 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0)); 980} 981 982/* 983 * Do a readlink rpc. 984 * Called by nfs_doio() from below the buffer cache. 985 */ 986int 987nfs_readlinkrpc(vp, uiop, cred) 988 register struct vnode *vp; 989 struct uio *uiop; 990 struct ucred *cred; 991{ 992 register u_long *tl; 993 register caddr_t cp; 994 register long t1, t2; 995 caddr_t bpos, dpos, cp2; 996 int error = 0, len, attrflag; 997 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 998 int v3 = NFS_ISV3(vp); 999 1000 nfsstats.rpccnt[NFSPROC_READLINK]++; 1001 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3)); 1002 nfsm_fhtom(vp, v3); 1003 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 1004 if (v3) 1005 nfsm_postop_attr(vp, attrflag); 1006 if (!error) { 1007 nfsm_strsiz(len, NFS_MAXPATHLEN); 1008 nfsm_mtouio(uiop, len); 1009 } 1010 nfsm_reqdone; 1011 return (error); 1012} 1013 1014/* 1015 * nfs read rpc call 1016 * Ditto above 1017 */ 1018int 1019nfs_readrpc(vp, uiop, cred) 1020 register struct vnode *vp; 1021 struct uio *uiop; 1022 struct ucred *cred; 1023{ 1024 register u_long *tl; 1025 register caddr_t cp; 1026 register long t1, t2; 1027 caddr_t bpos, dpos, cp2; 1028 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1029 struct nfsmount *nmp; 1030 int error = 0, len, retlen, tsiz, eof, attrflag; 1031 int v3 = NFS_ISV3(vp); 1032 1033#ifndef nolint 1034 eof = 0; 1035#endif 1036 nmp = VFSTONFS(vp->v_mount); 1037 tsiz = uiop->uio_resid; 1038 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 1039 return (EFBIG); 1040 while (tsiz > 0) { 1041 nfsstats.rpccnt[NFSPROC_READ]++; 1042 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 1043 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3); 1044 nfsm_fhtom(vp, v3); 1045 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3); 1046 if (v3) { 1047 txdr_hyper(&uiop->uio_offset, tl); 1048 *(tl + 2) = txdr_unsigned(len); 1049 } else { 1050 *tl++ = txdr_unsigned(uiop->uio_offset); 1051 *tl++ = txdr_unsigned(len); 1052 *tl = 0; 1053 } 1054 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 1055 if (v3) { 1056 nfsm_postop_attr(vp, attrflag); 1057 if (error) { 1058 m_freem(mrep); 1059 goto nfsmout; 1060 } 1061 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1062 eof = fxdr_unsigned(int, *(tl + 1)); 1063 } else 1064 nfsm_loadattr(vp, (struct vattr *)0); 1065 nfsm_strsiz(retlen, nmp->nm_rsize); 1066 nfsm_mtouio(uiop, retlen); 1067 m_freem(mrep); 1068 tsiz -= retlen; 1069 if (v3) { 1070 if (eof || retlen == 0) 1071 tsiz = 0; 1072 } else if (retlen < len) 1073 tsiz = 0; 1074 } 1075nfsmout: 1076 return (error); 1077} 1078 1079/* 1080 * nfs write call 1081 */ 1082int 1083nfs_writerpc(vp, uiop, cred, iomode, must_commit) 1084 register struct vnode *vp; 1085 register struct uio *uiop; 1086 struct ucred *cred; 1087 int *iomode, *must_commit; 1088{ 1089 register u_long *tl; 1090 register caddr_t cp; 1091 register int t1, t2, backup; 1092 caddr_t bpos, dpos, cp2; 1093 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1094 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1095 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit; 1096 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC; 1097 1098#ifndef DIAGNOSTIC 1099 if (uiop->uio_iovcnt != 1) 1100 panic("nfs: writerpc iovcnt > 1"); 1101#endif 1102 *must_commit = 0; 1103 tsiz = uiop->uio_resid; 1104 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 1105 return (EFBIG); 1106 while (tsiz > 0) { 1107 nfsstats.rpccnt[NFSPROC_WRITE]++; 1108 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 1109 nfsm_reqhead(vp, NFSPROC_WRITE, 1110 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 1111 nfsm_fhtom(vp, v3); 1112 if (v3) { 1113 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 1114 txdr_hyper(&uiop->uio_offset, tl); 1115 tl += 2; 1116 *tl++ = txdr_unsigned(len); 1117 *tl++ = txdr_unsigned(*iomode); 1118 } else { 1119 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED); 1120 *++tl = txdr_unsigned(uiop->uio_offset); 1121 tl += 2; 1122 } 1123 *tl = txdr_unsigned(len); 1124 nfsm_uiotom(uiop, len); 1125 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 1126 if (v3) { 1127 wccflag = NFSV3_WCCCHK; 1128 nfsm_wcc_data(vp, wccflag); 1129 if (!error) { 1130 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED + 1131 NFSX_V3WRITEVERF); 1132 rlen = fxdr_unsigned(int, *tl++); 1133 if (rlen == 0) { 1134 error = NFSERR_IO; 1135 break; 1136 } else if (rlen < len) { 1137 backup = len - rlen; 1138 uiop->uio_iov->iov_base -= backup; 1139 uiop->uio_iov->iov_len += backup; 1140 uiop->uio_offset -= backup; 1141 uiop->uio_resid += backup; 1142 len = rlen; 1143 } 1144 commit = fxdr_unsigned(int, *tl++); 1145 1146 /* 1147 * Return the lowest committment level 1148 * obtained by any of the RPCs. 1149 */ 1150 if (committed == NFSV3WRITE_FILESYNC) 1151 committed = commit; 1152 else if (committed == NFSV3WRITE_DATASYNC && 1153 commit == NFSV3WRITE_UNSTABLE) 1154 committed = commit; 1155 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) { 1156 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1157 NFSX_V3WRITEVERF); 1158 nmp->nm_flag |= NFSMNT_HASWRITEVERF; 1159 } else if (bcmp((caddr_t)tl, 1160 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) { 1161 *must_commit = 1; 1162 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1163 NFSX_V3WRITEVERF); 1164 } 1165 } 1166 } else 1167 nfsm_loadattr(vp, (struct vattr *)0); 1168 if (wccflag) 1169 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec; 1170 m_freem(mrep); 1171 tsiz -= len; 1172 } 1173nfsmout: 1174 if (vp->v_mount->mnt_flag & MNT_ASYNC) 1175 committed = NFSV3WRITE_FILESYNC; 1176 *iomode = committed; 1177 if (error) 1178 uiop->uio_resid = tsiz; 1179 return (error); 1180} 1181 1182/* 1183 * nfs mknod rpc 1184 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1185 * mode set to specify the file type and the size field for rdev. 1186 */ 1187static int 1188nfs_mknodrpc(dvp, vpp, cnp, vap) 1189 register struct vnode *dvp; 1190 register struct vnode **vpp; 1191 register struct componentname *cnp; 1192 register struct vattr *vap; 1193{ 1194 register struct nfsv2_sattr *sp; 1195 register struct nfsv3_sattr *sp3; 1196 register u_long *tl; 1197 register caddr_t cp; 1198 register long t1, t2; 1199 struct vnode *newvp = (struct vnode *)0; 1200 struct nfsnode *np = (struct nfsnode *)0; 1201 struct vattr vattr; 1202 char *cp2; 1203 caddr_t bpos, dpos; 1204 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0; 1205 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1206 u_long rdev; 1207 int v3 = NFS_ISV3(dvp); 1208 1209 if (vap->va_type == VCHR || vap->va_type == VBLK) 1210 rdev = txdr_unsigned(vap->va_rdev); 1211 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1212 rdev = 0xffffffff; 1213 else { 1214 VOP_ABORTOP(dvp, cnp); 1215 return (EOPNOTSUPP); 1216 } 1217 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1218 VOP_ABORTOP(dvp, cnp); 1219 return (error); 1220 } 1221 nfsstats.rpccnt[NFSPROC_MKNOD]++; 1222 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED + 1223 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1224 nfsm_fhtom(dvp, v3); 1225 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1226 if (v3) { 1227 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR); 1228 *tl++ = vtonfsv3_type(vap->va_type); 1229 sp3 = (struct nfsv3_sattr *)tl; 1230 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1231 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1232 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1233 *tl++ = txdr_unsigned(major(vap->va_rdev)); 1234 *tl = txdr_unsigned(minor(vap->va_rdev)); 1235 } 1236 } else { 1237 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1238 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1239 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1240 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1241 sp->sa_size = rdev; 1242 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1243 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1244 } 1245 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred); 1246 if (!error) { 1247 nfsm_mtofh(dvp, newvp, v3, gotvp); 1248 if (!gotvp) { 1249 if (newvp) { 1250 vput(newvp); 1251 newvp = (struct vnode *)0; 1252 } 1253 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1254 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1255 if (!error) 1256 newvp = NFSTOV(np); 1257 } 1258 } 1259 if (v3) 1260 nfsm_wcc_data(dvp, wccflag); 1261 nfsm_reqdone; 1262 if (error) { 1263 if (newvp) 1264 vput(newvp); 1265 } else { 1266 if (cnp->cn_flags & MAKEENTRY) 1267 cache_enter(dvp, newvp, cnp); 1268 *vpp = newvp; 1269 } 1270 zfree(namei_zone, cnp->cn_pnbuf); 1271 VTONFS(dvp)->n_flag |= NMODIFIED; 1272 if (!wccflag) 1273 VTONFS(dvp)->n_attrstamp = 0; 1274 return (error); 1275} 1276 1277/* 1278 * nfs mknod vop 1279 * just call nfs_mknodrpc() to do the work. 1280 */ 1281/* ARGSUSED */ 1282static int 1283nfs_mknod(ap) 1284 struct vop_mknod_args /* { 1285 struct vnode *a_dvp; 1286 struct vnode **a_vpp; 1287 struct componentname *a_cnp; 1288 struct vattr *a_vap; 1289 } */ *ap; 1290{ 1291 struct vnode *newvp; 1292 int error; 1293 1294 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap); 1295 if (!error) 1296 vput(newvp); 1297 return (error); 1298} 1299 1300static u_long create_verf; 1301/* 1302 * nfs file create call 1303 */ 1304static int 1305nfs_create(ap) 1306 struct vop_create_args /* { 1307 struct vnode *a_dvp; 1308 struct vnode **a_vpp; 1309 struct componentname *a_cnp; 1310 struct vattr *a_vap; 1311 } */ *ap; 1312{ 1313 register struct vnode *dvp = ap->a_dvp; 1314 register struct vattr *vap = ap->a_vap; 1315 register struct componentname *cnp = ap->a_cnp; 1316 register struct nfsv2_sattr *sp; 1317 register struct nfsv3_sattr *sp3; 1318 register u_long *tl; 1319 register caddr_t cp; 1320 register long t1, t2; 1321 struct nfsnode *np = (struct nfsnode *)0; 1322 struct vnode *newvp = (struct vnode *)0; 1323 caddr_t bpos, dpos, cp2; 1324 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0; 1325 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1326 struct vattr vattr; 1327 int v3 = NFS_ISV3(dvp); 1328 1329 /* 1330 * Oops, not for me.. 1331 */ 1332 if (vap->va_type == VSOCK) 1333 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1334 1335 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1336 VOP_ABORTOP(dvp, cnp); 1337 return (error); 1338 } 1339 if (vap->va_vaflags & VA_EXCLUSIVE) 1340 fmode |= O_EXCL; 1341again: 1342 nfsstats.rpccnt[NFSPROC_CREATE]++; 1343 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED + 1344 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1345 nfsm_fhtom(dvp, v3); 1346 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1347 if (v3) { 1348 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 1349 if (fmode & O_EXCL) { 1350 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); 1351 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF); 1352#ifdef INET 1353 if (!TAILQ_EMPTY(&in_ifaddrhead)) 1354 *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr; 1355 else 1356#endif 1357 *tl++ = create_verf; 1358 *tl = ++create_verf; 1359 } else { 1360 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED); 1361 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR); 1362 sp3 = (struct nfsv3_sattr *)tl; 1363 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1364 } 1365 } else { 1366 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1367 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1368 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1369 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1370 sp->sa_size = 0; 1371 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1372 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1373 } 1374 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1375 if (!error) { 1376 nfsm_mtofh(dvp, newvp, v3, gotvp); 1377 if (!gotvp) { 1378 if (newvp) { 1379 vput(newvp); 1380 newvp = (struct vnode *)0; 1381 } 1382 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1383 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1384 if (!error) 1385 newvp = NFSTOV(np); 1386 } 1387 } 1388 if (v3) 1389 nfsm_wcc_data(dvp, wccflag); 1390 nfsm_reqdone; 1391 if (error) { 1392 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) { 1393 fmode &= ~O_EXCL; 1394 goto again; 1395 } 1396 if (newvp) 1397 vput(newvp); 1398 } else if (v3 && (fmode & O_EXCL)) 1399 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc); 1400 if (!error) { 1401 if (cnp->cn_flags & MAKEENTRY) 1402 cache_enter(dvp, newvp, cnp); 1403 *ap->a_vpp = newvp; 1404 } 1405 zfree(namei_zone, cnp->cn_pnbuf); 1406 VTONFS(dvp)->n_flag |= NMODIFIED; 1407 if (!wccflag) 1408 VTONFS(dvp)->n_attrstamp = 0; 1409 return (error); 1410} 1411 1412/* 1413 * nfs file remove call 1414 * To try and make nfs semantics closer to ufs semantics, a file that has 1415 * other processes using the vnode is renamed instead of removed and then 1416 * removed later on the last close. 1417 * - If v_usecount > 1 1418 * If a rename is not already in the works 1419 * call nfs_sillyrename() to set it up 1420 * else 1421 * do the remove rpc 1422 */ 1423static int 1424nfs_remove(ap) 1425 struct vop_remove_args /* { 1426 struct vnodeop_desc *a_desc; 1427 struct vnode * a_dvp; 1428 struct vnode * a_vp; 1429 struct componentname * a_cnp; 1430 } */ *ap; 1431{ 1432 register struct vnode *vp = ap->a_vp; 1433 register struct vnode *dvp = ap->a_dvp; 1434 register struct componentname *cnp = ap->a_cnp; 1435 register struct nfsnode *np = VTONFS(vp); 1436 int error = 0; 1437 struct vattr vattr; 1438 1439#ifndef DIAGNOSTIC 1440 if ((cnp->cn_flags & HASBUF) == 0) 1441 panic("nfs_remove: no name"); 1442 if (vp->v_usecount < 1) 1443 panic("nfs_remove: bad v_usecount"); 1444#endif 1445 if (vp->v_usecount == 1 || (np->n_sillyrename && 1446 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 && 1447 vattr.va_nlink > 1)) { 1448 /* 1449 * Purge the name cache so that the chance of a lookup for 1450 * the name succeeding while the remove is in progress is 1451 * minimized. Without node locking it can still happen, such 1452 * that an I/O op returns ESTALE, but since you get this if 1453 * another host removes the file.. 1454 */ 1455 cache_purge(vp); 1456 /* 1457 * throw away biocache buffers, mainly to avoid 1458 * unnecessary delayed writes later. 1459 */ 1460 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1461 /* Do the rpc */ 1462 if (error != EINTR) 1463 error = nfs_removerpc(dvp, cnp->cn_nameptr, 1464 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); 1465 /* 1466 * Kludge City: If the first reply to the remove rpc is lost.. 1467 * the reply to the retransmitted request will be ENOENT 1468 * since the file was in fact removed 1469 * Therefore, we cheat and return success. 1470 */ 1471 if (error == ENOENT) 1472 error = 0; 1473 } else if (!np->n_sillyrename) 1474 error = nfs_sillyrename(dvp, vp, cnp); 1475 zfree(namei_zone, cnp->cn_pnbuf); 1476 np->n_attrstamp = 0; 1477 return (error); 1478} 1479 1480/* 1481 * nfs file remove rpc called from nfs_inactive 1482 */ 1483int 1484nfs_removeit(sp) 1485 register struct sillyrename *sp; 1486{ 1487 1488 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, 1489 (struct proc *)0)); 1490} 1491 1492/* 1493 * Nfs remove rpc, called from nfs_remove() and nfs_removeit(). 1494 */ 1495static int 1496nfs_removerpc(dvp, name, namelen, cred, proc) 1497 register struct vnode *dvp; 1498 char *name; 1499 int namelen; 1500 struct ucred *cred; 1501 struct proc *proc; 1502{ 1503 register u_long *tl; 1504 register caddr_t cp; 1505 register long t1, t2; 1506 caddr_t bpos, dpos, cp2; 1507 int error = 0, wccflag = NFSV3_WCCRATTR; 1508 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1509 int v3 = NFS_ISV3(dvp); 1510 1511 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1512 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1513 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 1514 nfsm_fhtom(dvp, v3); 1515 nfsm_strtom(name, namelen, NFS_MAXNAMLEN); 1516 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred); 1517 if (v3) 1518 nfsm_wcc_data(dvp, wccflag); 1519 nfsm_reqdone; 1520 VTONFS(dvp)->n_flag |= NMODIFIED; 1521 if (!wccflag) 1522 VTONFS(dvp)->n_attrstamp = 0; 1523 return (error); 1524} 1525 1526/* 1527 * nfs file rename call 1528 */ 1529static int 1530nfs_rename(ap) 1531 struct vop_rename_args /* { 1532 struct vnode *a_fdvp; 1533 struct vnode *a_fvp; 1534 struct componentname *a_fcnp; 1535 struct vnode *a_tdvp; 1536 struct vnode *a_tvp; 1537 struct componentname *a_tcnp; 1538 } */ *ap; 1539{ 1540 register struct vnode *fvp = ap->a_fvp; 1541 register struct vnode *tvp = ap->a_tvp; 1542 register struct vnode *fdvp = ap->a_fdvp; 1543 register struct vnode *tdvp = ap->a_tdvp; 1544 register struct componentname *tcnp = ap->a_tcnp; 1545 register struct componentname *fcnp = ap->a_fcnp; 1546 int error; 1547 1548#ifndef DIAGNOSTIC 1549 if ((tcnp->cn_flags & HASBUF) == 0 || 1550 (fcnp->cn_flags & HASBUF) == 0) 1551 panic("nfs_rename: no name"); 1552#endif 1553 /* Check for cross-device rename */ 1554 if ((fvp->v_mount != tdvp->v_mount) || 1555 (tvp && (fvp->v_mount != tvp->v_mount))) { 1556 error = EXDEV; 1557 goto out; 1558 } 1559 1560 /* 1561 * If the tvp exists and is in use, sillyrename it before doing the 1562 * rename of the new file over it. 1563 * XXX Can't sillyrename a directory. 1564 */ 1565 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && 1566 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { 1567 vput(tvp); 1568 tvp = NULL; 1569 } 1570 1571 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1572 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1573 tcnp->cn_proc); 1574 1575 if (fvp->v_type == VDIR) { 1576 if (tvp != NULL && tvp->v_type == VDIR) 1577 cache_purge(tdvp); 1578 cache_purge(fdvp); 1579 } 1580out: 1581 if (tdvp == tvp) 1582 vrele(tdvp); 1583 else 1584 vput(tdvp); 1585 if (tvp) 1586 vput(tvp); 1587 vrele(fdvp); 1588 vrele(fvp); 1589 /* 1590 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1591 */ 1592 if (error == ENOENT) 1593 error = 0; 1594 return (error); 1595} 1596 1597/* 1598 * nfs file rename rpc called from nfs_remove() above 1599 */ 1600static int 1601nfs_renameit(sdvp, scnp, sp) 1602 struct vnode *sdvp; 1603 struct componentname *scnp; 1604 register struct sillyrename *sp; 1605{ 1606 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, 1607 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc)); 1608} 1609 1610/* 1611 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1612 */ 1613static int 1614nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc) 1615 register struct vnode *fdvp; 1616 char *fnameptr; 1617 int fnamelen; 1618 register struct vnode *tdvp; 1619 char *tnameptr; 1620 int tnamelen; 1621 struct ucred *cred; 1622 struct proc *proc; 1623{ 1624 register u_long *tl; 1625 register caddr_t cp; 1626 register long t1, t2; 1627 caddr_t bpos, dpos, cp2; 1628 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; 1629 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1630 int v3 = NFS_ISV3(fdvp); 1631 1632 nfsstats.rpccnt[NFSPROC_RENAME]++; 1633 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1634 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) + 1635 nfsm_rndup(tnamelen)); 1636 nfsm_fhtom(fdvp, v3); 1637 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); 1638 nfsm_fhtom(tdvp, v3); 1639 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); 1640 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred); 1641 if (v3) { 1642 nfsm_wcc_data(fdvp, fwccflag); 1643 nfsm_wcc_data(tdvp, twccflag); 1644 } 1645 nfsm_reqdone; 1646 VTONFS(fdvp)->n_flag |= NMODIFIED; 1647 VTONFS(tdvp)->n_flag |= NMODIFIED; 1648 if (!fwccflag) 1649 VTONFS(fdvp)->n_attrstamp = 0; 1650 if (!twccflag) 1651 VTONFS(tdvp)->n_attrstamp = 0; 1652 return (error); 1653} 1654 1655/* 1656 * nfs hard link create call 1657 */ 1658static int 1659nfs_link(ap) 1660 struct vop_link_args /* { 1661 struct vnode *a_tdvp; 1662 struct vnode *a_vp; 1663 struct componentname *a_cnp; 1664 } */ *ap; 1665{ 1666 register struct vnode *vp = ap->a_vp; 1667 register struct vnode *tdvp = ap->a_tdvp; 1668 register struct componentname *cnp = ap->a_cnp; 1669 register u_long *tl; 1670 register caddr_t cp; 1671 register long t1, t2; 1672 caddr_t bpos, dpos, cp2; 1673 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0; 1674 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1675 int v3 = NFS_ISV3(vp); 1676 1677 if (vp->v_mount != tdvp->v_mount) { 1678 VOP_ABORTOP(vp, cnp); 1679 return (EXDEV); 1680 } 1681 1682 /* 1683 * Push all writes to the server, so that the attribute cache 1684 * doesn't get "out of sync" with the server. 1685 * XXX There should be a better way! 1686 */ 1687 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1688 1689 nfsstats.rpccnt[NFSPROC_LINK]++; 1690 nfsm_reqhead(vp, NFSPROC_LINK, 1691 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1692 nfsm_fhtom(vp, v3); 1693 nfsm_fhtom(tdvp, v3); 1694 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1695 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1696 if (v3) { 1697 nfsm_postop_attr(vp, attrflag); 1698 nfsm_wcc_data(tdvp, wccflag); 1699 } 1700 nfsm_reqdone; 1701 zfree(namei_zone, cnp->cn_pnbuf); 1702 VTONFS(tdvp)->n_flag |= NMODIFIED; 1703 if (!attrflag) 1704 VTONFS(vp)->n_attrstamp = 0; 1705 if (!wccflag) 1706 VTONFS(tdvp)->n_attrstamp = 0; 1707 /* 1708 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1709 */ 1710 if (error == EEXIST) 1711 error = 0; 1712 return (error); 1713} 1714 1715/* 1716 * nfs symbolic link create call 1717 */ 1718static int 1719nfs_symlink(ap) 1720 struct vop_symlink_args /* { 1721 struct vnode *a_dvp; 1722 struct vnode **a_vpp; 1723 struct componentname *a_cnp; 1724 struct vattr *a_vap; 1725 char *a_target; 1726 } */ *ap; 1727{ 1728 register struct vnode *dvp = ap->a_dvp; 1729 register struct vattr *vap = ap->a_vap; 1730 register struct componentname *cnp = ap->a_cnp; 1731 register struct nfsv2_sattr *sp; 1732 register struct nfsv3_sattr *sp3; 1733 register u_long *tl; 1734 register caddr_t cp; 1735 register long t1, t2; 1736 caddr_t bpos, dpos, cp2; 1737 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp; 1738 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1739 struct vnode *newvp = (struct vnode *)0; 1740 int v3 = NFS_ISV3(dvp); 1741 1742 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1743 slen = strlen(ap->a_target); 1744 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED + 1745 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3)); 1746 nfsm_fhtom(dvp, v3); 1747 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1748 if (v3) { 1749 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1750 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, 1751 cnp->cn_cred->cr_gid); 1752 } 1753 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1754 if (!v3) { 1755 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1756 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode); 1757 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1758 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1759 sp->sa_size = -1; 1760 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1761 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1762 } 1763 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1764 if (v3) { 1765 if (!error) 1766 nfsm_mtofh(dvp, newvp, v3, gotvp); 1767 nfsm_wcc_data(dvp, wccflag); 1768 } 1769 nfsm_reqdone; 1770 if (newvp) 1771 vput(newvp); 1772 zfree(namei_zone, cnp->cn_pnbuf); 1773 VTONFS(dvp)->n_flag |= NMODIFIED; 1774 if (!wccflag) 1775 VTONFS(dvp)->n_attrstamp = 0; 1776 /* 1777 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1778 */ 1779 if (error == EEXIST) 1780 error = 0; 1781 return (error); 1782} 1783 1784/* 1785 * nfs make dir call 1786 */ 1787static int 1788nfs_mkdir(ap) 1789 struct vop_mkdir_args /* { 1790 struct vnode *a_dvp; 1791 struct vnode **a_vpp; 1792 struct componentname *a_cnp; 1793 struct vattr *a_vap; 1794 } */ *ap; 1795{ 1796 register struct vnode *dvp = ap->a_dvp; 1797 register struct vattr *vap = ap->a_vap; 1798 register struct componentname *cnp = ap->a_cnp; 1799 register struct nfsv2_sattr *sp; 1800 register struct nfsv3_sattr *sp3; 1801 register u_long *tl; 1802 register caddr_t cp; 1803 register long t1, t2; 1804 register int len; 1805 struct nfsnode *np = (struct nfsnode *)0; 1806 struct vnode *newvp = (struct vnode *)0; 1807 caddr_t bpos, dpos, cp2; 1808 int error = 0, wccflag = NFSV3_WCCRATTR; 1809 int gotvp = 0; 1810 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1811 struct vattr vattr; 1812 int v3 = NFS_ISV3(dvp); 1813 1814 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1815 VOP_ABORTOP(dvp, cnp); 1816 return (error); 1817 } 1818 len = cnp->cn_namelen; 1819 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1820 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1821 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3)); 1822 nfsm_fhtom(dvp, v3); 1823 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1824 if (v3) { 1825 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1826 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1827 } else { 1828 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1829 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); 1830 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1831 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1832 sp->sa_size = -1; 1833 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1834 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1835 } 1836 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1837 if (!error) 1838 nfsm_mtofh(dvp, newvp, v3, gotvp); 1839 if (v3) 1840 nfsm_wcc_data(dvp, wccflag); 1841 nfsm_reqdone; 1842 VTONFS(dvp)->n_flag |= NMODIFIED; 1843 if (!wccflag) 1844 VTONFS(dvp)->n_attrstamp = 0; 1845 /* 1846 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1847 * if we can succeed in looking up the directory. 1848 */ 1849 if (error == EEXIST || (!error && !gotvp)) { 1850 if (newvp) { 1851 vrele(newvp); 1852 newvp = (struct vnode *)0; 1853 } 1854 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, 1855 cnp->cn_proc, &np); 1856 if (!error) { 1857 newvp = NFSTOV(np); 1858 if (newvp->v_type != VDIR) 1859 error = EEXIST; 1860 } 1861 } 1862 if (error) { 1863 if (newvp) 1864 vrele(newvp); 1865 } else 1866 *ap->a_vpp = newvp; 1867 zfree(namei_zone, cnp->cn_pnbuf); 1868 return (error); 1869} 1870 1871/* 1872 * nfs remove directory call 1873 */ 1874static int 1875nfs_rmdir(ap) 1876 struct vop_rmdir_args /* { 1877 struct vnode *a_dvp; 1878 struct vnode *a_vp; 1879 struct componentname *a_cnp; 1880 } */ *ap; 1881{ 1882 register struct vnode *vp = ap->a_vp; 1883 register struct vnode *dvp = ap->a_dvp; 1884 register struct componentname *cnp = ap->a_cnp; 1885 register u_long *tl; 1886 register caddr_t cp; 1887 register long t1, t2; 1888 caddr_t bpos, dpos, cp2; 1889 int error = 0, wccflag = NFSV3_WCCRATTR; 1890 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1891 int v3 = NFS_ISV3(dvp); 1892 1893 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1894 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1895 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1896 nfsm_fhtom(dvp, v3); 1897 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1898 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1899 if (v3) 1900 nfsm_wcc_data(dvp, wccflag); 1901 nfsm_reqdone; 1902 zfree(namei_zone, cnp->cn_pnbuf); 1903 VTONFS(dvp)->n_flag |= NMODIFIED; 1904 if (!wccflag) 1905 VTONFS(dvp)->n_attrstamp = 0; 1906 cache_purge(dvp); 1907 cache_purge(vp); 1908 /* 1909 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1910 */ 1911 if (error == ENOENT) 1912 error = 0; 1913 return (error); 1914} 1915 1916/* 1917 * nfs readdir call 1918 */ 1919static int 1920nfs_readdir(ap) 1921 struct vop_readdir_args /* { 1922 struct vnode *a_vp; 1923 struct uio *a_uio; 1924 struct ucred *a_cred; 1925 } */ *ap; 1926{ 1927 register struct vnode *vp = ap->a_vp; 1928 register struct nfsnode *np = VTONFS(vp); 1929 register struct uio *uio = ap->a_uio; 1930 int tresid, error; 1931 struct vattr vattr; 1932 1933 if (vp->v_type != VDIR) 1934 return (EPERM); 1935 /* 1936 * First, check for hit on the EOF offset cache 1937 */ 1938 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && 1939 (np->n_flag & NMODIFIED) == 0) { 1940 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1941 if (NQNFS_CKCACHABLE(vp, ND_READ)) { 1942 nfsstats.direofcache_hits++; 1943 return (0); 1944 } 1945 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1946 np->n_mtime == vattr.va_mtime.tv_sec) { 1947 nfsstats.direofcache_hits++; 1948 return (0); 1949 } 1950 } 1951 1952 /* 1953 * Call nfs_bioread() to do the real work. 1954 */ 1955 tresid = uio->uio_resid; 1956 error = nfs_bioread(vp, uio, 0, ap->a_cred, 0); 1957 1958 if (!error && uio->uio_resid == tresid) 1959 nfsstats.direofcache_misses++; 1960 return (error); 1961} 1962 1963/* 1964 * Readdir rpc call. 1965 * Called from below the buffer cache by nfs_doio(). 1966 */ 1967int 1968nfs_readdirrpc(vp, uiop, cred) 1969 struct vnode *vp; 1970 register struct uio *uiop; 1971 struct ucred *cred; 1972 1973{ 1974 register int len, left; 1975 register struct dirent *dp; 1976 register u_long *tl; 1977 register caddr_t cp; 1978 register long t1, t2; 1979 register nfsuint64 *cookiep; 1980 caddr_t bpos, dpos, cp2; 1981 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1982 nfsuint64 cookie; 1983 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1984 struct nfsnode *dnp = VTONFS(vp); 1985 u_quad_t fileno; 1986 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; 1987 int attrflag; 1988 int v3 = NFS_ISV3(vp); 1989 1990#ifndef nolint 1991 dp = (struct dirent *)0; 1992#endif 1993#ifndef DIAGNOSTIC 1994 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) || 1995 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 1996 panic("nfs readdirrpc bad uio"); 1997#endif 1998 1999 /* 2000 * If there is no cookie, assume directory was stale. 2001 */ 2002 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2003 if (cookiep) 2004 cookie = *cookiep; 2005 else 2006 return (NFSERR_BAD_COOKIE); 2007 /* 2008 * Loop around doing readdir rpc's of size nm_readdirsize 2009 * truncated to a multiple of DIRBLKSIZ. 2010 * The stopping criteria is EOF or buffer full. 2011 */ 2012 while (more_dirs && bigenough) { 2013 nfsstats.rpccnt[NFSPROC_READDIR]++; 2014 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) + 2015 NFSX_READDIR(v3)); 2016 nfsm_fhtom(vp, v3); 2017 if (v3) { 2018 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 2019 *tl++ = cookie.nfsuquad[0]; 2020 *tl++ = cookie.nfsuquad[1]; 2021 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2022 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2023 } else { 2024 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 2025 *tl++ = cookie.nfsuquad[0]; 2026 } 2027 *tl = txdr_unsigned(nmp->nm_readdirsize); 2028 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 2029 if (v3) { 2030 nfsm_postop_attr(vp, attrflag); 2031 if (!error) { 2032 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2033 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2034 dnp->n_cookieverf.nfsuquad[1] = *tl; 2035 } else { 2036 m_freem(mrep); 2037 goto nfsmout; 2038 } 2039 } 2040 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2041 more_dirs = fxdr_unsigned(int, *tl); 2042 2043 /* loop thru the dir entries, doctoring them to 4bsd form */ 2044 while (more_dirs && bigenough) { 2045 if (v3) { 2046 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2047 fxdr_hyper(tl, &fileno); 2048 len = fxdr_unsigned(int, *(tl + 2)); 2049 } else { 2050 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2051 fileno = fxdr_unsigned(u_quad_t, *tl++); 2052 len = fxdr_unsigned(int, *tl); 2053 } 2054 if (len <= 0 || len > NFS_MAXNAMLEN) { 2055 error = EBADRPC; 2056 m_freem(mrep); 2057 goto nfsmout; 2058 } 2059 tlen = nfsm_rndup(len); 2060 if (tlen == len) 2061 tlen += 4; /* To ensure null termination */ 2062 left = DIRBLKSIZ - blksiz; 2063 if ((tlen + DIRHDSIZ) > left) { 2064 dp->d_reclen += left; 2065 uiop->uio_iov->iov_base += left; 2066 uiop->uio_iov->iov_len -= left; 2067 uiop->uio_offset += left; 2068 uiop->uio_resid -= left; 2069 blksiz = 0; 2070 } 2071 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2072 bigenough = 0; 2073 if (bigenough) { 2074 dp = (struct dirent *)uiop->uio_iov->iov_base; 2075 dp->d_fileno = (int)fileno; 2076 dp->d_namlen = len; 2077 dp->d_reclen = tlen + DIRHDSIZ; 2078 dp->d_type = DT_UNKNOWN; 2079 blksiz += dp->d_reclen; 2080 if (blksiz == DIRBLKSIZ) 2081 blksiz = 0; 2082 uiop->uio_offset += DIRHDSIZ; 2083 uiop->uio_resid -= DIRHDSIZ; 2084 uiop->uio_iov->iov_base += DIRHDSIZ; 2085 uiop->uio_iov->iov_len -= DIRHDSIZ; 2086 nfsm_mtouio(uiop, len); 2087 cp = uiop->uio_iov->iov_base; 2088 tlen -= len; 2089 *cp = '\0'; /* null terminate */ 2090 uiop->uio_iov->iov_base += tlen; 2091 uiop->uio_iov->iov_len -= tlen; 2092 uiop->uio_offset += tlen; 2093 uiop->uio_resid -= tlen; 2094 } else 2095 nfsm_adv(nfsm_rndup(len)); 2096 if (v3) { 2097 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2098 } else { 2099 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2100 } 2101 if (bigenough) { 2102 cookie.nfsuquad[0] = *tl++; 2103 if (v3) 2104 cookie.nfsuquad[1] = *tl++; 2105 } else if (v3) 2106 tl += 2; 2107 else 2108 tl++; 2109 more_dirs = fxdr_unsigned(int, *tl); 2110 } 2111 /* 2112 * If at end of rpc data, get the eof boolean 2113 */ 2114 if (!more_dirs) { 2115 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2116 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2117 } 2118 m_freem(mrep); 2119 } 2120 /* 2121 * Fill last record, iff any, out to a multiple of DIRBLKSIZ 2122 * by increasing d_reclen for the last record. 2123 */ 2124 if (blksiz > 0) { 2125 left = DIRBLKSIZ - blksiz; 2126 dp->d_reclen += left; 2127 uiop->uio_iov->iov_base += left; 2128 uiop->uio_iov->iov_len -= left; 2129 uiop->uio_offset += left; 2130 uiop->uio_resid -= left; 2131 } 2132 2133 /* 2134 * We are now either at the end of the directory or have filled the 2135 * block. 2136 */ 2137 if (bigenough) 2138 dnp->n_direofoffset = uiop->uio_offset; 2139 else { 2140 if (uiop->uio_resid > 0) 2141 printf("EEK! readdirrpc resid > 0\n"); 2142 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2143 *cookiep = cookie; 2144 } 2145nfsmout: 2146 return (error); 2147} 2148 2149/* 2150 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2151 */ 2152int 2153nfs_readdirplusrpc(vp, uiop, cred) 2154 struct vnode *vp; 2155 register struct uio *uiop; 2156 struct ucred *cred; 2157{ 2158 register int len, left; 2159 register struct dirent *dp; 2160 register u_long *tl; 2161 register caddr_t cp; 2162 register long t1, t2; 2163 register struct vnode *newvp; 2164 register nfsuint64 *cookiep; 2165 caddr_t bpos, dpos, cp2, dpossav1, dpossav2; 2166 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2; 2167 struct nameidata nami, *ndp = &nami; 2168 struct componentname *cnp = &ndp->ni_cnd; 2169 nfsuint64 cookie; 2170 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2171 struct nfsnode *dnp = VTONFS(vp), *np; 2172 nfsfh_t *fhp; 2173 u_quad_t fileno; 2174 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2175 int attrflag, fhsize; 2176 2177#ifndef nolint 2178 dp = (struct dirent *)0; 2179#endif 2180#ifndef DIAGNOSTIC 2181 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) || 2182 (uiop->uio_resid & (DIRBLKSIZ - 1))) 2183 panic("nfs readdirplusrpc bad uio"); 2184#endif 2185 ndp->ni_dvp = vp; 2186 newvp = NULLVP; 2187 2188 /* 2189 * If there is no cookie, assume directory was stale. 2190 */ 2191 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2192 if (cookiep) 2193 cookie = *cookiep; 2194 else 2195 return (NFSERR_BAD_COOKIE); 2196 /* 2197 * Loop around doing readdir rpc's of size nm_readdirsize 2198 * truncated to a multiple of DIRBLKSIZ. 2199 * The stopping criteria is EOF or buffer full. 2200 */ 2201 while (more_dirs && bigenough) { 2202 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2203 nfsm_reqhead(vp, NFSPROC_READDIRPLUS, 2204 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2205 nfsm_fhtom(vp, 1); 2206 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED); 2207 *tl++ = cookie.nfsuquad[0]; 2208 *tl++ = cookie.nfsuquad[1]; 2209 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2210 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2211 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2212 *tl = txdr_unsigned(nmp->nm_rsize); 2213 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred); 2214 nfsm_postop_attr(vp, attrflag); 2215 if (error) { 2216 m_freem(mrep); 2217 goto nfsmout; 2218 } 2219 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2220 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2221 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2222 more_dirs = fxdr_unsigned(int, *tl); 2223 2224 /* loop thru the dir entries, doctoring them to 4bsd form */ 2225 while (more_dirs && bigenough) { 2226 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2227 fxdr_hyper(tl, &fileno); 2228 len = fxdr_unsigned(int, *(tl + 2)); 2229 if (len <= 0 || len > NFS_MAXNAMLEN) { 2230 error = EBADRPC; 2231 m_freem(mrep); 2232 goto nfsmout; 2233 } 2234 tlen = nfsm_rndup(len); 2235 if (tlen == len) 2236 tlen += 4; /* To ensure null termination*/ 2237 left = DIRBLKSIZ - blksiz; 2238 if ((tlen + DIRHDSIZ) > left) { 2239 dp->d_reclen += left; 2240 uiop->uio_iov->iov_base += left; 2241 uiop->uio_iov->iov_len -= left; 2242 uiop->uio_offset += left; 2243 uiop->uio_resid -= left; 2244 blksiz = 0; 2245 } 2246 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2247 bigenough = 0; 2248 if (bigenough) { 2249 dp = (struct dirent *)uiop->uio_iov->iov_base; 2250 dp->d_fileno = (int)fileno; 2251 dp->d_namlen = len; 2252 dp->d_reclen = tlen + DIRHDSIZ; 2253 dp->d_type = DT_UNKNOWN; 2254 blksiz += dp->d_reclen; 2255 if (blksiz == DIRBLKSIZ) 2256 blksiz = 0; 2257 uiop->uio_offset += DIRHDSIZ; 2258 uiop->uio_resid -= DIRHDSIZ; 2259 uiop->uio_iov->iov_base += DIRHDSIZ; 2260 uiop->uio_iov->iov_len -= DIRHDSIZ; 2261 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2262 cnp->cn_namelen = len; 2263 nfsm_mtouio(uiop, len); 2264 cp = uiop->uio_iov->iov_base; 2265 tlen -= len; 2266 *cp = '\0'; 2267 uiop->uio_iov->iov_base += tlen; 2268 uiop->uio_iov->iov_len -= tlen; 2269 uiop->uio_offset += tlen; 2270 uiop->uio_resid -= tlen; 2271 } else 2272 nfsm_adv(nfsm_rndup(len)); 2273 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2274 if (bigenough) { 2275 cookie.nfsuquad[0] = *tl++; 2276 cookie.nfsuquad[1] = *tl++; 2277 } else 2278 tl += 2; 2279 2280 /* 2281 * Since the attributes are before the file handle 2282 * (sigh), we must skip over the attributes and then 2283 * come back and get them. 2284 */ 2285 attrflag = fxdr_unsigned(int, *tl); 2286 if (attrflag) { 2287 dpossav1 = dpos; 2288 mdsav1 = md; 2289 nfsm_adv(NFSX_V3FATTR); 2290 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2291 doit = fxdr_unsigned(int, *tl); 2292 if (doit) { 2293 nfsm_getfh(fhp, fhsize, 1); 2294 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2295 VREF(vp); 2296 newvp = vp; 2297 np = dnp; 2298 } else { 2299 if (error = nfs_nget(vp->v_mount, fhp, 2300 fhsize, &np)) 2301 doit = 0; 2302 else 2303 newvp = NFSTOV(np); 2304 } 2305 } 2306 if (doit) { 2307 dpossav2 = dpos; 2308 dpos = dpossav1; 2309 mdsav2 = md; 2310 md = mdsav1; 2311 nfsm_loadattr(newvp, (struct vattr *)0); 2312 dpos = dpossav2; 2313 md = mdsav2; 2314 dp->d_type = 2315 IFTODT(VTTOIF(np->n_vattr.va_type)); 2316 ndp->ni_vp = newvp; 2317 cnp->cn_hash = 0; 2318 for (cp = cnp->cn_nameptr, i = 1; i <= len; 2319 i++, cp++) 2320 cnp->cn_hash += (unsigned char)*cp * i; 2321 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 2322 } 2323 } else { 2324 /* Just skip over the file handle */ 2325 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2326 i = fxdr_unsigned(int, *tl); 2327 nfsm_adv(nfsm_rndup(i)); 2328 } 2329 if (newvp != NULLVP) { 2330 vrele(newvp); 2331 newvp = NULLVP; 2332 } 2333 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2334 more_dirs = fxdr_unsigned(int, *tl); 2335 } 2336 /* 2337 * If at end of rpc data, get the eof boolean 2338 */ 2339 if (!more_dirs) { 2340 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2341 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2342 } 2343 m_freem(mrep); 2344 } 2345 /* 2346 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 2347 * by increasing d_reclen for the last record. 2348 */ 2349 if (blksiz > 0) { 2350 left = DIRBLKSIZ - blksiz; 2351 dp->d_reclen += left; 2352 uiop->uio_iov->iov_base += left; 2353 uiop->uio_iov->iov_len -= left; 2354 uiop->uio_offset += left; 2355 uiop->uio_resid -= left; 2356 } 2357 2358 /* 2359 * We are now either at the end of the directory or have filled the 2360 * block. 2361 */ 2362 if (bigenough) 2363 dnp->n_direofoffset = uiop->uio_offset; 2364 else { 2365 if (uiop->uio_resid > 0) 2366 printf("EEK! readdirplusrpc resid > 0\n"); 2367 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2368 *cookiep = cookie; 2369 } 2370nfsmout: 2371 if (newvp != NULLVP) { 2372 if (newvp == vp) 2373 vrele(newvp); 2374 else 2375 vput(newvp); 2376 newvp = NULLVP; 2377 } 2378 return (error); 2379} 2380 2381/* 2382 * Silly rename. To make the NFS filesystem that is stateless look a little 2383 * more like the "ufs" a remove of an active vnode is translated to a rename 2384 * to a funny looking filename that is removed by nfs_inactive on the 2385 * nfsnode. There is the potential for another process on a different client 2386 * to create the same funny name between the nfs_lookitup() fails and the 2387 * nfs_rename() completes, but... 2388 */ 2389static int 2390nfs_sillyrename(dvp, vp, cnp) 2391 struct vnode *dvp, *vp; 2392 struct componentname *cnp; 2393{ 2394 register struct sillyrename *sp; 2395 struct nfsnode *np; 2396 int error; 2397 short pid; 2398 2399 cache_purge(dvp); 2400 np = VTONFS(vp); 2401#ifndef DIAGNOSTIC 2402 if (vp->v_type == VDIR) 2403 panic("nfs: sillyrename dir"); 2404#endif 2405 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2406 M_NFSREQ, M_WAITOK); 2407 sp->s_cred = crdup(cnp->cn_cred); 2408 sp->s_dvp = dvp; 2409 VREF(dvp); 2410 2411 /* Fudge together a funny name */ 2412 pid = cnp->cn_proc->p_pid; 2413 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid); 2414 2415 /* Try lookitups until we get one that isn't there */ 2416 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2417 cnp->cn_proc, (struct nfsnode **)0) == 0) { 2418 sp->s_name[4]++; 2419 if (sp->s_name[4] > 'z') { 2420 error = EINVAL; 2421 goto bad; 2422 } 2423 } 2424 if (error = nfs_renameit(dvp, cnp, sp)) 2425 goto bad; 2426 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2427 cnp->cn_proc, &np); 2428 np->n_sillyrename = sp; 2429 return (0); 2430bad: 2431 vrele(sp->s_dvp); 2432 crfree(sp->s_cred); 2433 free((caddr_t)sp, M_NFSREQ); 2434 return (error); 2435} 2436 2437/* 2438 * Look up a file name and optionally either update the file handle or 2439 * allocate an nfsnode, depending on the value of npp. 2440 * npp == NULL --> just do the lookup 2441 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2442 * handled too 2443 * *npp != NULL --> update the file handle in the vnode 2444 */ 2445static int 2446nfs_lookitup(dvp, name, len, cred, procp, npp) 2447 register struct vnode *dvp; 2448 char *name; 2449 int len; 2450 struct ucred *cred; 2451 struct proc *procp; 2452 struct nfsnode **npp; 2453{ 2454 register u_long *tl; 2455 register caddr_t cp; 2456 register long t1, t2; 2457 struct vnode *newvp = (struct vnode *)0; 2458 struct nfsnode *np, *dnp = VTONFS(dvp); 2459 caddr_t bpos, dpos, cp2; 2460 int error = 0, fhlen, attrflag; 2461 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2462 nfsfh_t *nfhp; 2463 int v3 = NFS_ISV3(dvp); 2464 2465 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2466 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 2467 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 2468 nfsm_fhtom(dvp, v3); 2469 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2470 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred); 2471 if (npp && !error) { 2472 nfsm_getfh(nfhp, fhlen, v3); 2473 if (*npp) { 2474 np = *npp; 2475 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 2476 free((caddr_t)np->n_fhp, M_NFSBIGFH); 2477 np->n_fhp = &np->n_fh; 2478 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 2479 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 2480 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); 2481 np->n_fhsize = fhlen; 2482 newvp = NFSTOV(np); 2483 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2484 VREF(dvp); 2485 newvp = dvp; 2486 } else { 2487 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2488 if (error) { 2489 m_freem(mrep); 2490 return (error); 2491 } 2492 newvp = NFSTOV(np); 2493 } 2494 if (v3) { 2495 nfsm_postop_attr(newvp, attrflag); 2496 if (!attrflag && *npp == NULL) { 2497 m_freem(mrep); 2498 if (newvp == dvp) 2499 vrele(newvp); 2500 else 2501 vput(newvp); 2502 return (ENOENT); 2503 } 2504 } else 2505 nfsm_loadattr(newvp, (struct vattr *)0); 2506 } 2507 nfsm_reqdone; 2508 if (npp && *npp == NULL) { 2509 if (error) { 2510 if (newvp) 2511 if (newvp == dvp) 2512 vrele(newvp); 2513 else 2514 vput(newvp); 2515 } else 2516 *npp = np; 2517 } 2518 return (error); 2519} 2520 2521/* 2522 * Nfs Version 3 commit rpc 2523 */ 2524static int 2525nfs_commit(vp, offset, cnt, cred, procp) 2526 register struct vnode *vp; 2527 u_quad_t offset; 2528 int cnt; 2529 struct ucred *cred; 2530 struct proc *procp; 2531{ 2532 register caddr_t cp; 2533 register u_long *tl; 2534 register int t1, t2; 2535 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2536 caddr_t bpos, dpos, cp2; 2537 int error = 0, wccflag = NFSV3_WCCRATTR; 2538 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2539 2540 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) 2541 return (0); 2542 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2543 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1)); 2544 nfsm_fhtom(vp, 1); 2545 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 2546 txdr_hyper(&offset, tl); 2547 tl += 2; 2548 *tl = txdr_unsigned(cnt); 2549 nfsm_request(vp, NFSPROC_COMMIT, procp, cred); 2550 nfsm_wcc_data(vp, wccflag); 2551 if (!error) { 2552 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF); 2553 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl, 2554 NFSX_V3WRITEVERF)) { 2555 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 2556 NFSX_V3WRITEVERF); 2557 error = NFSERR_STALEWRITEVERF; 2558 } 2559 } 2560 nfsm_reqdone; 2561 return (error); 2562} 2563 2564/* 2565 * Kludge City.. 2566 * - make nfs_bmap() essentially a no-op that does no translation 2567 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2568 * (Maybe I could use the process's page mapping, but I was concerned that 2569 * Kernel Write might not be enabled and also figured copyout() would do 2570 * a lot more work than bcopy() and also it currently happens in the 2571 * context of the swapper process (2). 2572 */ 2573static int 2574nfs_bmap(ap) 2575 struct vop_bmap_args /* { 2576 struct vnode *a_vp; 2577 daddr_t a_bn; 2578 struct vnode **a_vpp; 2579 daddr_t *a_bnp; 2580 int *a_runp; 2581 int *a_runb; 2582 } */ *ap; 2583{ 2584 register struct vnode *vp = ap->a_vp; 2585 2586 if (ap->a_vpp != NULL) 2587 *ap->a_vpp = vp; 2588 if (ap->a_bnp != NULL) 2589 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2590 if (ap->a_runp != NULL) 2591 *ap->a_runp = 0; 2592 if (ap->a_runb != NULL) 2593 *ap->a_runb = 0; 2594 return (0); 2595} 2596 2597/* 2598 * Strategy routine. 2599 * For async requests when nfsiod(s) are running, queue the request by 2600 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2601 * request. 2602 */ 2603static int 2604nfs_strategy(ap) 2605 struct vop_strategy_args *ap; 2606{ 2607 register struct buf *bp = ap->a_bp; 2608 struct ucred *cr; 2609 struct proc *p; 2610 int error = 0; 2611 2612 if (bp->b_flags & B_PHYS) 2613 panic("nfs physio"); 2614 if (bp->b_flags & B_ASYNC) 2615 p = (struct proc *)0; 2616 else 2617 p = curproc; /* XXX */ 2618 if (bp->b_flags & B_READ) 2619 cr = bp->b_rcred; 2620 else 2621 cr = bp->b_wcred; 2622 /* 2623 * If the op is asynchronous and an i/o daemon is waiting 2624 * queue the request, wake it up and wait for completion 2625 * otherwise just do it ourselves. 2626 */ 2627 if ((bp->b_flags & B_ASYNC) == 0 || 2628 nfs_asyncio(bp, NOCRED)) 2629 error = nfs_doio(bp, cr, p); 2630 return (error); 2631} 2632 2633/* 2634 * Mmap a file 2635 * 2636 * NB Currently unsupported. 2637 */ 2638/* ARGSUSED */ 2639static int 2640nfs_mmap(ap) 2641 struct vop_mmap_args /* { 2642 struct vnode *a_vp; 2643 int a_fflags; 2644 struct ucred *a_cred; 2645 struct proc *a_p; 2646 } */ *ap; 2647{ 2648 2649 return (EINVAL); 2650} 2651 2652/* 2653 * fsync vnode op. Just call nfs_flush() with commit == 1. 2654 */ 2655/* ARGSUSED */ 2656static int 2657nfs_fsync(ap) 2658 struct vop_fsync_args /* { 2659 struct vnodeop_desc *a_desc; 2660 struct vnode * a_vp; 2661 struct ucred * a_cred; 2662 int a_waitfor; 2663 struct proc * a_p; 2664 } */ *ap; 2665{ 2666 2667 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2668} 2669 2670/* 2671 * Flush all the blocks associated with a vnode. 2672 * Walk through the buffer pool and push any dirty pages 2673 * associated with the vnode. 2674 */ 2675static int 2676nfs_flush(vp, cred, waitfor, p, commit) 2677 register struct vnode *vp; 2678 struct ucred *cred; 2679 int waitfor; 2680 struct proc *p; 2681 int commit; 2682{ 2683 register struct nfsnode *np = VTONFS(vp); 2684 register struct buf *bp; 2685 register int i; 2686 struct buf *nbp; 2687 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2688 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2689 int passone = 1; 2690 u_quad_t off, endoff, toff; 2691 struct ucred* wcred = NULL; 2692 struct buf **bvec = NULL; 2693#ifndef NFS_COMMITBVECSIZ 2694#define NFS_COMMITBVECSIZ 20 2695#endif 2696 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; 2697 int bvecsize = 0, bveccount; 2698 2699 if (nmp->nm_flag & NFSMNT_INT) 2700 slpflag = PCATCH; 2701 if (!commit) 2702 passone = 0; 2703 /* 2704 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2705 * server, but nas not been committed to stable storage on the server 2706 * yet. On the first pass, the byte range is worked out and the commit 2707 * rpc is done. On the second pass, nfs_writebp() is called to do the 2708 * job. 2709 */ 2710again: 2711 off = (u_quad_t)-1; 2712 endoff = 0; 2713 bvecpos = 0; 2714 if (NFS_ISV3(vp) && commit) { 2715 s = splbio(); 2716 /* 2717 * Count up how many buffers waiting for a commit. 2718 */ 2719 bveccount = 0; 2720 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2721 nbp = bp->b_vnbufs.le_next; 2722 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2723 == (B_DELWRI | B_NEEDCOMMIT)) 2724 bveccount++; 2725 } 2726 /* 2727 * Allocate space to remember the list of bufs to commit. It is 2728 * important to use M_NOWAIT here to avoid a race with nfs_write. 2729 * If we can't get memory (for whatever reason), we will end up 2730 * committing the buffers one-by-one in the loop below. 2731 */ 2732 if (bveccount > NFS_COMMITBVECSIZ) { 2733 if (bvec != NULL && bvec != bvec_on_stack) 2734 free(bvec, M_TEMP); 2735 bvec = (struct buf **) 2736 malloc(bveccount * sizeof(struct buf *), 2737 M_TEMP, M_NOWAIT); 2738 if (bvec == NULL) { 2739 bvec = bvec_on_stack; 2740 bvecsize = NFS_COMMITBVECSIZ; 2741 } else 2742 bvecsize = bveccount; 2743 } else { 2744 bvec = bvec_on_stack; 2745 bvecsize = NFS_COMMITBVECSIZ; 2746 } 2747 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2748 nbp = bp->b_vnbufs.le_next; 2749 if (bvecpos >= bvecsize) 2750 break; 2751 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2752 != (B_DELWRI | B_NEEDCOMMIT)) 2753 continue; 2754 bremfree(bp); 2755 /* 2756 * Work out if all buffers are using the same cred 2757 * so we can deal with them all with one commit. 2758 */ 2759 if (wcred == NULL) 2760 wcred = bp->b_wcred; 2761 else if (wcred != bp->b_wcred) 2762 wcred = NOCRED; 2763 bp->b_flags |= (B_BUSY | B_WRITEINPROG); 2764 vfs_busy_pages(bp, 1); 2765 /* 2766 * A list of these buffers is kept so that the 2767 * second loop knows which buffers have actually 2768 * been committed. This is necessary, since there 2769 * may be a race between the commit rpc and new 2770 * uncommitted writes on the file. 2771 */ 2772 bvec[bvecpos++] = bp; 2773 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2774 bp->b_dirtyoff; 2775 if (toff < off) 2776 off = toff; 2777 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2778 if (toff > endoff) 2779 endoff = toff; 2780 } 2781 splx(s); 2782 } 2783 if (bvecpos > 0) { 2784 /* 2785 * Commit data on the server, as required. 2786 * If all bufs are using the same wcred, then use that with 2787 * one call for all of them, otherwise commit each one 2788 * separately. 2789 */ 2790 if (wcred != NOCRED) 2791 retv = nfs_commit(vp, off, (int)(endoff - off), 2792 wcred, p); 2793 else { 2794 retv = 0; 2795 for (i = 0; i < bvecpos; i++) { 2796 off_t off, size; 2797 bp = bvec[i]; 2798 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2799 bp->b_dirtyoff; 2800 size = (u_quad_t)(bp->b_dirtyend 2801 - bp->b_dirtyoff); 2802 retv = nfs_commit(vp, off, (int)size, 2803 bp->b_wcred, p); 2804 if (retv) break; 2805 } 2806 } 2807 2808 if (retv == NFSERR_STALEWRITEVERF) 2809 nfs_clearcommit(vp->v_mount); 2810 /* 2811 * Now, either mark the blocks I/O done or mark the 2812 * blocks dirty, depending on whether the commit 2813 * succeeded. 2814 */ 2815 for (i = 0; i < bvecpos; i++) { 2816 bp = bvec[i]; 2817 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2818 if (retv) { 2819 vfs_unbusy_pages(bp); 2820 brelse(bp); 2821 } else { 2822 vp->v_numoutput++; 2823 bp->b_flags |= B_ASYNC; 2824 if (bp->b_flags & B_DELWRI) { 2825 --numdirtybuffers; 2826 if (needsbuffer) { 2827 vfs_bio_need_satisfy(); 2828 } 2829 } 2830 s = splbio(); /* XXX check this positionning */ 2831 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2832 bp->b_dirtyoff = bp->b_dirtyend = 0; 2833 reassignbuf(bp, vp); 2834 splx(s); 2835 biodone(bp); 2836 } 2837 } 2838 } 2839 2840 /* 2841 * Start/do any write(s) that are required. 2842 */ 2843loop: 2844 s = splbio(); 2845 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2846 nbp = bp->b_vnbufs.le_next; 2847 if (bp->b_flags & B_BUSY) { 2848 if (waitfor != MNT_WAIT || passone) 2849 continue; 2850 bp->b_flags |= B_WANTED; 2851 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2852 "nfsfsync", slptimeo); 2853 splx(s); 2854 if (error) { 2855 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2856 error = EINTR; 2857 goto done; 2858 } 2859 if (slpflag == PCATCH) { 2860 slpflag = 0; 2861 slptimeo = 2 * hz; 2862 } 2863 } 2864 goto loop; 2865 } 2866 if ((bp->b_flags & B_DELWRI) == 0) 2867 panic("nfs_fsync: not dirty"); 2868 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2869 continue; 2870 bremfree(bp); 2871 if (passone || !commit) 2872 bp->b_flags |= (B_BUSY|B_ASYNC); 2873 else 2874 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2875 splx(s); 2876 VOP_BWRITE(bp); 2877 goto loop; 2878 } 2879 splx(s); 2880 if (passone) { 2881 passone = 0; 2882 goto again; 2883 } 2884 if (waitfor == MNT_WAIT) { 2885 while (vp->v_numoutput) { 2886 vp->v_flag |= VBWAIT; 2887 error = tsleep((caddr_t)&vp->v_numoutput, 2888 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2889 if (error) { 2890 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2891 error = EINTR; 2892 goto done; 2893 } 2894 if (slpflag == PCATCH) { 2895 slpflag = 0; 2896 slptimeo = 2 * hz; 2897 } 2898 } 2899 } 2900 if (vp->v_dirtyblkhd.lh_first && commit) { 2901 goto loop; 2902 } 2903 } 2904 if (np->n_flag & NWRITEERR) { 2905 error = np->n_error; 2906 np->n_flag &= ~NWRITEERR; 2907 } 2908done: 2909 if (bvec != NULL && bvec != bvec_on_stack) 2910 free(bvec, M_TEMP); 2911 return (error); 2912} 2913 2914/* 2915 * NFS advisory byte-level locks. 2916 * Currently unsupported. 2917 */ 2918static int 2919nfs_advlock(ap) 2920 struct vop_advlock_args /* { 2921 struct vnode *a_vp; 2922 caddr_t a_id; 2923 int a_op; 2924 struct flock *a_fl; 2925 int a_flags; 2926 } */ *ap; 2927{ 2928 register struct nfsnode *np = VTONFS(ap->a_vp); 2929 2930 /* 2931 * The following kludge is to allow diskless support to work 2932 * until a real NFS lockd is implemented. Basically, just pretend 2933 * that this is a local lock. 2934 */ 2935 return (lf_advlock(ap, &(np->n_lockf), np->n_size)); 2936} 2937 2938/* 2939 * Print out the contents of an nfsnode. 2940 */ 2941static int 2942nfs_print(ap) 2943 struct vop_print_args /* { 2944 struct vnode *a_vp; 2945 } */ *ap; 2946{ 2947 register struct vnode *vp = ap->a_vp; 2948 register struct nfsnode *np = VTONFS(vp); 2949 2950 printf("tag VT_NFS, fileid %ld fsid 0x%lx", 2951 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2952 if (vp->v_type == VFIFO) 2953 fifo_printinfo(vp); 2954 printf("\n"); 2955 return (0); 2956} 2957 2958/* 2959 * Just call nfs_writebp() with the force argument set to 1. 2960 */ 2961static int 2962nfs_bwrite(ap) 2963 struct vop_bwrite_args /* { 2964 struct vnode *a_bp; 2965 } */ *ap; 2966{ 2967 2968 return (nfs_writebp(ap->a_bp, 1)); 2969} 2970 2971/* 2972 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless 2973 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 2974 */ 2975int 2976nfs_writebp(bp, force) 2977 register struct buf *bp; 2978 int force; 2979{ 2980 int s; 2981 register int oldflags = bp->b_flags, retv = 1; 2982 off_t off; 2983 2984 if(!(bp->b_flags & B_BUSY)) 2985 panic("bwrite: buffer is not busy???"); 2986 2987 if (bp->b_flags & B_INVAL) 2988 bp->b_flags |= B_INVAL | B_NOCACHE; 2989 2990 if (bp->b_flags & B_DELWRI) { 2991 --numdirtybuffers; 2992 if (needsbuffer) 2993 vfs_bio_need_satisfy(); 2994 } 2995 s = splbio(); /* XXX check if needed */ 2996 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2997 2998 if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) { 2999 reassignbuf(bp, bp->b_vp); 3000 } 3001 3002 bp->b_vp->v_numoutput++; 3003 curproc->p_stats->p_ru.ru_oublock++; 3004 splx(s); 3005 3006 /* 3007 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 3008 * an actual write will have to be scheduled via. VOP_STRATEGY(). 3009 * If B_WRITEINPROG is already set, then push it with a write anyhow. 3010 */ 3011 vfs_busy_pages(bp, 1); 3012 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) { 3013 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 3014 bp->b_flags |= B_WRITEINPROG; 3015 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, 3016 bp->b_wcred, bp->b_proc); 3017 bp->b_flags &= ~B_WRITEINPROG; 3018 if (!retv) { 3019 bp->b_dirtyoff = bp->b_dirtyend = 0; 3020 bp->b_flags &= ~B_NEEDCOMMIT; 3021 biodone(bp); 3022 } else if (retv == NFSERR_STALEWRITEVERF) 3023 nfs_clearcommit(bp->b_vp->v_mount); 3024 } 3025 if (retv) { 3026 if (force) 3027 bp->b_flags |= B_WRITEINPROG; 3028 VOP_STRATEGY(bp); 3029 } 3030 3031 if( (oldflags & B_ASYNC) == 0) { 3032 int rtval = biowait(bp); 3033 3034 if (oldflags & B_DELWRI) { 3035 s = splbio(); 3036 reassignbuf(bp, bp->b_vp); 3037 splx(s); 3038 } 3039 3040 brelse(bp); 3041 return (rtval); 3042 } 3043 3044 return (0); 3045} 3046 3047/* 3048 * nfs special file access vnode op. 3049 * Essentially just get vattr and then imitate iaccess() since the device is 3050 * local to the client. 3051 */ 3052static int 3053nfsspec_access(ap) 3054 struct vop_access_args /* { 3055 struct vnode *a_vp; 3056 int a_mode; 3057 struct ucred *a_cred; 3058 struct proc *a_p; 3059 } */ *ap; 3060{ 3061 register struct vattr *vap; 3062 register gid_t *gp; 3063 register struct ucred *cred = ap->a_cred; 3064 struct vnode *vp = ap->a_vp; 3065 mode_t mode = ap->a_mode; 3066 struct vattr vattr; 3067 register int i; 3068 int error; 3069 3070 /* 3071 * Disallow write attempts on filesystems mounted read-only; 3072 * unless the file is a socket, fifo, or a block or character 3073 * device resident on the filesystem. 3074 */ 3075 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3076 switch (vp->v_type) { 3077 case VREG: case VDIR: case VLNK: 3078 return (EROFS); 3079 } 3080 } 3081 /* 3082 * If you're the super-user, 3083 * you always get access. 3084 */ 3085 if (cred->cr_uid == 0) 3086 return (0); 3087 vap = &vattr; 3088 error = VOP_GETATTR(vp, vap, cred, ap->a_p); 3089 if (error) 3090 return (error); 3091 /* 3092 * Access check is based on only one of owner, group, public. 3093 * If not owner, then check group. If not a member of the 3094 * group, then check public access. 3095 */ 3096 if (cred->cr_uid != vap->va_uid) { 3097 mode >>= 3; 3098 gp = cred->cr_groups; 3099 for (i = 0; i < cred->cr_ngroups; i++, gp++) 3100 if (vap->va_gid == *gp) 3101 goto found; 3102 mode >>= 3; 3103found: 3104 ; 3105 } 3106 error = (vap->va_mode & mode) == mode ? 0 : EACCES; 3107 return (error); 3108} 3109 3110/* 3111 * Read wrapper for special devices. 3112 */ 3113static int 3114nfsspec_read(ap) 3115 struct vop_read_args /* { 3116 struct vnode *a_vp; 3117 struct uio *a_uio; 3118 int a_ioflag; 3119 struct ucred *a_cred; 3120 } */ *ap; 3121{ 3122 register struct nfsnode *np = VTONFS(ap->a_vp); 3123 struct timeval tv; 3124 3125 /* 3126 * Set access flag. 3127 */ 3128 np->n_flag |= NACC; 3129 getmicrotime(&tv); 3130 np->n_atim.tv_sec = tv.tv_sec; 3131 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3132 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3133} 3134 3135/* 3136 * Write wrapper for special devices. 3137 */ 3138static int 3139nfsspec_write(ap) 3140 struct vop_write_args /* { 3141 struct vnode *a_vp; 3142 struct uio *a_uio; 3143 int a_ioflag; 3144 struct ucred *a_cred; 3145 } */ *ap; 3146{ 3147 register struct nfsnode *np = VTONFS(ap->a_vp); 3148 struct timeval tv; 3149 3150 /* 3151 * Set update flag. 3152 */ 3153 np->n_flag |= NUPD; 3154 getmicrotime(&tv); 3155 np->n_mtim.tv_sec = tv.tv_sec; 3156 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3157 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3158} 3159 3160/* 3161 * Close wrapper for special devices. 3162 * 3163 * Update the times on the nfsnode then do device close. 3164 */ 3165static int 3166nfsspec_close(ap) 3167 struct vop_close_args /* { 3168 struct vnode *a_vp; 3169 int a_fflag; 3170 struct ucred *a_cred; 3171 struct proc *a_p; 3172 } */ *ap; 3173{ 3174 register struct vnode *vp = ap->a_vp; 3175 register struct nfsnode *np = VTONFS(vp); 3176 struct vattr vattr; 3177 3178 if (np->n_flag & (NACC | NUPD)) { 3179 np->n_flag |= NCHG; 3180 if (vp->v_usecount == 1 && 3181 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3182 VATTR_NULL(&vattr); 3183 if (np->n_flag & NACC) 3184 vattr.va_atime = np->n_atim; 3185 if (np->n_flag & NUPD) 3186 vattr.va_mtime = np->n_mtim; 3187 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3188 } 3189 } 3190 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3191} 3192 3193/* 3194 * Read wrapper for fifos. 3195 */ 3196static int 3197nfsfifo_read(ap) 3198 struct vop_read_args /* { 3199 struct vnode *a_vp; 3200 struct uio *a_uio; 3201 int a_ioflag; 3202 struct ucred *a_cred; 3203 } */ *ap; 3204{ 3205 register struct nfsnode *np = VTONFS(ap->a_vp); 3206 struct timeval tv; 3207 3208 /* 3209 * Set access flag. 3210 */ 3211 np->n_flag |= NACC; 3212 getmicrotime(&tv); 3213 np->n_atim.tv_sec = tv.tv_sec; 3214 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3215 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3216} 3217 3218/* 3219 * Write wrapper for fifos. 3220 */ 3221static int 3222nfsfifo_write(ap) 3223 struct vop_write_args /* { 3224 struct vnode *a_vp; 3225 struct uio *a_uio; 3226 int a_ioflag; 3227 struct ucred *a_cred; 3228 } */ *ap; 3229{ 3230 register struct nfsnode *np = VTONFS(ap->a_vp); 3231 struct timeval tv; 3232 3233 /* 3234 * Set update flag. 3235 */ 3236 np->n_flag |= NUPD; 3237 getmicrotime(&tv); 3238 np->n_mtim.tv_sec = tv.tv_sec; 3239 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3240 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3241} 3242 3243/* 3244 * Close wrapper for fifos. 3245 * 3246 * Update the times on the nfsnode then do fifo close. 3247 */ 3248static int 3249nfsfifo_close(ap) 3250 struct vop_close_args /* { 3251 struct vnode *a_vp; 3252 int a_fflag; 3253 struct ucred *a_cred; 3254 struct proc *a_p; 3255 } */ *ap; 3256{ 3257 register struct vnode *vp = ap->a_vp; 3258 register struct nfsnode *np = VTONFS(vp); 3259 struct timeval tv; 3260 struct vattr vattr; 3261 3262 if (np->n_flag & (NACC | NUPD)) { 3263 getmicrotime(&tv); 3264 if (np->n_flag & NACC) { 3265 np->n_atim.tv_sec = tv.tv_sec; 3266 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3267 } 3268 if (np->n_flag & NUPD) { 3269 np->n_mtim.tv_sec = tv.tv_sec; 3270 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3271 } 3272 np->n_flag |= NCHG; 3273 if (vp->v_usecount == 1 && 3274 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3275 VATTR_NULL(&vattr); 3276 if (np->n_flag & NACC) 3277 vattr.va_atime = np->n_atim; 3278 if (np->n_flag & NUPD) 3279 vattr.va_mtime = np->n_mtim; 3280 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3281 } 3282 } 3283 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3284} 3285