The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/nfsclient/nfs_vnops.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1989, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * Rick Macklem at The University of Guelph.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __FBSDID("$FreeBSD: releng/5.1/sys/nfsclient/nfs_vnops.c 115041 2003-05-15 21:12:08Z rwatson $");
   41 
   42 /*
   43  * vnode op calls for Sun NFS version 2 and 3
   44  */
   45 
   46 #include "opt_inet.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/kernel.h>
   50 #include <sys/systm.h>
   51 #include <sys/resourcevar.h>
   52 #include <sys/proc.h>
   53 #include <sys/mount.h>
   54 #include <sys/bio.h>
   55 #include <sys/buf.h>
   56 #include <sys/malloc.h>
   57 #include <sys/mbuf.h>
   58 #include <sys/namei.h>
   59 #include <sys/socket.h>
   60 #include <sys/vnode.h>
   61 #include <sys/dirent.h>
   62 #include <sys/fcntl.h>
   63 #include <sys/lockf.h>
   64 #include <sys/stat.h>
   65 #include <sys/sysctl.h>
   66 
   67 #include <vm/vm.h>
   68 #include <vm/vm_extern.h>
   69 
   70 #include <fs/fifofs/fifo.h>
   71 
   72 #include <nfs/rpcv2.h>
   73 #include <nfs/nfsproto.h>
   74 #include <nfsclient/nfs.h>
   75 #include <nfsclient/nfsnode.h>
   76 #include <nfsclient/nfsmount.h>
   77 #include <nfsclient/nfs_lock.h>
   78 #include <nfs/xdr_subs.h>
   79 #include <nfsclient/nfsm_subs.h>
   80 
   81 #include <net/if.h>
   82 #include <netinet/in.h>
   83 #include <netinet/in_var.h>
   84 
   85 /* Defs */
   86 #define TRUE    1
   87 #define FALSE   0
   88 
   89 /*
   90  * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these
   91  * calls are not in getblk() and brelse() so that they would not be necessary
   92  * here.
   93  */
   94 #ifndef B_VMIO
   95 #define vfs_busy_pages(bp, f)
   96 #endif
   97 
   98 static int      nfsspec_read(struct vop_read_args *);
   99 static int      nfsspec_write(struct vop_write_args *);
  100 static int      nfsfifo_read(struct vop_read_args *);
  101 static int      nfsfifo_write(struct vop_write_args *);
  102 static int      nfsspec_close(struct vop_close_args *);
  103 static int      nfsfifo_close(struct vop_close_args *);
  104 static int      nfs_flush(struct vnode *, struct ucred *, int, struct thread *,
  105                     int);
  106 static int      nfs_setattrrpc(struct vnode *, struct vattr *, struct ucred *,
  107                     struct thread *);
  108 static  int     nfs_lookup(struct vop_lookup_args *);
  109 static  int     nfs_create(struct vop_create_args *);
  110 static  int     nfs_mknod(struct vop_mknod_args *);
  111 static  int     nfs_open(struct vop_open_args *);
  112 static  int     nfs_close(struct vop_close_args *);
  113 static  int     nfs_access(struct vop_access_args *);
  114 static  int     nfs_getattr(struct vop_getattr_args *);
  115 static  int     nfs_setattr(struct vop_setattr_args *);
  116 static  int     nfs_read(struct vop_read_args *);
  117 static  int     nfs_fsync(struct vop_fsync_args *);
  118 static  int     nfs_remove(struct vop_remove_args *);
  119 static  int     nfs_link(struct vop_link_args *);
  120 static  int     nfs_rename(struct vop_rename_args *);
  121 static  int     nfs_mkdir(struct vop_mkdir_args *);
  122 static  int     nfs_rmdir(struct vop_rmdir_args *);
  123 static  int     nfs_symlink(struct vop_symlink_args *);
  124 static  int     nfs_readdir(struct vop_readdir_args *);
  125 static  int     nfs_strategy(struct vop_strategy_args *);
  126 static  int     nfs_lookitup(struct vnode *, const char *, int,
  127                     struct ucred *, struct thread *, struct nfsnode **);
  128 static  int     nfs_sillyrename(struct vnode *, struct vnode *,
  129                     struct componentname *);
  130 static int      nfsspec_access(struct vop_access_args *);
  131 static int      nfs_readlink(struct vop_readlink_args *);
  132 static int      nfs_print(struct vop_print_args *);
  133 static int      nfs_advlock(struct vop_advlock_args *);
  134 
  135 /*
  136  * Global vfs data structures for nfs
  137  */
  138 vop_t **nfsv2_vnodeop_p;
  139 static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
  140         { &vop_default_desc,            (vop_t *) vop_defaultop },
  141         { &vop_access_desc,             (vop_t *) nfs_access },
  142         { &vop_advlock_desc,            (vop_t *) nfs_advlock },
  143         { &vop_close_desc,              (vop_t *) nfs_close },
  144         { &vop_create_desc,             (vop_t *) nfs_create },
  145         { &vop_fsync_desc,              (vop_t *) nfs_fsync },
  146         { &vop_getattr_desc,            (vop_t *) nfs_getattr },
  147         { &vop_getpages_desc,           (vop_t *) nfs_getpages },
  148         { &vop_putpages_desc,           (vop_t *) nfs_putpages },
  149         { &vop_inactive_desc,           (vop_t *) nfs_inactive },
  150         { &vop_lease_desc,              (vop_t *) vop_null },
  151         { &vop_link_desc,               (vop_t *) nfs_link },
  152         { &vop_lock_desc,               (vop_t *) vop_sharedlock },
  153         { &vop_lookup_desc,             (vop_t *) nfs_lookup },
  154         { &vop_mkdir_desc,              (vop_t *) nfs_mkdir },
  155         { &vop_mknod_desc,              (vop_t *) nfs_mknod },
  156         { &vop_open_desc,               (vop_t *) nfs_open },
  157         { &vop_print_desc,              (vop_t *) nfs_print },
  158         { &vop_read_desc,               (vop_t *) nfs_read },
  159         { &vop_readdir_desc,            (vop_t *) nfs_readdir },
  160         { &vop_readlink_desc,           (vop_t *) nfs_readlink },
  161         { &vop_reclaim_desc,            (vop_t *) nfs_reclaim },
  162         { &vop_remove_desc,             (vop_t *) nfs_remove },
  163         { &vop_rename_desc,             (vop_t *) nfs_rename },
  164         { &vop_rmdir_desc,              (vop_t *) nfs_rmdir },
  165         { &vop_setattr_desc,            (vop_t *) nfs_setattr },
  166         { &vop_strategy_desc,           (vop_t *) nfs_strategy },
  167         { &vop_symlink_desc,            (vop_t *) nfs_symlink },
  168         { &vop_write_desc,              (vop_t *) nfs_write },
  169         { NULL, NULL }
  170 };
  171 static struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
  172         { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
  173 VNODEOP_SET(nfsv2_vnodeop_opv_desc);
  174 
  175 /*
  176  * Special device vnode ops
  177  */
  178 vop_t **spec_nfsv2nodeop_p;
  179 static struct vnodeopv_entry_desc nfsv2_specop_entries[] = {
  180         { &vop_default_desc,            (vop_t *) spec_vnoperate },
  181         { &vop_access_desc,             (vop_t *) nfsspec_access },
  182         { &vop_close_desc,              (vop_t *) nfsspec_close },
  183         { &vop_fsync_desc,              (vop_t *) nfs_fsync },
  184         { &vop_getattr_desc,            (vop_t *) nfs_getattr },
  185         { &vop_inactive_desc,           (vop_t *) nfs_inactive },
  186         { &vop_lock_desc,               (vop_t *) vop_sharedlock },
  187         { &vop_print_desc,              (vop_t *) nfs_print },
  188         { &vop_read_desc,               (vop_t *) nfsspec_read },
  189         { &vop_reclaim_desc,            (vop_t *) nfs_reclaim },
  190         { &vop_setattr_desc,            (vop_t *) nfs_setattr },
  191         { &vop_write_desc,              (vop_t *) nfsspec_write },
  192         { NULL, NULL }
  193 };
  194 static struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
  195         { &spec_nfsv2nodeop_p, nfsv2_specop_entries };
  196 VNODEOP_SET(spec_nfsv2nodeop_opv_desc);
  197 
  198 vop_t **fifo_nfsv2nodeop_p;
  199 static struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = {
  200         { &vop_default_desc,            (vop_t *) fifo_vnoperate },
  201         { &vop_access_desc,             (vop_t *) nfsspec_access },
  202         { &vop_close_desc,              (vop_t *) nfsfifo_close },
  203         { &vop_fsync_desc,              (vop_t *) nfs_fsync },
  204         { &vop_getattr_desc,            (vop_t *) nfs_getattr },
  205         { &vop_inactive_desc,           (vop_t *) nfs_inactive },
  206         { &vop_lock_desc,               (vop_t *) vop_sharedlock },
  207         { &vop_print_desc,              (vop_t *) nfs_print },
  208         { &vop_read_desc,               (vop_t *) nfsfifo_read },
  209         { &vop_reclaim_desc,            (vop_t *) nfs_reclaim },
  210         { &vop_setattr_desc,            (vop_t *) nfs_setattr },
  211         { &vop_write_desc,              (vop_t *) nfsfifo_write },
  212         { NULL, NULL }
  213 };
  214 static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
  215         { &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries };
  216 VNODEOP_SET(fifo_nfsv2nodeop_opv_desc);
  217 
  218 static int      nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp,
  219                              struct componentname *cnp, struct vattr *vap);
  220 static int      nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
  221                               struct ucred *cred, struct thread *td);
  222 static int      nfs_renamerpc(struct vnode *fdvp, const char *fnameptr,
  223                               int fnamelen, struct vnode *tdvp,
  224                               const char *tnameptr, int tnamelen,
  225                               struct ucred *cred, struct thread *td);
  226 static int      nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
  227                              struct sillyrename *sp);
  228 
  229 /*
  230  * Global variables
  231  */
  232 struct proc     *nfs_iodwant[NFS_MAXASYNCDAEMON];
  233 struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
  234 int              nfs_numasync = 0;
  235 #define DIRHDSIZ        (sizeof (struct dirent) - (MAXNAMLEN + 1))
  236 
  237 SYSCTL_DECL(_vfs_nfs);
  238 
  239 static int      nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
  240 SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
  241            &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
  242 
  243 static int      nfsv3_commit_on_close = 0;
  244 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW,
  245            &nfsv3_commit_on_close, 0, "write+commit on close, else only write");
  246 #if 0
  247 SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_hits, CTLFLAG_RD,
  248            &nfsstats.accesscache_hits, 0, "NFS ACCESS cache hit count");
  249 
  250 SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_misses, CTLFLAG_RD,
  251            &nfsstats.accesscache_misses, 0, "NFS ACCESS cache miss count");
  252 #endif
  253 
  254 #define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY          \
  255                          | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE     \
  256                          | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
  257 static int
  258 nfs3_access_otw(struct vnode *vp, int wmode, struct thread *td,
  259     struct ucred *cred)
  260 {
  261         const int v3 = 1;
  262         u_int32_t *tl;
  263         int error = 0, attrflag;
  264 
  265         struct mbuf *mreq, *mrep, *md, *mb;
  266         caddr_t bpos, dpos;
  267         u_int32_t rmode;
  268         struct nfsnode *np = VTONFS(vp);
  269 
  270         nfsstats.rpccnt[NFSPROC_ACCESS]++;
  271         mreq = nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
  272         mb = mreq;
  273         bpos = mtod(mb, caddr_t);
  274         nfsm_fhtom(vp, v3);
  275         tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
  276         *tl = txdr_unsigned(wmode);
  277         nfsm_request(vp, NFSPROC_ACCESS, td, cred);
  278         nfsm_postop_attr(vp, attrflag);
  279         if (!error) {
  280                 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
  281                 rmode = fxdr_unsigned(u_int32_t, *tl);
  282                 np->n_mode = rmode;
  283                 np->n_modeuid = cred->cr_uid;
  284                 np->n_modestamp = time_second;
  285         }
  286         m_freem(mrep);
  287 nfsmout:
  288         return error;
  289 }
  290 
  291 /*
  292  * nfs access vnode op.
  293  * For nfs version 2, just return ok. File accesses may fail later.
  294  * For nfs version 3, use the access rpc to check accessibility. If file modes
  295  * are changed on the server, accesses might still fail later.
  296  */
  297 static int
  298 nfs_access(struct vop_access_args *ap)
  299 {
  300         struct vnode *vp = ap->a_vp;
  301         int error = 0;
  302         u_int32_t mode, wmode;
  303         int v3 = NFS_ISV3(vp);
  304         struct nfsnode *np = VTONFS(vp);
  305 
  306         /*
  307          * Disallow write attempts on filesystems mounted read-only;
  308          * unless the file is a socket, fifo, or a block or character
  309          * device resident on the filesystem.
  310          */
  311         if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
  312                 switch (vp->v_type) {
  313                 case VREG:
  314                 case VDIR:
  315                 case VLNK:
  316                         return (EROFS);
  317                 default:
  318                         break;
  319                 }
  320         }
  321         /*
  322          * For nfs v3, check to see if we have done this recently, and if
  323          * so return our cached result instead of making an ACCESS call.
  324          * If not, do an access rpc, otherwise you are stuck emulating
  325          * ufs_access() locally using the vattr. This may not be correct,
  326          * since the server may apply other access criteria such as
  327          * client uid-->server uid mapping that we do not know about.
  328          */
  329         if (v3) {
  330                 if (ap->a_mode & VREAD)
  331                         mode = NFSV3ACCESS_READ;
  332                 else
  333                         mode = 0;
  334                 if (vp->v_type != VDIR) {
  335                         if (ap->a_mode & VWRITE)
  336                                 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
  337                         if (ap->a_mode & VEXEC)
  338                                 mode |= NFSV3ACCESS_EXECUTE;
  339                 } else {
  340                         if (ap->a_mode & VWRITE)
  341                                 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
  342                                          NFSV3ACCESS_DELETE);
  343                         if (ap->a_mode & VEXEC)
  344                                 mode |= NFSV3ACCESS_LOOKUP;
  345                 }
  346                 /* XXX safety belt, only make blanket request if caching */
  347                 if (nfsaccess_cache_timeout > 0) {
  348                         wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY |
  349                                 NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE |
  350                                 NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP;
  351                 } else {
  352                         wmode = mode;
  353                 }
  354 
  355                 /*
  356                  * Does our cached result allow us to give a definite yes to
  357                  * this request?
  358                  */
  359                 if ((time_second < (np->n_modestamp + nfsaccess_cache_timeout)) &&
  360                     (ap->a_cred->cr_uid == np->n_modeuid) &&
  361                     ((np->n_mode & mode) == mode)) {
  362                         nfsstats.accesscache_hits++;
  363                 } else {
  364                         /*
  365                          * Either a no, or a don't know.  Go to the wire.
  366                          */
  367                         nfsstats.accesscache_misses++;
  368                         error = nfs3_access_otw(vp, wmode, ap->a_td,ap->a_cred);
  369                         if (!error) {
  370                                 if ((np->n_mode & mode) != mode) {
  371                                         error = EACCES;
  372                                 }
  373                         }
  374                 }
  375                 return (error);
  376         } else {
  377                 if ((error = nfsspec_access(ap)) != 0)
  378                         return (error);
  379 
  380                 /*
  381                  * Attempt to prevent a mapped root from accessing a file
  382                  * which it shouldn't.  We try to read a byte from the file
  383                  * if the user is root and the file is not zero length.
  384                  * After calling nfsspec_access, we should have the correct
  385                  * file size cached.
  386                  */
  387                 if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD)
  388                     && VTONFS(vp)->n_size > 0) {
  389                         struct iovec aiov;
  390                         struct uio auio;
  391                         char buf[1];
  392 
  393                         aiov.iov_base = buf;
  394                         aiov.iov_len = 1;
  395                         auio.uio_iov = &aiov;
  396                         auio.uio_iovcnt = 1;
  397                         auio.uio_offset = 0;
  398                         auio.uio_resid = 1;
  399                         auio.uio_segflg = UIO_SYSSPACE;
  400                         auio.uio_rw = UIO_READ;
  401                         auio.uio_td = ap->a_td;
  402 
  403                         if (vp->v_type == VREG)
  404                                 error = nfs_readrpc(vp, &auio, ap->a_cred);
  405                         else if (vp->v_type == VDIR) {
  406                                 char* bp;
  407                                 bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK);
  408                                 aiov.iov_base = bp;
  409                                 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ;
  410                                 error = nfs_readdirrpc(vp, &auio, ap->a_cred);
  411                                 free(bp, M_TEMP);
  412                         } else if (vp->v_type == VLNK)
  413                                 error = nfs_readlinkrpc(vp, &auio, ap->a_cred);
  414                         else
  415                                 error = EACCES;
  416                 }
  417                 return (error);
  418         }
  419 }
  420 
  421 /*
  422  * nfs open vnode op
  423  * Check to see if the type is ok
  424  * and that deletion is not in progress.
  425  * For paged in text files, you will need to flush the page cache
  426  * if consistency is lost.
  427  */
  428 /* ARGSUSED */
  429 static int
  430 nfs_open(struct vop_open_args *ap)
  431 {
  432         struct vnode *vp = ap->a_vp;
  433         struct nfsnode *np = VTONFS(vp);
  434         struct vattr vattr;
  435         int error;
  436 
  437         if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
  438 #ifdef DIAGNOSTIC
  439                 printf("open eacces vtyp=%d\n", vp->v_type);
  440 #endif
  441                 return (EACCES);
  442         }
  443         /*
  444          * Get a valid lease. If cached data is stale, flush it.
  445          */
  446         if (np->n_flag & NMODIFIED) {
  447                 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
  448                         ap->a_td, 1)) == EINTR)
  449                         return (error);
  450                 np->n_attrstamp = 0;
  451                 if (vp->v_type == VDIR)
  452                         np->n_direofoffset = 0;
  453                 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
  454                 if (error)
  455                         return (error);
  456                 np->n_mtime = vattr.va_mtime.tv_sec;
  457         } else {
  458                 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_td);
  459                 if (error)
  460                         return (error);
  461                 if (np->n_mtime != vattr.va_mtime.tv_sec) {
  462                         if (vp->v_type == VDIR)
  463                                 np->n_direofoffset = 0;
  464                         if ((error = nfs_vinvalbuf(vp, V_SAVE,
  465                                 ap->a_cred, ap->a_td, 1)) == EINTR)
  466                                 return (error);
  467                         np->n_mtime = vattr.va_mtime.tv_sec;
  468                 }
  469         }
  470         np->n_attrstamp = 0; /* For Open/Close consistency */
  471         return (0);
  472 }
  473 
  474 /*
  475  * nfs close vnode op
  476  * What an NFS client should do upon close after writing is a debatable issue.
  477  * Most NFS clients push delayed writes to the server upon close, basically for
  478  * two reasons:
  479  * 1 - So that any write errors may be reported back to the client process
  480  *     doing the close system call. By far the two most likely errors are
  481  *     NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
  482  * 2 - To put a worst case upper bound on cache inconsistency between
  483  *     multiple clients for the file.
  484  * There is also a consistency problem for Version 2 of the protocol w.r.t.
  485  * not being able to tell if other clients are writing a file concurrently,
  486  * since there is no way of knowing if the changed modify time in the reply
  487  * is only due to the write for this client.
  488  * (NFS Version 3 provides weak cache consistency data in the reply that
  489  *  should be sufficient to detect and handle this case.)
  490  *
  491  * The current code does the following:
  492  * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
  493  * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
  494  *                     or commit them (this satisfies 1 and 2 except for the
  495  *                     case where the server crashes after this close but
  496  *                     before the commit RPC, which is felt to be "good
  497  *                     enough". Changing the last argument to nfs_flush() to
  498  *                     a 1 would force a commit operation, if it is felt a
  499  *                     commit is necessary now.
  500  */
  501 /* ARGSUSED */
  502 static int
  503 nfs_close(struct vop_close_args *ap)
  504 {
  505         struct vnode *vp = ap->a_vp;
  506         struct nfsnode *np = VTONFS(vp);
  507         int error = 0;
  508 
  509         if (vp->v_type == VREG) {
  510             if (np->n_flag & NMODIFIED) {
  511                 if (NFS_ISV3(vp)) {
  512                     /*
  513                      * Under NFSv3 we have dirty buffers to dispose of.  We
  514                      * must flush them to the NFS server.  We have the option
  515                      * of waiting all the way through the commit rpc or just
  516                      * waiting for the initial write.  The default is to only
  517                      * wait through the initial write so the data is in the
  518                      * server's cache, which is roughly similar to the state
  519                      * a standard disk subsystem leaves the file in on close().
  520                      *
  521                      * We cannot clear the NMODIFIED bit in np->n_flag due to
  522                      * potential races with other processes, and certainly
  523                      * cannot clear it if we don't commit.
  524                      */
  525                     int cm = nfsv3_commit_on_close ? 1 : 0;
  526                     error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_td, cm);
  527                     /* np->n_flag &= ~NMODIFIED; */
  528                 } else {
  529                     vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
  530                     error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_td, 1);
  531                     VOP_UNLOCK(vp, 0, ap->a_td);
  532                 }
  533                 np->n_attrstamp = 0;
  534             }
  535             if (np->n_flag & NWRITEERR) {
  536                 np->n_flag &= ~NWRITEERR;
  537                 error = np->n_error;
  538             }
  539         }
  540         return (error);
  541 }
  542 
  543 /*
  544  * nfs getattr call from vfs.
  545  */
  546 static int
  547 nfs_getattr(struct vop_getattr_args *ap)
  548 {
  549         struct vnode *vp = ap->a_vp;
  550         struct nfsnode *np = VTONFS(vp);
  551         caddr_t bpos, dpos;
  552         int error = 0;
  553         struct mbuf *mreq, *mrep, *md, *mb;
  554         int v3 = NFS_ISV3(vp);
  555 
  556         /*
  557          * Update local times for special files.
  558          */
  559         if (np->n_flag & (NACC | NUPD))
  560                 np->n_flag |= NCHG;
  561         /*
  562          * First look in the cache.
  563          */
  564         if (nfs_getattrcache(vp, ap->a_vap) == 0)
  565                 return (0);
  566 
  567         if (v3 && nfsaccess_cache_timeout > 0) {
  568                 nfsstats.accesscache_misses++;
  569                 nfs3_access_otw(vp, NFSV3ACCESS_ALL, ap->a_td, ap->a_cred);
  570                 if (nfs_getattrcache(vp, ap->a_vap) == 0)
  571                         return (0);
  572         }
  573 
  574         nfsstats.rpccnt[NFSPROC_GETATTR]++;
  575         mreq = nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
  576         mb = mreq;
  577         bpos = mtod(mb, caddr_t);
  578         nfsm_fhtom(vp, v3);
  579         nfsm_request(vp, NFSPROC_GETATTR, ap->a_td, ap->a_cred);
  580         if (!error) {
  581                 nfsm_loadattr(vp, ap->a_vap);
  582         }
  583         m_freem(mrep);
  584 nfsmout:
  585         return (error);
  586 }
  587 
  588 /*
  589  * nfs setattr call.
  590  */
  591 static int
  592 nfs_setattr(struct vop_setattr_args *ap)
  593 {
  594         struct vnode *vp = ap->a_vp;
  595         struct nfsnode *np = VTONFS(vp);
  596         struct vattr *vap = ap->a_vap;
  597         int error = 0;
  598         u_quad_t tsize;
  599 
  600 #ifndef nolint
  601         tsize = (u_quad_t)0;
  602 #endif
  603 
  604         /*
  605          * Setting of flags is not supported.
  606          */
  607         if (vap->va_flags != VNOVAL)
  608                 return (EOPNOTSUPP);
  609 
  610         /*
  611          * Disallow write attempts if the filesystem is mounted read-only.
  612          */
  613         if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
  614             vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
  615             vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
  616             (vp->v_mount->mnt_flag & MNT_RDONLY))
  617                 return (EROFS);
  618         if (vap->va_size != VNOVAL) {
  619                 switch (vp->v_type) {
  620                 case VDIR:
  621                         return (EISDIR);
  622                 case VCHR:
  623                 case VBLK:
  624                 case VSOCK:
  625                 case VFIFO:
  626                         if (vap->va_mtime.tv_sec == VNOVAL &&
  627                             vap->va_atime.tv_sec == VNOVAL &&
  628                             vap->va_mode == (mode_t)VNOVAL &&
  629                             vap->va_uid == (uid_t)VNOVAL &&
  630                             vap->va_gid == (gid_t)VNOVAL)
  631                                 return (0);
  632                         vap->va_size = VNOVAL;
  633                         break;
  634                 default:
  635                         /*
  636                          * Disallow write attempts if the filesystem is
  637                          * mounted read-only.
  638                          */
  639                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  640                                 return (EROFS);
  641 
  642                         /*
  643                          *  We run vnode_pager_setsize() early (why?),
  644                          * we must set np->n_size now to avoid vinvalbuf
  645                          * V_SAVE races that might setsize a lower
  646                          * value.
  647                          */
  648 
  649                         tsize = np->n_size;
  650                         error = nfs_meta_setsize(vp, ap->a_cred, 
  651                                                 ap->a_td, vap->va_size);
  652 
  653                         if (np->n_flag & NMODIFIED) {
  654                             if (vap->va_size == 0)
  655                                 error = nfs_vinvalbuf(vp, 0,
  656                                         ap->a_cred, ap->a_td, 1);
  657                             else
  658                                 error = nfs_vinvalbuf(vp, V_SAVE,
  659                                         ap->a_cred, ap->a_td, 1);
  660                             if (error) {
  661                                 vnode_pager_setsize(vp, np->n_size);
  662                                 return (error);
  663                             }
  664                         }
  665                         np->n_vattr.va_size = vap->va_size;
  666                 };
  667         } else if ((vap->va_mtime.tv_sec != VNOVAL ||
  668                 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) &&
  669                 vp->v_type == VREG &&
  670                 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
  671                  ap->a_td, 1)) == EINTR)
  672                 return (error);
  673         error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_td);
  674         if (error && vap->va_size != VNOVAL) {
  675                 np->n_size = np->n_vattr.va_size = tsize;
  676                 vnode_pager_setsize(vp, np->n_size);
  677         }
  678         return (error);
  679 }
  680 
  681 /*
  682  * Do an nfs setattr rpc.
  683  */
  684 static int
  685 nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred,
  686     struct thread *td)
  687 {
  688         struct nfsv2_sattr *sp;
  689         caddr_t bpos, dpos;
  690         u_int32_t *tl;
  691         int error = 0, wccflag = NFSV3_WCCRATTR;
  692         struct mbuf *mreq, *mrep, *md, *mb;
  693         int v3 = NFS_ISV3(vp);
  694 
  695         nfsstats.rpccnt[NFSPROC_SETATTR]++;
  696         mreq = nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
  697         mb = mreq;
  698         bpos = mtod(mb, caddr_t);
  699         nfsm_fhtom(vp, v3);
  700         if (v3) {
  701                 nfsm_v3attrbuild(vap, TRUE);
  702                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
  703                 *tl = nfs_false;
  704         } else {
  705                 sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
  706                 if (vap->va_mode == (mode_t)VNOVAL)
  707                         sp->sa_mode = nfs_xdrneg1;
  708                 else
  709                         sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
  710                 if (vap->va_uid == (uid_t)VNOVAL)
  711                         sp->sa_uid = nfs_xdrneg1;
  712                 else
  713                         sp->sa_uid = txdr_unsigned(vap->va_uid);
  714                 if (vap->va_gid == (gid_t)VNOVAL)
  715                         sp->sa_gid = nfs_xdrneg1;
  716                 else
  717                         sp->sa_gid = txdr_unsigned(vap->va_gid);
  718                 sp->sa_size = txdr_unsigned(vap->va_size);
  719                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
  720                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
  721         }
  722         nfsm_request(vp, NFSPROC_SETATTR, td, cred);
  723         if (v3) {
  724                 nfsm_wcc_data(vp, wccflag);
  725         } else
  726                 nfsm_loadattr(vp, NULL);
  727         m_freem(mrep);
  728 nfsmout:
  729         return (error);
  730 }
  731 
  732 /*
  733  * nfs lookup call, one step at a time...
  734  * First look in cache
  735  * If not found, unlock the directory nfsnode and do the rpc
  736  */
  737 static int
  738 nfs_lookup(struct vop_lookup_args *ap)
  739 {
  740         struct componentname *cnp = ap->a_cnp;
  741         struct vnode *dvp = ap->a_dvp;
  742         struct vnode **vpp = ap->a_vpp;
  743         int flags = cnp->cn_flags;
  744         struct vnode *newvp;
  745         struct nfsmount *nmp;
  746         caddr_t bpos, dpos;
  747         struct mbuf *mreq, *mrep, *md, *mb;
  748         long len;
  749         nfsfh_t *fhp;
  750         struct nfsnode *np;
  751         int lockparent, wantparent, error = 0, attrflag, fhsize;
  752         int v3 = NFS_ISV3(dvp);
  753         struct thread *td = cnp->cn_thread;
  754 
  755         *vpp = NULLVP;
  756         cnp->cn_flags &= ~PDIRUNLOCK;
  757         if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
  758             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
  759                 return (EROFS);
  760         if (dvp->v_type != VDIR)
  761                 return (ENOTDIR);
  762         lockparent = flags & LOCKPARENT;
  763         wantparent = flags & (LOCKPARENT|WANTPARENT);
  764         nmp = VFSTONFS(dvp->v_mount);
  765         np = VTONFS(dvp);
  766         if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) {
  767                 struct vattr vattr;
  768                 int vpid;
  769 
  770                 if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) {
  771                         *vpp = NULLVP;
  772                         return (error);
  773                 }
  774 
  775                 vhold(*vpp);
  776                 newvp = *vpp;
  777                 vpid = newvp->v_id;
  778                 /*
  779                  * See the comment starting `Step through' in ufs/ufs_lookup.c
  780                  * for an explanation of the locking protocol
  781                  */
  782                 if (dvp == newvp) {
  783                         VREF(newvp);
  784                         error = 0;
  785                 } else if (flags & ISDOTDOT) {
  786                         VOP_UNLOCK(dvp, 0, td);
  787                         cnp->cn_flags |= PDIRUNLOCK;
  788                         error = vget(newvp, LK_EXCLUSIVE, td);
  789                         if (!error && lockparent && (flags & ISLASTCN)) {
  790                                 error = vn_lock(dvp, LK_EXCLUSIVE, td);
  791                                 if (error == 0)
  792                                         cnp->cn_flags &= ~PDIRUNLOCK;
  793                         }
  794                 } else {
  795                         error = vget(newvp, LK_EXCLUSIVE, td);
  796                         if (!lockparent || error || !(flags & ISLASTCN)) {
  797                                 VOP_UNLOCK(dvp, 0, td);
  798                                 cnp->cn_flags |= PDIRUNLOCK;
  799                         }
  800                 }
  801                 if (!error) {
  802                         if (vpid == newvp->v_id) {
  803                            if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, td)
  804                             && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
  805                                 nfsstats.lookupcache_hits++;
  806                                 if (cnp->cn_nameiop != LOOKUP &&
  807                                     (flags & ISLASTCN))
  808                                         cnp->cn_flags |= SAVENAME;
  809                                 vdrop(newvp);
  810                                 return (0);
  811                            }
  812                            cache_purge(newvp);
  813                         }
  814                         vput(newvp);
  815                         if (lockparent && dvp != newvp && (flags & ISLASTCN))
  816                                 VOP_UNLOCK(dvp, 0, td);
  817                 }
  818                 vdrop(newvp);
  819                 error = vn_lock(dvp, LK_EXCLUSIVE, td);
  820                 *vpp = NULLVP;
  821                 if (error) {
  822                         cnp->cn_flags |= PDIRUNLOCK;
  823                         return (error);
  824                 }
  825                 cnp->cn_flags &= ~PDIRUNLOCK;
  826         }
  827         error = 0;
  828         newvp = NULLVP;
  829         nfsstats.lookupcache_misses++;
  830         nfsstats.rpccnt[NFSPROC_LOOKUP]++;
  831         len = cnp->cn_namelen;
  832         mreq = nfsm_reqhead(dvp, NFSPROC_LOOKUP,
  833                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
  834         mb = mreq;
  835         bpos = mtod(mb, caddr_t);
  836         nfsm_fhtom(dvp, v3);
  837         nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
  838         nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_thread, cnp->cn_cred);
  839         if (error) {
  840                 nfsm_postop_attr(dvp, attrflag);
  841                 m_freem(mrep);
  842                 goto nfsmout;
  843         }
  844         nfsm_getfh(fhp, fhsize, v3);
  845 
  846         /*
  847          * Handle RENAME case...
  848          */
  849         if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
  850                 if (NFS_CMPFH(np, fhp, fhsize)) {
  851                         m_freem(mrep);
  852                         return (EISDIR);
  853                 }
  854                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
  855                 if (error) {
  856                         m_freem(mrep);
  857                         return (error);
  858                 }
  859                 newvp = NFSTOV(np);
  860                 if (v3) {
  861                         nfsm_postop_attr(newvp, attrflag);
  862                         nfsm_postop_attr(dvp, attrflag);
  863                 } else
  864                         nfsm_loadattr(newvp, NULL);
  865                 *vpp = newvp;
  866                 m_freem(mrep);
  867                 cnp->cn_flags |= SAVENAME;
  868                 if (!lockparent) {
  869                         VOP_UNLOCK(dvp, 0, td);
  870                         cnp->cn_flags |= PDIRUNLOCK;
  871                 }
  872                 return (0);
  873         }
  874 
  875         if (flags & ISDOTDOT) {
  876                 VOP_UNLOCK(dvp, 0, td);
  877                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
  878                 if (error) {
  879                         vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
  880                         return (error);
  881                 }
  882                 newvp = NFSTOV(np);
  883                 if (lockparent && (flags & ISLASTCN)) {
  884                         error = vn_lock(dvp, LK_EXCLUSIVE, td);
  885                         if (error) {
  886                                 cnp->cn_flags |= PDIRUNLOCK;
  887                                 vput(newvp);
  888                                 return (error);
  889                         }
  890                 } else
  891                         cnp->cn_flags |= PDIRUNLOCK;
  892         } else if (NFS_CMPFH(np, fhp, fhsize)) {
  893                 VREF(dvp);
  894                 newvp = dvp;
  895         } else {
  896                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
  897                 if (error) {
  898                         m_freem(mrep);
  899                         return (error);
  900                 }
  901                 if (!lockparent || !(flags & ISLASTCN)) {
  902                         cnp->cn_flags |= PDIRUNLOCK;
  903                         VOP_UNLOCK(dvp, 0, td);
  904                 }
  905                 newvp = NFSTOV(np);
  906         }
  907         if (v3) {
  908                 nfsm_postop_attr(newvp, attrflag);
  909                 nfsm_postop_attr(dvp, attrflag);
  910         } else
  911                 nfsm_loadattr(newvp, NULL);
  912         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
  913                 cnp->cn_flags |= SAVENAME;
  914         if ((cnp->cn_flags & MAKEENTRY) &&
  915             (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
  916                 np->n_ctime = np->n_vattr.va_ctime.tv_sec;
  917                 cache_enter(dvp, newvp, cnp);
  918         }
  919         *vpp = newvp;
  920         m_freem(mrep);
  921 nfsmout:
  922         if (error) {
  923                 if (newvp != NULLVP) {
  924                         vrele(newvp);
  925                         *vpp = NULLVP;
  926                 }
  927                 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
  928                     (flags & ISLASTCN) && error == ENOENT) {
  929                         if (!lockparent) {
  930                                 VOP_UNLOCK(dvp, 0, td);
  931                                 cnp->cn_flags |= PDIRUNLOCK;
  932                         }
  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  */
  948 static int
  949 nfs_read(struct vop_read_args *ap)
  950 {
  951         struct vnode *vp = ap->a_vp;
  952 
  953         if (vp->v_type != VREG)
  954                 return (EPERM);
  955         return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
  956 }
  957 
  958 /*
  959  * nfs readlink call
  960  */
  961 static int
  962 nfs_readlink(struct vop_readlink_args *ap)
  963 {
  964         struct vnode *vp = ap->a_vp;
  965 
  966         if (vp->v_type != VLNK)
  967                 return (EINVAL);
  968         return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));
  969 }
  970 
  971 /*
  972  * Do a readlink rpc.
  973  * Called by nfs_doio() from below the buffer cache.
  974  */
  975 int
  976 nfs_readlinkrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
  977 {
  978         caddr_t bpos, dpos;
  979         int error = 0, len, attrflag;
  980         struct mbuf *mreq, *mrep, *md, *mb;
  981         int v3 = NFS_ISV3(vp);
  982 
  983         nfsstats.rpccnt[NFSPROC_READLINK]++;
  984         mreq = nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
  985         mb = mreq;
  986         bpos = mtod(mb, caddr_t);
  987         nfsm_fhtom(vp, v3);
  988         nfsm_request(vp, NFSPROC_READLINK, uiop->uio_td, cred);
  989         if (v3)
  990                 nfsm_postop_attr(vp, attrflag);
  991         if (!error) {
  992                 nfsm_strsiz(len, NFS_MAXPATHLEN);
  993                 if (len == NFS_MAXPATHLEN) {
  994                         struct nfsnode *np = VTONFS(vp);
  995                         if (np->n_size && np->n_size < NFS_MAXPATHLEN)
  996                                 len = np->n_size;
  997                 }
  998                 nfsm_mtouio(uiop, len);
  999         }
 1000         m_freem(mrep);
 1001 nfsmout:
 1002         return (error);
 1003 }
 1004 
 1005 /*
 1006  * nfs read rpc call
 1007  * Ditto above
 1008  */
 1009 int
 1010 nfs_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
 1011 {
 1012         u_int32_t *tl;
 1013         caddr_t bpos, dpos;
 1014         struct mbuf *mreq, *mrep, *md, *mb;
 1015         struct nfsmount *nmp;
 1016         int error = 0, len, retlen, tsiz, eof, attrflag;
 1017         int v3 = NFS_ISV3(vp);
 1018 
 1019 #ifndef nolint
 1020         eof = 0;
 1021 #endif
 1022         nmp = VFSTONFS(vp->v_mount);
 1023         tsiz = uiop->uio_resid;
 1024         if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
 1025                 return (EFBIG);
 1026         while (tsiz > 0) {
 1027                 nfsstats.rpccnt[NFSPROC_READ]++;
 1028                 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
 1029                 mreq = nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
 1030                 mb = mreq;
 1031                 bpos = mtod(mb, caddr_t);
 1032                 nfsm_fhtom(vp, v3);
 1033                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED * 3);
 1034                 if (v3) {
 1035                         txdr_hyper(uiop->uio_offset, tl);
 1036                         *(tl + 2) = txdr_unsigned(len);
 1037                 } else {
 1038                         *tl++ = txdr_unsigned(uiop->uio_offset);
 1039                         *tl++ = txdr_unsigned(len);
 1040                         *tl = 0;
 1041                 }
 1042                 nfsm_request(vp, NFSPROC_READ, uiop->uio_td, cred);
 1043                 if (v3) {
 1044                         nfsm_postop_attr(vp, attrflag);
 1045                         if (error) {
 1046                                 m_freem(mrep);
 1047                                 goto nfsmout;
 1048                         }
 1049                         tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED);
 1050                         eof = fxdr_unsigned(int, *(tl + 1));
 1051                 } else
 1052                         nfsm_loadattr(vp, NULL);
 1053                 nfsm_strsiz(retlen, nmp->nm_rsize);
 1054                 nfsm_mtouio(uiop, retlen);
 1055                 m_freem(mrep);
 1056                 tsiz -= retlen;
 1057                 if (v3) {
 1058                         if (eof || retlen == 0) {
 1059                                 tsiz = 0;
 1060                         }
 1061                 } else if (retlen < len) {
 1062                         tsiz = 0;
 1063                 }
 1064         }
 1065 nfsmout:
 1066         return (error);
 1067 }
 1068 
 1069 /*
 1070  * nfs write call
 1071  */
 1072 int
 1073 nfs_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
 1074     int *iomode, int *must_commit)
 1075 {
 1076         u_int32_t *tl;
 1077         int32_t backup;
 1078         caddr_t bpos, dpos;
 1079         struct mbuf *mreq, *mrep, *md, *mb;
 1080         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 1081         int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
 1082         int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
 1083 
 1084 #ifndef DIAGNOSTIC
 1085         if (uiop->uio_iovcnt != 1)
 1086                 panic("nfs: writerpc iovcnt > 1");
 1087 #endif
 1088         *must_commit = 0;
 1089         tsiz = uiop->uio_resid;
 1090         if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
 1091                 return (EFBIG);
 1092         while (tsiz > 0) {
 1093                 nfsstats.rpccnt[NFSPROC_WRITE]++;
 1094                 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
 1095                 mreq = nfsm_reqhead(vp, NFSPROC_WRITE,
 1096                         NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
 1097                 mb = mreq;
 1098                 bpos = mtod(mb, caddr_t);
 1099                 nfsm_fhtom(vp, v3);
 1100                 if (v3) {
 1101                         tl = nfsm_build(u_int32_t *, 5 * NFSX_UNSIGNED);
 1102                         txdr_hyper(uiop->uio_offset, tl);
 1103                         tl += 2;
 1104                         *tl++ = txdr_unsigned(len);
 1105                         *tl++ = txdr_unsigned(*iomode);
 1106                         *tl = txdr_unsigned(len);
 1107                 } else {
 1108                         u_int32_t x;
 1109 
 1110                         tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
 1111                         /* Set both "begin" and "current" to non-garbage. */
 1112                         x = txdr_unsigned((u_int32_t)uiop->uio_offset);
 1113                         *tl++ = x;      /* "begin offset" */
 1114                         *tl++ = x;      /* "current offset" */
 1115                         x = txdr_unsigned(len);
 1116                         *tl++ = x;      /* total to this offset */
 1117                         *tl = x;        /* size of this write */
 1118                 }
 1119                 nfsm_uiotom(uiop, len);
 1120                 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_td, cred);
 1121                 if (v3) {
 1122                         wccflag = NFSV3_WCCCHK;
 1123                         nfsm_wcc_data(vp, wccflag);
 1124                         if (!error) {
 1125                                 tl = nfsm_dissect(u_int32_t *, 2 * NFSX_UNSIGNED
 1126                                         + NFSX_V3WRITEVERF);
 1127                                 rlen = fxdr_unsigned(int, *tl++);
 1128                                 if (rlen == 0) {
 1129                                         error = NFSERR_IO;
 1130                                         m_freem(mrep);
 1131                                         break;
 1132                                 } else if (rlen < len) {
 1133                                         backup = len - rlen;
 1134                                         uiop->uio_iov->iov_base =
 1135                                             (char *)uiop->uio_iov->iov_base -
 1136                                             backup;
 1137                                         uiop->uio_iov->iov_len += backup;
 1138                                         uiop->uio_offset -= backup;
 1139                                         uiop->uio_resid += backup;
 1140                                         len = rlen;
 1141                                 }
 1142                                 commit = fxdr_unsigned(int, *tl++);
 1143 
 1144                                 /*
 1145                                  * Return the lowest committment level
 1146                                  * obtained by any of the RPCs.
 1147                                  */
 1148                                 if (committed == NFSV3WRITE_FILESYNC)
 1149                                         committed = commit;
 1150                                 else if (committed == NFSV3WRITE_DATASYNC &&
 1151                                         commit == NFSV3WRITE_UNSTABLE)
 1152                                         committed = commit;
 1153                                 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0){
 1154                                     bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
 1155                                         NFSX_V3WRITEVERF);
 1156                                     nmp->nm_state |= NFSSTA_HASWRITEVERF;
 1157                                 } else if (bcmp((caddr_t)tl,
 1158                                     (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
 1159                                     *must_commit = 1;
 1160                                     bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
 1161                                         NFSX_V3WRITEVERF);
 1162                                 }
 1163                         }
 1164                 } else
 1165                     nfsm_loadattr(vp, NULL);
 1166                 if (wccflag)
 1167                     VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec;
 1168                 m_freem(mrep);
 1169                 if (error)
 1170                         break;
 1171                 tsiz -= len;
 1172         }
 1173 nfsmout:
 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  */
 1187 static int
 1188 nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
 1189     struct vattr *vap)
 1190 {
 1191         struct nfsv2_sattr *sp;
 1192         u_int32_t *tl;
 1193         struct vnode *newvp = NULL;
 1194         struct nfsnode *np = NULL;
 1195         struct vattr vattr;
 1196         caddr_t bpos, dpos;
 1197         int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
 1198         struct mbuf *mreq, *mrep, *md, *mb;
 1199         u_int32_t rdev;
 1200         int v3 = NFS_ISV3(dvp);
 1201 
 1202         if (vap->va_type == VCHR || vap->va_type == VBLK)
 1203                 rdev = txdr_unsigned(vap->va_rdev);
 1204         else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
 1205                 rdev = nfs_xdrneg1;
 1206         else {
 1207                 return (EOPNOTSUPP);
 1208         }
 1209         if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_thread)) != 0) {
 1210                 return (error);
 1211         }
 1212         nfsstats.rpccnt[NFSPROC_MKNOD]++;
 1213         mreq = nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
 1214                 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
 1215         mb = mreq;
 1216         bpos = mtod(mb, caddr_t);
 1217         nfsm_fhtom(dvp, v3);
 1218         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 1219         if (v3) {
 1220                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
 1221                 *tl++ = vtonfsv3_type(vap->va_type);
 1222                 nfsm_v3attrbuild(vap, FALSE);
 1223                 if (vap->va_type == VCHR || vap->va_type == VBLK) {
 1224                         tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
 1225                         *tl++ = txdr_unsigned(umajor(vap->va_rdev));
 1226                         *tl = txdr_unsigned(uminor(vap->va_rdev));
 1227                 }
 1228         } else {
 1229                 sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
 1230                 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
 1231                 sp->sa_uid = nfs_xdrneg1;
 1232                 sp->sa_gid = nfs_xdrneg1;
 1233                 sp->sa_size = rdev;
 1234                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
 1235                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
 1236         }
 1237         nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_thread, cnp->cn_cred);
 1238         if (!error) {
 1239                 nfsm_mtofh(dvp, newvp, v3, gotvp);
 1240                 if (!gotvp) {
 1241                         if (newvp) {
 1242                                 vput(newvp);
 1243                                 newvp = NULL;
 1244                         }
 1245                         error = nfs_lookitup(dvp, cnp->cn_nameptr,
 1246                             cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread, &np);
 1247                         if (!error)
 1248                                 newvp = NFSTOV(np);
 1249                 }
 1250         }
 1251         if (v3)
 1252                 nfsm_wcc_data(dvp, wccflag);
 1253         m_freem(mrep);
 1254 nfsmout:
 1255         if (error) {
 1256                 if (newvp)
 1257                         vput(newvp);
 1258         } else {
 1259                 if (cnp->cn_flags & MAKEENTRY)
 1260                         cache_enter(dvp, newvp, cnp);
 1261                 *vpp = newvp;
 1262         }
 1263         VTONFS(dvp)->n_flag |= NMODIFIED;
 1264         if (!wccflag)
 1265                 VTONFS(dvp)->n_attrstamp = 0;
 1266         return (error);
 1267 }
 1268 
 1269 /*
 1270  * nfs mknod vop
 1271  * just call nfs_mknodrpc() to do the work.
 1272  */
 1273 /* ARGSUSED */
 1274 static int
 1275 nfs_mknod(struct vop_mknod_args *ap)
 1276 {
 1277 
 1278         return nfs_mknodrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
 1279 }
 1280 
 1281 static u_long create_verf;
 1282 /*
 1283  * nfs file create call
 1284  */
 1285 static int
 1286 nfs_create(struct vop_create_args *ap)
 1287 {
 1288         struct vnode *dvp = ap->a_dvp;
 1289         struct vattr *vap = ap->a_vap;
 1290         struct componentname *cnp = ap->a_cnp;
 1291         struct nfsv2_sattr *sp;
 1292         u_int32_t *tl;
 1293         struct nfsnode *np = NULL;
 1294         struct vnode *newvp = NULL;
 1295         caddr_t bpos, dpos;
 1296         int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
 1297         struct mbuf *mreq, *mrep, *md, *mb;
 1298         struct vattr vattr;
 1299         int v3 = NFS_ISV3(dvp);
 1300 
 1301         /*
 1302          * Oops, not for me..
 1303          */
 1304         if (vap->va_type == VSOCK)
 1305                 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
 1306 
 1307         if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_thread)) != 0) {
 1308                 return (error);
 1309         }
 1310         if (vap->va_vaflags & VA_EXCLUSIVE)
 1311                 fmode |= O_EXCL;
 1312 again:
 1313         nfsstats.rpccnt[NFSPROC_CREATE]++;
 1314         mreq = nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
 1315                 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
 1316         mb = mreq;
 1317         bpos = mtod(mb, caddr_t);
 1318         nfsm_fhtom(dvp, v3);
 1319         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 1320         if (v3) {
 1321                 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
 1322                 if (fmode & O_EXCL) {
 1323                         *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
 1324                         tl = nfsm_build(u_int32_t *, NFSX_V3CREATEVERF);
 1325 #ifdef INET
 1326                         if (!TAILQ_EMPTY(&in_ifaddrhead))
 1327                                 *tl++ = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr.s_addr;
 1328                         else
 1329 #endif
 1330                                 *tl++ = create_verf;
 1331                         *tl = ++create_verf;
 1332                 } else {
 1333                         *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
 1334                         nfsm_v3attrbuild(vap, FALSE);
 1335                 }
 1336         } else {
 1337                 sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
 1338                 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
 1339                 sp->sa_uid = nfs_xdrneg1;
 1340                 sp->sa_gid = nfs_xdrneg1;
 1341                 sp->sa_size = 0;
 1342                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
 1343                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
 1344         }
 1345         nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_thread, cnp->cn_cred);
 1346         if (!error) {
 1347                 nfsm_mtofh(dvp, newvp, v3, gotvp);
 1348                 if (!gotvp) {
 1349                         if (newvp) {
 1350                                 vput(newvp);
 1351                                 newvp = NULL;
 1352                         }
 1353                         error = nfs_lookitup(dvp, cnp->cn_nameptr,
 1354                             cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread, &np);
 1355                         if (!error)
 1356                                 newvp = NFSTOV(np);
 1357                 }
 1358         }
 1359         if (v3)
 1360                 nfsm_wcc_data(dvp, wccflag);
 1361         m_freem(mrep);
 1362 nfsmout:
 1363         if (error) {
 1364                 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
 1365                         fmode &= ~O_EXCL;
 1366                         goto again;
 1367                 }
 1368                 if (newvp)
 1369                         vput(newvp);
 1370         } else if (v3 && (fmode & O_EXCL)) {
 1371                 /*
 1372                  * We are normally called with only a partially initialized
 1373                  * VAP.  Since the NFSv3 spec says that server may use the
 1374                  * file attributes to store the verifier, the spec requires
 1375                  * us to do a SETATTR RPC. FreeBSD servers store the verifier
 1376                  * in atime, but we can't really assume that all servers will
 1377                  * so we ensure that our SETATTR sets both atime and mtime.
 1378                  */
 1379                 if (vap->va_mtime.tv_sec == VNOVAL)
 1380                         vfs_timestamp(&vap->va_mtime);
 1381                 if (vap->va_atime.tv_sec == VNOVAL)
 1382                         vap->va_atime = vap->va_mtime;
 1383                 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_thread);
 1384         }
 1385         if (!error) {
 1386                 if (cnp->cn_flags & MAKEENTRY)
 1387                         cache_enter(dvp, newvp, cnp);
 1388                 *ap->a_vpp = newvp;
 1389         }
 1390         VTONFS(dvp)->n_flag |= NMODIFIED;
 1391         if (!wccflag)
 1392                 VTONFS(dvp)->n_attrstamp = 0;
 1393         return (error);
 1394 }
 1395 
 1396 /*
 1397  * nfs file remove call
 1398  * To try and make nfs semantics closer to ufs semantics, a file that has
 1399  * other processes using the vnode is renamed instead of removed and then
 1400  * removed later on the last close.
 1401  * - If v_usecount > 1
 1402  *        If a rename is not already in the works
 1403  *           call nfs_sillyrename() to set it up
 1404  *     else
 1405  *        do the remove rpc
 1406  */
 1407 static int
 1408 nfs_remove(struct vop_remove_args *ap)
 1409 {
 1410         struct vnode *vp = ap->a_vp;
 1411         struct vnode *dvp = ap->a_dvp;
 1412         struct componentname *cnp = ap->a_cnp;
 1413         struct nfsnode *np = VTONFS(vp);
 1414         int error = 0;
 1415         struct vattr vattr;
 1416 
 1417 #ifndef DIAGNOSTIC
 1418         if ((cnp->cn_flags & HASBUF) == 0)
 1419                 panic("nfs_remove: no name");
 1420         if (vrefcnt(vp) < 1)
 1421                 panic("nfs_remove: bad v_usecount");
 1422 #endif
 1423         if (vp->v_type == VDIR)
 1424                 error = EPERM;
 1425         else if (vrefcnt(vp) == 1 || (np->n_sillyrename &&
 1426             VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_thread) == 0 &&
 1427             vattr.va_nlink > 1)) {
 1428                 /*
 1429                  * Purge the name cache so that the chance of a lookup for
 1430                  * the name succeeding while the remove is in progress is
 1431                  * minimized. Without node locking it can still happen, such
 1432                  * that an I/O op returns ESTALE, but since you get this if
 1433                  * another host removes the file..
 1434                  */
 1435                 cache_purge(vp);
 1436                 /*
 1437                  * throw away biocache buffers, mainly to avoid
 1438                  * unnecessary delayed writes later.
 1439                  */
 1440                 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_thread, 1);
 1441                 /* Do the rpc */
 1442                 if (error != EINTR)
 1443                         error = nfs_removerpc(dvp, cnp->cn_nameptr,
 1444                                 cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread);
 1445                 /*
 1446                  * Kludge City: If the first reply to the remove rpc is lost..
 1447                  *   the reply to the retransmitted request will be ENOENT
 1448                  *   since the file was in fact removed
 1449                  *   Therefore, we cheat and return success.
 1450                  */
 1451                 if (error == ENOENT)
 1452                         error = 0;
 1453         } else if (!np->n_sillyrename)
 1454                 error = nfs_sillyrename(dvp, vp, cnp);
 1455         np->n_attrstamp = 0;
 1456         return (error);
 1457 }
 1458 
 1459 /*
 1460  * nfs file remove rpc called from nfs_inactive
 1461  */
 1462 int
 1463 nfs_removeit(struct sillyrename *sp)
 1464 {
 1465 
 1466         return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
 1467                 NULL));
 1468 }
 1469 
 1470 /*
 1471  * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
 1472  */
 1473 static int
 1474 nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
 1475     struct ucred *cred, struct thread *td)
 1476 {
 1477         caddr_t bpos, dpos;
 1478         int error = 0, wccflag = NFSV3_WCCRATTR;
 1479         struct mbuf *mreq, *mrep, *md, *mb;
 1480         int v3 = NFS_ISV3(dvp);
 1481 
 1482         nfsstats.rpccnt[NFSPROC_REMOVE]++;
 1483         mreq = nfsm_reqhead(dvp, NFSPROC_REMOVE,
 1484                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
 1485         mb = mreq;
 1486         bpos = mtod(mb, caddr_t);
 1487         nfsm_fhtom(dvp, v3);
 1488         nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
 1489         nfsm_request(dvp, NFSPROC_REMOVE, td, cred);
 1490         if (v3)
 1491                 nfsm_wcc_data(dvp, wccflag);
 1492         m_freem(mrep);
 1493 nfsmout:
 1494         VTONFS(dvp)->n_flag |= NMODIFIED;
 1495         if (!wccflag)
 1496                 VTONFS(dvp)->n_attrstamp = 0;
 1497         return (error);
 1498 }
 1499 
 1500 /*
 1501  * nfs file rename call
 1502  */
 1503 static int
 1504 nfs_rename(struct vop_rename_args *ap)
 1505 {
 1506         struct vnode *fvp = ap->a_fvp;
 1507         struct vnode *tvp = ap->a_tvp;
 1508         struct vnode *fdvp = ap->a_fdvp;
 1509         struct vnode *tdvp = ap->a_tdvp;
 1510         struct componentname *tcnp = ap->a_tcnp;
 1511         struct componentname *fcnp = ap->a_fcnp;
 1512         int error;
 1513 
 1514 #ifndef DIAGNOSTIC
 1515         if ((tcnp->cn_flags & HASBUF) == 0 ||
 1516             (fcnp->cn_flags & HASBUF) == 0)
 1517                 panic("nfs_rename: no name");
 1518 #endif
 1519         /* Check for cross-device rename */
 1520         if ((fvp->v_mount != tdvp->v_mount) ||
 1521             (tvp && (fvp->v_mount != tvp->v_mount))) {
 1522                 error = EXDEV;
 1523                 goto out;
 1524         }
 1525 
 1526         if (fvp == tvp) {
 1527                 printf("nfs_rename: fvp == tvp (can't happen)\n");
 1528                 error = 0;
 1529                 goto out;
 1530         }
 1531         if ((error = vn_lock(fvp, LK_EXCLUSIVE, fcnp->cn_thread)) != 0)
 1532                 goto out;
 1533 
 1534         /*
 1535          * We have to flush B_DELWRI data prior to renaming
 1536          * the file.  If we don't, the delayed-write buffers
 1537          * can be flushed out later after the file has gone stale
 1538          * under NFSV3.  NFSV2 does not have this problem because
 1539          * ( as far as I can tell ) it flushes dirty buffers more
 1540          * often.
 1541          */
 1542         VOP_FSYNC(fvp, fcnp->cn_cred, MNT_WAIT, fcnp->cn_thread);
 1543         VOP_UNLOCK(fvp, 0, fcnp->cn_thread);
 1544         if (tvp)
 1545             VOP_FSYNC(tvp, tcnp->cn_cred, MNT_WAIT, tcnp->cn_thread);
 1546 
 1547         /*
 1548          * If the tvp exists and is in use, sillyrename it before doing the
 1549          * rename of the new file over it.
 1550          * XXX Can't sillyrename a directory.
 1551          */
 1552         if (tvp && vrefcnt(tvp) > 1 && !VTONFS(tvp)->n_sillyrename &&
 1553                 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
 1554                 vput(tvp);
 1555                 tvp = NULL;
 1556         }
 1557 
 1558         error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
 1559                 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
 1560                 tcnp->cn_thread);
 1561 
 1562         if (fvp->v_type == VDIR) {
 1563                 if (tvp != NULL && tvp->v_type == VDIR)
 1564                         cache_purge(tdvp);
 1565                 cache_purge(fdvp);
 1566         }
 1567 
 1568 out:
 1569         if (tdvp == tvp)
 1570                 vrele(tdvp);
 1571         else
 1572                 vput(tdvp);
 1573         if (tvp)
 1574                 vput(tvp);
 1575         vrele(fdvp);
 1576         vrele(fvp);
 1577         /*
 1578          * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
 1579          */
 1580         if (error == ENOENT)
 1581                 error = 0;
 1582         return (error);
 1583 }
 1584 
 1585 /*
 1586  * nfs file rename rpc called from nfs_remove() above
 1587  */
 1588 static int
 1589 nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
 1590     struct sillyrename *sp)
 1591 {
 1592 
 1593         return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, sdvp,
 1594             sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_thread));
 1595 }
 1596 
 1597 /*
 1598  * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
 1599  */
 1600 static int
 1601 nfs_renamerpc(struct vnode *fdvp, const char *fnameptr, int fnamelen,
 1602     struct vnode *tdvp, const char *tnameptr, int tnamelen, struct ucred *cred,
 1603     struct thread *td)
 1604 {
 1605         caddr_t bpos, dpos;
 1606         int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
 1607         struct mbuf *mreq, *mrep, *md, *mb;
 1608         int v3 = NFS_ISV3(fdvp);
 1609 
 1610         nfsstats.rpccnt[NFSPROC_RENAME]++;
 1611         mreq = nfsm_reqhead(fdvp, NFSPROC_RENAME,
 1612                 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
 1613                 nfsm_rndup(tnamelen));
 1614         mb = mreq;
 1615         bpos = mtod(mb, caddr_t);
 1616         nfsm_fhtom(fdvp, v3);
 1617         nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
 1618         nfsm_fhtom(tdvp, v3);
 1619         nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
 1620         nfsm_request(fdvp, NFSPROC_RENAME, td, cred);
 1621         if (v3) {
 1622                 nfsm_wcc_data(fdvp, fwccflag);
 1623                 nfsm_wcc_data(tdvp, twccflag);
 1624         }
 1625         m_freem(mrep);
 1626 nfsmout:
 1627         VTONFS(fdvp)->n_flag |= NMODIFIED;
 1628         VTONFS(tdvp)->n_flag |= NMODIFIED;
 1629         if (!fwccflag)
 1630                 VTONFS(fdvp)->n_attrstamp = 0;
 1631         if (!twccflag)
 1632                 VTONFS(tdvp)->n_attrstamp = 0;
 1633         return (error);
 1634 }
 1635 
 1636 /*
 1637  * nfs hard link create call
 1638  */
 1639 static int
 1640 nfs_link(struct vop_link_args *ap)
 1641 {
 1642         struct vnode *vp = ap->a_vp;
 1643         struct vnode *tdvp = ap->a_tdvp;
 1644         struct componentname *cnp = ap->a_cnp;
 1645         caddr_t bpos, dpos;
 1646         int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
 1647         struct mbuf *mreq, *mrep, *md, *mb;
 1648         int v3;
 1649 
 1650         if (vp->v_mount != tdvp->v_mount) {
 1651                 return (EXDEV);
 1652         }
 1653 
 1654         /*
 1655          * Push all writes to the server, so that the attribute cache
 1656          * doesn't get "out of sync" with the server.
 1657          * XXX There should be a better way!
 1658          */
 1659         VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_thread);
 1660 
 1661         v3 = NFS_ISV3(vp);
 1662         nfsstats.rpccnt[NFSPROC_LINK]++;
 1663         mreq = nfsm_reqhead(vp, NFSPROC_LINK,
 1664                 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
 1665         mb = mreq;
 1666         bpos = mtod(mb, caddr_t);
 1667         nfsm_fhtom(vp, v3);
 1668         nfsm_fhtom(tdvp, v3);
 1669         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 1670         nfsm_request(vp, NFSPROC_LINK, cnp->cn_thread, cnp->cn_cred);
 1671         if (v3) {
 1672                 nfsm_postop_attr(vp, attrflag);
 1673                 nfsm_wcc_data(tdvp, wccflag);
 1674         }
 1675         m_freem(mrep);
 1676 nfsmout:
 1677         VTONFS(tdvp)->n_flag |= NMODIFIED;
 1678         if (!attrflag)
 1679                 VTONFS(vp)->n_attrstamp = 0;
 1680         if (!wccflag)
 1681                 VTONFS(tdvp)->n_attrstamp = 0;
 1682         /*
 1683          * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
 1684          */
 1685         if (error == EEXIST)
 1686                 error = 0;
 1687         return (error);
 1688 }
 1689 
 1690 /*
 1691  * nfs symbolic link create call
 1692  */
 1693 static int
 1694 nfs_symlink(struct vop_symlink_args *ap)
 1695 {
 1696         struct vnode *dvp = ap->a_dvp;
 1697         struct vattr *vap = ap->a_vap;
 1698         struct componentname *cnp = ap->a_cnp;
 1699         struct nfsv2_sattr *sp;
 1700         caddr_t bpos, dpos;
 1701         int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
 1702         struct mbuf *mreq, *mrep, *md, *mb;
 1703         struct vnode *newvp = NULL;
 1704         int v3 = NFS_ISV3(dvp);
 1705 
 1706         nfsstats.rpccnt[NFSPROC_SYMLINK]++;
 1707         slen = strlen(ap->a_target);
 1708         mreq = nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
 1709             nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
 1710         mb = mreq;
 1711         bpos = mtod(mb, caddr_t);
 1712         nfsm_fhtom(dvp, v3);
 1713         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 1714         if (v3) {
 1715                 nfsm_v3attrbuild(vap, FALSE);
 1716         }
 1717         nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
 1718         if (!v3) {
 1719                 sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
 1720                 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
 1721                 sp->sa_uid = nfs_xdrneg1;
 1722                 sp->sa_gid = nfs_xdrneg1;
 1723                 sp->sa_size = nfs_xdrneg1;
 1724                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
 1725                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
 1726         }
 1727 
 1728         /*
 1729          * Issue the NFS request and get the rpc response.
 1730          *
 1731          * Only NFSv3 responses returning an error of 0 actually return
 1732          * a file handle that can be converted into newvp without having
 1733          * to do an extra lookup rpc.
 1734          */
 1735         nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_thread, cnp->cn_cred);
 1736         if (v3) {
 1737                 if (error == 0)
 1738                         nfsm_mtofh(dvp, newvp, v3, gotvp);
 1739                 nfsm_wcc_data(dvp, wccflag);
 1740         }
 1741 
 1742         /*
 1743          * out code jumps -> here, mrep is also freed.
 1744          */
 1745 
 1746         m_freem(mrep);
 1747 nfsmout:
 1748 
 1749         /*
 1750          * If we get an EEXIST error, silently convert it to no-error
 1751          * in case of an NFS retry.
 1752          */
 1753         if (error == EEXIST)
 1754                 error = 0;
 1755 
 1756         /*
 1757          * If we do not have (or no longer have) an error, and we could
 1758          * not extract the newvp from the response due to the request being
 1759          * NFSv2 or the error being EEXIST.  We have to do a lookup in order
 1760          * to obtain a newvp to return.
 1761          */
 1762         if (error == 0 && newvp == NULL) {
 1763                 struct nfsnode *np = NULL;
 1764 
 1765                 error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
 1766                     cnp->cn_cred, cnp->cn_thread, &np);
 1767                 if (!error)
 1768                         newvp = NFSTOV(np);
 1769         }
 1770         if (error) {
 1771                 if (newvp)
 1772                         vput(newvp);
 1773         } else {
 1774                 *ap->a_vpp = newvp;
 1775         }
 1776         VTONFS(dvp)->n_flag |= NMODIFIED;
 1777         if (!wccflag)
 1778                 VTONFS(dvp)->n_attrstamp = 0;
 1779         return (error);
 1780 }
 1781 
 1782 /*
 1783  * nfs make dir call
 1784  */
 1785 static int
 1786 nfs_mkdir(struct vop_mkdir_args *ap)
 1787 {
 1788         struct vnode *dvp = ap->a_dvp;
 1789         struct vattr *vap = ap->a_vap;
 1790         struct componentname *cnp = ap->a_cnp;
 1791         struct nfsv2_sattr *sp;
 1792         int len;
 1793         struct nfsnode *np = NULL;
 1794         struct vnode *newvp = NULL;
 1795         caddr_t bpos, dpos;
 1796         int error = 0, wccflag = NFSV3_WCCRATTR;
 1797         int gotvp = 0;
 1798         struct mbuf *mreq, *mrep, *md, *mb;
 1799         struct vattr vattr;
 1800         int v3 = NFS_ISV3(dvp);
 1801 
 1802         if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_thread)) != 0) {
 1803                 return (error);
 1804         }
 1805         len = cnp->cn_namelen;
 1806         nfsstats.rpccnt[NFSPROC_MKDIR]++;
 1807         mreq = nfsm_reqhead(dvp, NFSPROC_MKDIR,
 1808           NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
 1809         mb = mreq;
 1810         bpos = mtod(mb, caddr_t);
 1811         nfsm_fhtom(dvp, v3);
 1812         nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
 1813         if (v3) {
 1814                 nfsm_v3attrbuild(vap, FALSE);
 1815         } else {
 1816                 sp = nfsm_build(struct nfsv2_sattr *, NFSX_V2SATTR);
 1817                 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
 1818                 sp->sa_uid = nfs_xdrneg1;
 1819                 sp->sa_gid = nfs_xdrneg1;
 1820                 sp->sa_size = nfs_xdrneg1;
 1821                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
 1822                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
 1823         }
 1824         nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_thread, cnp->cn_cred);
 1825         if (!error)
 1826                 nfsm_mtofh(dvp, newvp, v3, gotvp);
 1827         if (v3)
 1828                 nfsm_wcc_data(dvp, wccflag);
 1829         m_freem(mrep);
 1830 nfsmout:
 1831         VTONFS(dvp)->n_flag |= NMODIFIED;
 1832         if (!wccflag)
 1833                 VTONFS(dvp)->n_attrstamp = 0;
 1834         /*
 1835          * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
 1836          * if we can succeed in looking up the directory.
 1837          */
 1838         if (error == EEXIST || (!error && !gotvp)) {
 1839                 if (newvp) {
 1840                         vrele(newvp);
 1841                         newvp = NULL;
 1842                 }
 1843                 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
 1844                         cnp->cn_thread, &np);
 1845                 if (!error) {
 1846                         newvp = NFSTOV(np);
 1847                         if (newvp->v_type != VDIR)
 1848                                 error = EEXIST;
 1849                 }
 1850         }
 1851         if (error) {
 1852                 if (newvp)
 1853                         vrele(newvp);
 1854         } else
 1855                 *ap->a_vpp = newvp;
 1856         return (error);
 1857 }
 1858 
 1859 /*
 1860  * nfs remove directory call
 1861  */
 1862 static int
 1863 nfs_rmdir(struct vop_rmdir_args *ap)
 1864 {
 1865         struct vnode *vp = ap->a_vp;
 1866         struct vnode *dvp = ap->a_dvp;
 1867         struct componentname *cnp = ap->a_cnp;
 1868         caddr_t bpos, dpos;
 1869         int error = 0, wccflag = NFSV3_WCCRATTR;
 1870         struct mbuf *mreq, *mrep, *md, *mb;
 1871         int v3 = NFS_ISV3(dvp);
 1872 
 1873         if (dvp == vp)
 1874                 return (EINVAL);
 1875         nfsstats.rpccnt[NFSPROC_RMDIR]++;
 1876         mreq = nfsm_reqhead(dvp, NFSPROC_RMDIR,
 1877                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
 1878         mb = mreq;
 1879         bpos = mtod(mb, caddr_t);
 1880         nfsm_fhtom(dvp, v3);
 1881         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 1882         nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_thread, cnp->cn_cred);
 1883         if (v3)
 1884                 nfsm_wcc_data(dvp, wccflag);
 1885         m_freem(mrep);
 1886 nfsmout:
 1887         VTONFS(dvp)->n_flag |= NMODIFIED;
 1888         if (!wccflag)
 1889                 VTONFS(dvp)->n_attrstamp = 0;
 1890         cache_purge(dvp);
 1891         cache_purge(vp);
 1892         /*
 1893          * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
 1894          */
 1895         if (error == ENOENT)
 1896                 error = 0;
 1897         return (error);
 1898 }
 1899 
 1900 /*
 1901  * nfs readdir call
 1902  */
 1903 static int
 1904 nfs_readdir(struct vop_readdir_args *ap)
 1905 {
 1906         struct vnode *vp = ap->a_vp;
 1907         struct nfsnode *np = VTONFS(vp);
 1908         struct uio *uio = ap->a_uio;
 1909         int tresid, error;
 1910         struct vattr vattr;
 1911 
 1912         if (vp->v_type != VDIR)
 1913                 return (EPERM);
 1914         /*
 1915          * First, check for hit on the EOF offset cache
 1916          */
 1917         if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
 1918             (np->n_flag & NMODIFIED) == 0) {
 1919                 if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_td) == 0 &&
 1920                         np->n_mtime == vattr.va_mtime.tv_sec) {
 1921                         nfsstats.direofcache_hits++;
 1922                         return (0);
 1923                 }
 1924         }
 1925 
 1926         /*
 1927          * Call nfs_bioread() to do the real work.
 1928          */
 1929         tresid = uio->uio_resid;
 1930         error = nfs_bioread(vp, uio, 0, ap->a_cred);
 1931 
 1932         if (!error && uio->uio_resid == tresid)
 1933                 nfsstats.direofcache_misses++;
 1934         return (error);
 1935 }
 1936 
 1937 /*
 1938  * Readdir rpc call.
 1939  * Called from below the buffer cache by nfs_doio().
 1940  */
 1941 int
 1942 nfs_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
 1943 {
 1944         int len, left;
 1945         struct dirent *dp = NULL;
 1946         u_int32_t *tl;
 1947         caddr_t cp;
 1948         nfsuint64 *cookiep;
 1949         caddr_t bpos, dpos;
 1950         struct mbuf *mreq, *mrep, *md, *mb;
 1951         nfsuint64 cookie;
 1952         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 1953         struct nfsnode *dnp = VTONFS(vp);
 1954         u_quad_t fileno;
 1955         int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
 1956         int attrflag;
 1957         int v3 = NFS_ISV3(vp);
 1958 
 1959 #ifndef DIAGNOSTIC
 1960         if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
 1961                 (uiop->uio_resid & (DIRBLKSIZ - 1)))
 1962                 panic("nfs readdirrpc bad uio");
 1963 #endif
 1964 
 1965         /*
 1966          * If there is no cookie, assume directory was stale.
 1967          */
 1968         cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
 1969         if (cookiep)
 1970                 cookie = *cookiep;
 1971         else
 1972                 return (NFSERR_BAD_COOKIE);
 1973         /*
 1974          * Loop around doing readdir rpc's of size nm_readdirsize
 1975          * truncated to a multiple of DIRBLKSIZ.
 1976          * The stopping criteria is EOF or buffer full.
 1977          */
 1978         while (more_dirs && bigenough) {
 1979                 nfsstats.rpccnt[NFSPROC_READDIR]++;
 1980                 mreq = nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
 1981                         NFSX_READDIR(v3));
 1982                 mb = mreq;
 1983                 bpos = mtod(mb, caddr_t);
 1984                 nfsm_fhtom(vp, v3);
 1985                 if (v3) {
 1986                         tl = nfsm_build(u_int32_t *, 5 * NFSX_UNSIGNED);
 1987                         *tl++ = cookie.nfsuquad[0];
 1988                         *tl++ = cookie.nfsuquad[1];
 1989                         *tl++ = dnp->n_cookieverf.nfsuquad[0];
 1990                         *tl++ = dnp->n_cookieverf.nfsuquad[1];
 1991                 } else {
 1992                         tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
 1993                         *tl++ = cookie.nfsuquad[0];
 1994                 }
 1995                 *tl = txdr_unsigned(nmp->nm_readdirsize);
 1996                 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_td, cred);
 1997                 if (v3) {
 1998                         nfsm_postop_attr(vp, attrflag);
 1999                         if (!error) {
 2000                                 tl = nfsm_dissect(u_int32_t *,
 2001                                     2 * NFSX_UNSIGNED);
 2002                                 dnp->n_cookieverf.nfsuquad[0] = *tl++;
 2003                                 dnp->n_cookieverf.nfsuquad[1] = *tl;
 2004                         } else {
 2005                                 m_freem(mrep);
 2006                                 goto nfsmout;
 2007                         }
 2008                 }
 2009                 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 2010                 more_dirs = fxdr_unsigned(int, *tl);
 2011 
 2012                 /* loop thru the dir entries, doctoring them to 4bsd form */
 2013                 while (more_dirs && bigenough) {
 2014                         if (v3) {
 2015                                 tl = nfsm_dissect(u_int32_t *,
 2016                                     3 * NFSX_UNSIGNED);
 2017                                 fileno = fxdr_hyper(tl);
 2018                                 len = fxdr_unsigned(int, *(tl + 2));
 2019                         } else {
 2020                                 tl = nfsm_dissect(u_int32_t *,
 2021                                     2 * NFSX_UNSIGNED);
 2022                                 fileno = fxdr_unsigned(u_quad_t, *tl++);
 2023                                 len = fxdr_unsigned(int, *tl);
 2024                         }
 2025                         if (len <= 0 || len > NFS_MAXNAMLEN) {
 2026                                 error = EBADRPC;
 2027                                 m_freem(mrep);
 2028                                 goto nfsmout;
 2029                         }
 2030                         tlen = nfsm_rndup(len);
 2031                         if (tlen == len)
 2032                                 tlen += 4;      /* To ensure null termination */
 2033                         left = DIRBLKSIZ - blksiz;
 2034                         if ((tlen + DIRHDSIZ) > left) {
 2035                                 dp->d_reclen += left;
 2036                                 uiop->uio_iov->iov_base =
 2037                                     (char *)uiop->uio_iov->iov_base + left;
 2038                                 uiop->uio_iov->iov_len -= left;
 2039                                 uiop->uio_offset += left;
 2040                                 uiop->uio_resid -= left;
 2041                                 blksiz = 0;
 2042                         }
 2043                         if ((tlen + DIRHDSIZ) > uiop->uio_resid)
 2044                                 bigenough = 0;
 2045                         if (bigenough) {
 2046                                 dp = (struct dirent *)uiop->uio_iov->iov_base;
 2047                                 dp->d_fileno = (int)fileno;
 2048                                 dp->d_namlen = len;
 2049                                 dp->d_reclen = tlen + DIRHDSIZ;
 2050                                 dp->d_type = DT_UNKNOWN;
 2051                                 blksiz += dp->d_reclen;
 2052                                 if (blksiz == DIRBLKSIZ)
 2053                                         blksiz = 0;
 2054                                 uiop->uio_offset += DIRHDSIZ;
 2055                                 uiop->uio_resid -= DIRHDSIZ;
 2056                                 uiop->uio_iov->iov_base =
 2057                                     (char *)uiop->uio_iov->iov_base + DIRHDSIZ;
 2058                                 uiop->uio_iov->iov_len -= DIRHDSIZ;
 2059                                 nfsm_mtouio(uiop, len);
 2060                                 cp = uiop->uio_iov->iov_base;
 2061                                 tlen -= len;
 2062                                 *cp = '\0';     /* null terminate */
 2063                                 uiop->uio_iov->iov_base =
 2064                                     (char *)uiop->uio_iov->iov_base + tlen;
 2065                                 uiop->uio_iov->iov_len -= tlen;
 2066                                 uiop->uio_offset += tlen;
 2067                                 uiop->uio_resid -= tlen;
 2068                         } else
 2069                                 nfsm_adv(nfsm_rndup(len));
 2070                         if (v3) {
 2071                                 tl = nfsm_dissect(u_int32_t *,
 2072                                     3 * NFSX_UNSIGNED);
 2073                         } else {
 2074                                 tl = nfsm_dissect(u_int32_t *,
 2075                                     2 * NFSX_UNSIGNED);
 2076                         }
 2077                         if (bigenough) {
 2078                                 cookie.nfsuquad[0] = *tl++;
 2079                                 if (v3)
 2080                                         cookie.nfsuquad[1] = *tl++;
 2081                         } else if (v3)
 2082                                 tl += 2;
 2083                         else
 2084                                 tl++;
 2085                         more_dirs = fxdr_unsigned(int, *tl);
 2086                 }
 2087                 /*
 2088                  * If at end of rpc data, get the eof boolean
 2089                  */
 2090                 if (!more_dirs) {
 2091                         tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 2092                         more_dirs = (fxdr_unsigned(int, *tl) == 0);
 2093                 }
 2094                 m_freem(mrep);
 2095         }
 2096         /*
 2097          * Fill last record, iff any, out to a multiple of DIRBLKSIZ
 2098          * by increasing d_reclen for the last record.
 2099          */
 2100         if (blksiz > 0) {
 2101                 left = DIRBLKSIZ - blksiz;
 2102                 dp->d_reclen += left;
 2103                 uiop->uio_iov->iov_base =
 2104                     (char *)uiop->uio_iov->iov_base + left;
 2105                 uiop->uio_iov->iov_len -= left;
 2106                 uiop->uio_offset += left;
 2107                 uiop->uio_resid -= left;
 2108         }
 2109 
 2110         /*
 2111          * We are now either at the end of the directory or have filled the
 2112          * block.
 2113          */
 2114         if (bigenough)
 2115                 dnp->n_direofoffset = uiop->uio_offset;
 2116         else {
 2117                 if (uiop->uio_resid > 0)
 2118                         printf("EEK! readdirrpc resid > 0\n");
 2119                 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
 2120                 *cookiep = cookie;
 2121         }
 2122 nfsmout:
 2123         return (error);
 2124 }
 2125 
 2126 /*
 2127  * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
 2128  */
 2129 int
 2130 nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
 2131 {
 2132         int len, left;
 2133         struct dirent *dp;
 2134         u_int32_t *tl;
 2135         caddr_t cp;
 2136         struct vnode *newvp;
 2137         nfsuint64 *cookiep;
 2138         caddr_t bpos, dpos, dpossav1, dpossav2;
 2139         struct mbuf *mreq, *mrep, *md, *mb, *mdsav1, *mdsav2;
 2140         struct nameidata nami, *ndp = &nami;
 2141         struct componentname *cnp = &ndp->ni_cnd;
 2142         nfsuint64 cookie;
 2143         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 2144         struct nfsnode *dnp = VTONFS(vp), *np;
 2145         nfsfh_t *fhp;
 2146         u_quad_t fileno;
 2147         int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
 2148         int attrflag, fhsize;
 2149 
 2150 #ifndef nolint
 2151         dp = NULL;
 2152 #endif
 2153 #ifndef DIAGNOSTIC
 2154         if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
 2155                 (uiop->uio_resid & (DIRBLKSIZ - 1)))
 2156                 panic("nfs readdirplusrpc bad uio");
 2157 #endif
 2158         ndp->ni_dvp = vp;
 2159         newvp = NULLVP;
 2160 
 2161         /*
 2162          * If there is no cookie, assume directory was stale.
 2163          */
 2164         cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
 2165         if (cookiep)
 2166                 cookie = *cookiep;
 2167         else
 2168                 return (NFSERR_BAD_COOKIE);
 2169         /*
 2170          * Loop around doing readdir rpc's of size nm_readdirsize
 2171          * truncated to a multiple of DIRBLKSIZ.
 2172          * The stopping criteria is EOF or buffer full.
 2173          */
 2174         while (more_dirs && bigenough) {
 2175                 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
 2176                 mreq = nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
 2177                         NFSX_FH(1) + 6 * NFSX_UNSIGNED);
 2178                 mb = mreq;
 2179                 bpos = mtod(mb, caddr_t);
 2180                 nfsm_fhtom(vp, 1);
 2181                 tl = nfsm_build(u_int32_t *, 6 * NFSX_UNSIGNED);
 2182                 *tl++ = cookie.nfsuquad[0];
 2183                 *tl++ = cookie.nfsuquad[1];
 2184                 *tl++ = dnp->n_cookieverf.nfsuquad[0];
 2185                 *tl++ = dnp->n_cookieverf.nfsuquad[1];
 2186                 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
 2187                 *tl = txdr_unsigned(nmp->nm_rsize);
 2188                 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_td, cred);
 2189                 nfsm_postop_attr(vp, attrflag);
 2190                 if (error) {
 2191                         m_freem(mrep);
 2192                         goto nfsmout;
 2193                 }
 2194                 tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
 2195                 dnp->n_cookieverf.nfsuquad[0] = *tl++;
 2196                 dnp->n_cookieverf.nfsuquad[1] = *tl++;
 2197                 more_dirs = fxdr_unsigned(int, *tl);
 2198 
 2199                 /* loop thru the dir entries, doctoring them to 4bsd form */
 2200                 while (more_dirs && bigenough) {
 2201                         tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
 2202                         fileno = fxdr_hyper(tl);
 2203                         len = fxdr_unsigned(int, *(tl + 2));
 2204                         if (len <= 0 || len > NFS_MAXNAMLEN) {
 2205                                 error = EBADRPC;
 2206                                 m_freem(mrep);
 2207                                 goto nfsmout;
 2208                         }
 2209                         tlen = nfsm_rndup(len);
 2210                         if (tlen == len)
 2211                                 tlen += 4;      /* To ensure null termination*/
 2212                         left = DIRBLKSIZ - blksiz;
 2213                         if ((tlen + DIRHDSIZ) > left) {
 2214                                 dp->d_reclen += left;
 2215                                 uiop->uio_iov->iov_base =
 2216                                     (char *)uiop->uio_iov->iov_base + left;
 2217                                 uiop->uio_iov->iov_len -= left;
 2218                                 uiop->uio_offset += left;
 2219                                 uiop->uio_resid -= left;
 2220                                 blksiz = 0;
 2221                         }
 2222                         if ((tlen + DIRHDSIZ) > uiop->uio_resid)
 2223                                 bigenough = 0;
 2224                         if (bigenough) {
 2225                                 dp = (struct dirent *)uiop->uio_iov->iov_base;
 2226                                 dp->d_fileno = (int)fileno;
 2227                                 dp->d_namlen = len;
 2228                                 dp->d_reclen = tlen + DIRHDSIZ;
 2229                                 dp->d_type = DT_UNKNOWN;
 2230                                 blksiz += dp->d_reclen;
 2231                                 if (blksiz == DIRBLKSIZ)
 2232                                         blksiz = 0;
 2233                                 uiop->uio_offset += DIRHDSIZ;
 2234                                 uiop->uio_resid -= DIRHDSIZ;
 2235                                 uiop->uio_iov->iov_base =
 2236                                     (char *)uiop->uio_iov->iov_base + DIRHDSIZ;
 2237                                 uiop->uio_iov->iov_len -= DIRHDSIZ;
 2238                                 cnp->cn_nameptr = uiop->uio_iov->iov_base;
 2239                                 cnp->cn_namelen = len;
 2240                                 nfsm_mtouio(uiop, len);
 2241                                 cp = uiop->uio_iov->iov_base;
 2242                                 tlen -= len;
 2243                                 *cp = '\0';
 2244                                 uiop->uio_iov->iov_base =
 2245                                     (char *)uiop->uio_iov->iov_base + tlen;
 2246                                 uiop->uio_iov->iov_len -= tlen;
 2247                                 uiop->uio_offset += tlen;
 2248                                 uiop->uio_resid -= tlen;
 2249                         } else
 2250                                 nfsm_adv(nfsm_rndup(len));
 2251                         tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
 2252                         if (bigenough) {
 2253                                 cookie.nfsuquad[0] = *tl++;
 2254                                 cookie.nfsuquad[1] = *tl++;
 2255                         } else
 2256                                 tl += 2;
 2257 
 2258                         /*
 2259                          * Since the attributes are before the file handle
 2260                          * (sigh), we must skip over the attributes and then
 2261                          * come back and get them.
 2262                          */
 2263                         attrflag = fxdr_unsigned(int, *tl);
 2264                         if (attrflag) {
 2265                             dpossav1 = dpos;
 2266                             mdsav1 = md;
 2267                             nfsm_adv(NFSX_V3FATTR);
 2268                             tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 2269                             doit = fxdr_unsigned(int, *tl);
 2270                             if (doit) {
 2271                                 nfsm_getfh(fhp, fhsize, 1);
 2272                                 if (NFS_CMPFH(dnp, fhp, fhsize)) {
 2273                                     VREF(vp);
 2274                                     newvp = vp;
 2275                                     np = dnp;
 2276                                 } else {
 2277                                     error = nfs_nget(vp->v_mount, fhp,
 2278                                         fhsize, &np);
 2279                                     if (error)
 2280                                         doit = 0;
 2281                                     else
 2282                                         newvp = NFSTOV(np);
 2283                                 }
 2284                             }
 2285                             if (doit && bigenough) {
 2286                                 dpossav2 = dpos;
 2287                                 dpos = dpossav1;
 2288                                 mdsav2 = md;
 2289                                 md = mdsav1;
 2290                                 nfsm_loadattr(newvp, NULL);
 2291                                 dpos = dpossav2;
 2292                                 md = mdsav2;
 2293                                 dp->d_type =
 2294                                     IFTODT(VTTOIF(np->n_vattr.va_type));
 2295                                 ndp->ni_vp = newvp;
 2296                                 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp);
 2297                             }
 2298                         } else {
 2299                             /* Just skip over the file handle */
 2300                             tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 2301                             i = fxdr_unsigned(int, *tl);
 2302                             nfsm_adv(nfsm_rndup(i));
 2303                         }
 2304                         if (newvp != NULLVP) {
 2305                             if (newvp == vp)
 2306                                 vrele(newvp);
 2307                             else
 2308                                 vput(newvp);
 2309                             newvp = NULLVP;
 2310                         }
 2311                         tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 2312                         more_dirs = fxdr_unsigned(int, *tl);
 2313                 }
 2314                 /*
 2315                  * If at end of rpc data, get the eof boolean
 2316                  */
 2317                 if (!more_dirs) {
 2318                         tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
 2319                         more_dirs = (fxdr_unsigned(int, *tl) == 0);
 2320                 }
 2321                 m_freem(mrep);
 2322         }
 2323         /*
 2324          * Fill last record, iff any, out to a multiple of DIRBLKSIZ
 2325          * by increasing d_reclen for the last record.
 2326          */
 2327         if (blksiz > 0) {
 2328                 left = DIRBLKSIZ - blksiz;
 2329                 dp->d_reclen += left;
 2330                 uiop->uio_iov->iov_base =
 2331                     (char *)uiop->uio_iov->iov_base + left;
 2332                 uiop->uio_iov->iov_len -= left;
 2333                 uiop->uio_offset += left;
 2334                 uiop->uio_resid -= left;
 2335         }
 2336 
 2337         /*
 2338          * We are now either at the end of the directory or have filled the
 2339          * block.
 2340          */
 2341         if (bigenough)
 2342                 dnp->n_direofoffset = uiop->uio_offset;
 2343         else {
 2344                 if (uiop->uio_resid > 0)
 2345                         printf("EEK! readdirplusrpc resid > 0\n");
 2346                 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
 2347                 *cookiep = cookie;
 2348         }
 2349 nfsmout:
 2350         if (newvp != NULLVP) {
 2351                 if (newvp == vp)
 2352                         vrele(newvp);
 2353                 else
 2354                         vput(newvp);
 2355                 newvp = NULLVP;
 2356         }
 2357         return (error);
 2358 }
 2359 
 2360 /*
 2361  * Silly rename. To make the NFS filesystem that is stateless look a little
 2362  * more like the "ufs" a remove of an active vnode is translated to a rename
 2363  * to a funny looking filename that is removed by nfs_inactive on the
 2364  * nfsnode. There is the potential for another process on a different client
 2365  * to create the same funny name between the nfs_lookitup() fails and the
 2366  * nfs_rename() completes, but...
 2367  */
 2368 static int
 2369 nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
 2370 {
 2371         struct sillyrename *sp;
 2372         struct nfsnode *np;
 2373         int error;
 2374         short pid;
 2375 
 2376         cache_purge(dvp);
 2377         np = VTONFS(vp);
 2378 #ifndef DIAGNOSTIC
 2379         if (vp->v_type == VDIR)
 2380                 panic("nfs: sillyrename dir");
 2381 #endif
 2382         MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
 2383                 M_NFSREQ, M_WAITOK);
 2384         sp->s_cred = crhold(cnp->cn_cred);
 2385         sp->s_dvp = dvp;
 2386         VREF(dvp);
 2387 
 2388         /* Fudge together a funny name */
 2389         pid = cnp->cn_thread->td_proc->p_pid;
 2390         sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid);
 2391 
 2392         /* Try lookitups until we get one that isn't there */
 2393         while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
 2394                 cnp->cn_thread, NULL) == 0) {
 2395                 sp->s_name[4]++;
 2396                 if (sp->s_name[4] > 'z') {
 2397                         error = EINVAL;
 2398                         goto bad;
 2399                 }
 2400         }
 2401         error = nfs_renameit(dvp, cnp, sp);
 2402         if (error)
 2403                 goto bad;
 2404         error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
 2405                 cnp->cn_thread, &np);
 2406         np->n_sillyrename = sp;
 2407         return (0);
 2408 bad:
 2409         vrele(sp->s_dvp);
 2410         crfree(sp->s_cred);
 2411         free((caddr_t)sp, M_NFSREQ);
 2412         return (error);
 2413 }
 2414 
 2415 /*
 2416  * Look up a file name and optionally either update the file handle or
 2417  * allocate an nfsnode, depending on the value of npp.
 2418  * npp == NULL  --> just do the lookup
 2419  * *npp == NULL --> allocate a new nfsnode and make sure attributes are
 2420  *                      handled too
 2421  * *npp != NULL --> update the file handle in the vnode
 2422  */
 2423 static int
 2424 nfs_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
 2425     struct thread *td, struct nfsnode **npp)
 2426 {
 2427         struct vnode *newvp = NULL;
 2428         struct nfsnode *np, *dnp = VTONFS(dvp);
 2429         caddr_t bpos, dpos;
 2430         int error = 0, fhlen, attrflag;
 2431         struct mbuf *mreq, *mrep, *md, *mb;
 2432         nfsfh_t *nfhp;
 2433         int v3 = NFS_ISV3(dvp);
 2434 
 2435         nfsstats.rpccnt[NFSPROC_LOOKUP]++;
 2436         mreq = nfsm_reqhead(dvp, NFSPROC_LOOKUP,
 2437                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
 2438         mb = mreq;
 2439         bpos = mtod(mb, caddr_t);
 2440         nfsm_fhtom(dvp, v3);
 2441         nfsm_strtom(name, len, NFS_MAXNAMLEN);
 2442         nfsm_request(dvp, NFSPROC_LOOKUP, td, cred);
 2443         if (npp && !error) {
 2444                 nfsm_getfh(nfhp, fhlen, v3);
 2445                 if (*npp) {
 2446                     np = *npp;
 2447                     if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
 2448                         free((caddr_t)np->n_fhp, M_NFSBIGFH);
 2449                         np->n_fhp = &np->n_fh;
 2450                     } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
 2451                         np->n_fhp =(nfsfh_t *)malloc(fhlen, M_NFSBIGFH, M_WAITOK);
 2452                     bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
 2453                     np->n_fhsize = fhlen;
 2454                     newvp = NFSTOV(np);
 2455                 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
 2456                     VREF(dvp);
 2457                     newvp = dvp;
 2458                 } else {
 2459                     error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
 2460                     if (error) {
 2461                         m_freem(mrep);
 2462                         return (error);
 2463                     }
 2464                     newvp = NFSTOV(np);
 2465                 }
 2466                 if (v3) {
 2467                         nfsm_postop_attr(newvp, attrflag);
 2468                         if (!attrflag && *npp == NULL) {
 2469                                 m_freem(mrep);
 2470                                 if (newvp == dvp)
 2471                                         vrele(newvp);
 2472                                 else
 2473                                         vput(newvp);
 2474                                 return (ENOENT);
 2475                         }
 2476                 } else
 2477                         nfsm_loadattr(newvp, NULL);
 2478         }
 2479         m_freem(mrep);
 2480 nfsmout:
 2481         if (npp && *npp == NULL) {
 2482                 if (error) {
 2483                         if (newvp) {
 2484                                 if (newvp == dvp)
 2485                                         vrele(newvp);
 2486                                 else
 2487                                         vput(newvp);
 2488                         }
 2489                 } else
 2490                         *npp = np;
 2491         }
 2492         return (error);
 2493 }
 2494 
 2495 /*
 2496  * Nfs Version 3 commit rpc
 2497  */
 2498 int
 2499 nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred,
 2500     struct thread *td)
 2501 {
 2502         u_int32_t *tl;
 2503         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 2504         caddr_t bpos, dpos;
 2505         int error = 0, wccflag = NFSV3_WCCRATTR;
 2506         struct mbuf *mreq, *mrep, *md, *mb;
 2507 
 2508         if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0)
 2509                 return (0);
 2510         nfsstats.rpccnt[NFSPROC_COMMIT]++;
 2511         mreq = nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
 2512         mb = mreq;
 2513         bpos = mtod(mb, caddr_t);
 2514         nfsm_fhtom(vp, 1);
 2515         tl = nfsm_build(u_int32_t *, 3 * NFSX_UNSIGNED);
 2516         txdr_hyper(offset, tl);
 2517         tl += 2;
 2518         *tl = txdr_unsigned(cnt);
 2519         nfsm_request(vp, NFSPROC_COMMIT, td, cred);
 2520         nfsm_wcc_data(vp, wccflag);
 2521         if (!error) {
 2522                 tl = nfsm_dissect(u_int32_t *, NFSX_V3WRITEVERF);
 2523                 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
 2524                         NFSX_V3WRITEVERF)) {
 2525                         bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
 2526                                 NFSX_V3WRITEVERF);
 2527                         error = NFSERR_STALEWRITEVERF;
 2528                 }
 2529         }
 2530         m_freem(mrep);
 2531 nfsmout:
 2532         return (error);
 2533 }
 2534 
 2535 /*
 2536  * Strategy routine.
 2537  * For async requests when nfsiod(s) are running, queue the request by
 2538  * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
 2539  * request.
 2540  */
 2541 static int
 2542 nfs_strategy(struct vop_strategy_args *ap)
 2543 {
 2544         struct buf *bp = ap->a_bp;
 2545         struct ucred *cr;
 2546         struct thread *td;
 2547         int error = 0;
 2548 
 2549         KASSERT(!(bp->b_flags & B_DONE), ("nfs_strategy: buffer %p unexpectedly marked B_DONE", bp));
 2550         KASSERT(BUF_REFCNT(bp) > 0, ("nfs_strategy: buffer %p not locked", bp));
 2551 
 2552         if (bp->b_flags & B_PHYS)
 2553                 panic("nfs physio");
 2554 
 2555         if (bp->b_flags & B_ASYNC)
 2556                 td = NULL;
 2557         else
 2558                 td = curthread; /* XXX */
 2559 
 2560         if (bp->b_iocmd == BIO_READ)
 2561                 cr = bp->b_rcred;
 2562         else
 2563                 cr = bp->b_wcred;
 2564 
 2565         /*
 2566          * If the op is asynchronous and an i/o daemon is waiting
 2567          * queue the request, wake it up and wait for completion
 2568          * otherwise just do it ourselves.
 2569          */
 2570         if ((bp->b_flags & B_ASYNC) == 0 ||
 2571                 nfs_asyncio(bp, NOCRED, td))
 2572                 error = nfs_doio(bp, cr, td);
 2573         return (error);
 2574 }
 2575 
 2576 /*
 2577  * fsync vnode op. Just call nfs_flush() with commit == 1.
 2578  */
 2579 /* ARGSUSED */
 2580 static int
 2581 nfs_fsync(struct vop_fsync_args *ap)
 2582 {
 2583 
 2584         return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_td, 1));
 2585 }
 2586 
 2587 /*
 2588  * Flush all the blocks associated with a vnode.
 2589  *      Walk through the buffer pool and push any dirty pages
 2590  *      associated with the vnode.
 2591  */
 2592 static int
 2593 nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct thread *td,
 2594     int commit)
 2595 {
 2596         struct nfsnode *np = VTONFS(vp);
 2597         struct buf *bp;
 2598         int i;
 2599         struct buf *nbp;
 2600         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 2601         int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
 2602         int passone = 1;
 2603         u_quad_t off, endoff, toff;
 2604         struct ucred* wcred = NULL;
 2605         struct buf **bvec = NULL;
 2606 #ifndef NFS_COMMITBVECSIZ
 2607 #define NFS_COMMITBVECSIZ       20
 2608 #endif
 2609         struct buf *bvec_on_stack[NFS_COMMITBVECSIZ];
 2610         int bvecsize = 0, bveccount;
 2611 
 2612         if (nmp->nm_flag & NFSMNT_INT)
 2613                 slpflag = PCATCH;
 2614         if (!commit)
 2615                 passone = 0;
 2616         /*
 2617          * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
 2618          * server, but nas not been committed to stable storage on the server
 2619          * yet. On the first pass, the byte range is worked out and the commit
 2620          * rpc is done. On the second pass, nfs_writebp() is called to do the
 2621          * job.
 2622          */
 2623 again:
 2624         off = (u_quad_t)-1;
 2625         endoff = 0;
 2626         bvecpos = 0;
 2627         if (NFS_ISV3(vp) && commit) {
 2628                 s = splbio();
 2629                 if (bvec != NULL && bvec != bvec_on_stack)
 2630                         free(bvec, M_TEMP);
 2631                 /*
 2632                  * Count up how many buffers waiting for a commit.
 2633                  */
 2634                 bveccount = 0;
 2635                 VI_LOCK(vp);
 2636                 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
 2637                         nbp = TAILQ_NEXT(bp, b_vnbufs);
 2638                         if (BUF_REFCNT(bp) == 0 &&
 2639                             (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT))
 2640                                 == (B_DELWRI | B_NEEDCOMMIT))
 2641                                 bveccount++;
 2642                 }
 2643                 /*
 2644                  * Allocate space to remember the list of bufs to commit.  It is
 2645                  * important to use M_NOWAIT here to avoid a race with nfs_write.
 2646                  * If we can't get memory (for whatever reason), we will end up
 2647                  * committing the buffers one-by-one in the loop below.
 2648                  */
 2649                 if (bveccount > NFS_COMMITBVECSIZ) {
 2650                         /*
 2651                          * Release the vnode interlock to avoid a lock
 2652                          * order reversal.
 2653                          */
 2654                         VI_UNLOCK(vp);
 2655                         bvec = (struct buf **)
 2656                                 malloc(bveccount * sizeof(struct buf *),
 2657                                        M_TEMP, M_NOWAIT);
 2658                         VI_LOCK(vp);
 2659                         if (bvec == NULL) {
 2660                                 bvec = bvec_on_stack;
 2661                                 bvecsize = NFS_COMMITBVECSIZ;
 2662                         } else
 2663                                 bvecsize = bveccount;
 2664                 } else {
 2665                         bvec = bvec_on_stack;
 2666                         bvecsize = NFS_COMMITBVECSIZ;
 2667                 }
 2668                 for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
 2669                         if (bvecpos >= bvecsize)
 2670                                 break;
 2671                         if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
 2672                                 nbp = TAILQ_NEXT(bp, b_vnbufs);
 2673                                 continue;
 2674                         }
 2675                         if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) !=
 2676                             (B_DELWRI | B_NEEDCOMMIT)) {
 2677                                 BUF_UNLOCK(bp);
 2678                                 nbp = TAILQ_NEXT(bp, b_vnbufs);
 2679                                 continue;
 2680                         }
 2681                         VI_UNLOCK(vp);
 2682                         bremfree(bp);
 2683                         /*
 2684                          * Work out if all buffers are using the same cred
 2685                          * so we can deal with them all with one commit.
 2686                          *
 2687                          * NOTE: we are not clearing B_DONE here, so we have
 2688                          * to do it later on in this routine if we intend to
 2689                          * initiate I/O on the bp.
 2690                          *
 2691                          * Note: to avoid loopback deadlocks, we do not
 2692                          * assign b_runningbufspace.
 2693                          */
 2694                         if (wcred == NULL)
 2695                                 wcred = bp->b_wcred;
 2696                         else if (wcred != bp->b_wcred)
 2697                                 wcred = NOCRED;
 2698                         bp->b_flags |= B_WRITEINPROG;
 2699                         vfs_busy_pages(bp, 1);
 2700 
 2701                         VI_LOCK(vp);
 2702                         /*
 2703                          * bp is protected by being locked, but nbp is not
 2704                          * and vfs_busy_pages() may sleep.  We have to
 2705                          * recalculate nbp.
 2706                          */
 2707                         nbp = TAILQ_NEXT(bp, b_vnbufs);
 2708 
 2709                         /*
 2710                          * A list of these buffers is kept so that the
 2711                          * second loop knows which buffers have actually
 2712                          * been committed. This is necessary, since there
 2713                          * may be a race between the commit rpc and new
 2714                          * uncommitted writes on the file.
 2715                          */
 2716                         bvec[bvecpos++] = bp;
 2717                         toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
 2718                                 bp->b_dirtyoff;
 2719                         if (toff < off)
 2720                                 off = toff;
 2721                         toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
 2722                         if (toff > endoff)
 2723                                 endoff = toff;
 2724                 }
 2725                 splx(s);
 2726                 VI_UNLOCK(vp);
 2727         }
 2728         if (bvecpos > 0) {
 2729                 /*
 2730                  * Commit data on the server, as required.
 2731                  * If all bufs are using the same wcred, then use that with
 2732                  * one call for all of them, otherwise commit each one
 2733                  * separately.
 2734                  */
 2735                 if (wcred != NOCRED)
 2736                         retv = nfs_commit(vp, off, (int)(endoff - off),
 2737                                           wcred, td);
 2738                 else {
 2739                         retv = 0;
 2740                         for (i = 0; i < bvecpos; i++) {
 2741                                 off_t off, size;
 2742                                 bp = bvec[i];
 2743                                 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
 2744                                         bp->b_dirtyoff;
 2745                                 size = (u_quad_t)(bp->b_dirtyend
 2746                                                   - bp->b_dirtyoff);
 2747                                 retv = nfs_commit(vp, off, (int)size,
 2748                                                   bp->b_wcred, td);
 2749                                 if (retv) break;
 2750                         }
 2751                 }
 2752 
 2753                 if (retv == NFSERR_STALEWRITEVERF)
 2754                         nfs_clearcommit(vp->v_mount);
 2755 
 2756                 /*
 2757                  * Now, either mark the blocks I/O done or mark the
 2758                  * blocks dirty, depending on whether the commit
 2759                  * succeeded.
 2760                  */
 2761                 for (i = 0; i < bvecpos; i++) {
 2762                         bp = bvec[i];
 2763                         bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG | B_CLUSTEROK);
 2764                         if (retv) {
 2765                                 /*
 2766                                  * Error, leave B_DELWRI intact
 2767                                  */
 2768                                 vfs_unbusy_pages(bp);
 2769                                 brelse(bp);
 2770                         } else {
 2771                                 /*
 2772                                  * Success, remove B_DELWRI ( bundirty() ).
 2773                                  *
 2774                                  * b_dirtyoff/b_dirtyend seem to be NFS
 2775                                  * specific.  We should probably move that
 2776                                  * into bundirty(). XXX
 2777                                  */
 2778                                 s = splbio();
 2779                                 VI_LOCK(vp);
 2780                                 vp->v_numoutput++;
 2781                                 VI_UNLOCK(vp);
 2782                                 bp->b_flags |= B_ASYNC;
 2783                                 bundirty(bp);
 2784                                 bp->b_flags &= ~B_DONE;
 2785                                 bp->b_ioflags &= ~BIO_ERROR;
 2786                                 bp->b_dirtyoff = bp->b_dirtyend = 0;
 2787                                 splx(s);
 2788                                 bufdone(bp);
 2789                         }
 2790                 }
 2791         }
 2792 
 2793         /*
 2794          * Start/do any write(s) that are required.
 2795          */
 2796 loop:
 2797         s = splbio();
 2798         VI_LOCK(vp);
 2799         for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
 2800                 nbp = TAILQ_NEXT(bp, b_vnbufs);
 2801                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
 2802                         if (waitfor != MNT_WAIT || passone)
 2803                                 continue;
 2804 
 2805                         error = BUF_TIMELOCK(bp,
 2806                             LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
 2807                             VI_MTX(vp), "nfsfsync", slpflag, slptimeo);
 2808                         splx(s);
 2809                         if (error == 0)
 2810                                 panic("nfs_fsync: inconsistent lock");
 2811                         if (error == ENOLCK)
 2812                                 goto loop;
 2813                         if (nfs_sigintr(nmp, NULL, td)) {
 2814                                 error = EINTR;
 2815                                 goto done;
 2816                         }
 2817                         if (slpflag == PCATCH) {
 2818                                 slpflag = 0;
 2819                                 slptimeo = 2 * hz;
 2820                         }
 2821                         goto loop;
 2822                 }
 2823                 if ((bp->b_flags & B_DELWRI) == 0)
 2824                         panic("nfs_fsync: not dirty");
 2825                 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) {
 2826                         BUF_UNLOCK(bp);
 2827                         continue;
 2828                 }
 2829                 VI_UNLOCK(vp);
 2830                 bremfree(bp);
 2831                 if (passone || !commit)
 2832                     bp->b_flags |= B_ASYNC;
 2833                 else
 2834                     bp->b_flags |= B_ASYNC | B_WRITEINPROG;
 2835                 splx(s);
 2836                 BUF_WRITE(bp);
 2837                 goto loop;
 2838         }
 2839         splx(s);
 2840         if (passone) {
 2841                 passone = 0;
 2842                 VI_UNLOCK(vp);
 2843                 goto again;
 2844         }
 2845         if (waitfor == MNT_WAIT) {
 2846                 while (vp->v_numoutput) {
 2847                         vp->v_iflag |= VI_BWAIT;
 2848                         error = msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp),
 2849                                 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo);
 2850                         if (error) {
 2851                             VI_UNLOCK(vp);
 2852                             if (nfs_sigintr(nmp, NULL, td)) {
 2853                                 error = EINTR;
 2854                                 goto done;
 2855                             }
 2856                             if (slpflag == PCATCH) {
 2857                                 slpflag = 0;
 2858                                 slptimeo = 2 * hz;
 2859                             }
 2860                             VI_LOCK(vp);
 2861                         }
 2862                 }
 2863                 if (!TAILQ_EMPTY(&vp->v_dirtyblkhd) && commit) {
 2864                         VI_UNLOCK(vp);
 2865                         goto loop;
 2866                 }
 2867         }
 2868         VI_UNLOCK(vp);
 2869         if (np->n_flag & NWRITEERR) {
 2870                 error = np->n_error;
 2871                 np->n_flag &= ~NWRITEERR;
 2872         }
 2873 done:
 2874         if (bvec != NULL && bvec != bvec_on_stack)
 2875                 free(bvec, M_TEMP);
 2876         return (error);
 2877 }
 2878 
 2879 /*
 2880  * NFS advisory byte-level locks.
 2881  */
 2882 static int
 2883 nfs_advlock(struct vop_advlock_args *ap)
 2884 {
 2885 
 2886         if ((VFSTONFS(ap->a_vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
 2887                 struct nfsnode *np = VTONFS(ap->a_vp);
 2888 
 2889                 return (lf_advlock(ap, &(np->n_lockf), np->n_size));
 2890         }
 2891         return (nfs_dolock(ap));
 2892 }
 2893 
 2894 /*
 2895  * Print out the contents of an nfsnode.
 2896  */
 2897 static int
 2898 nfs_print(struct vop_print_args *ap)
 2899 {
 2900         struct vnode *vp = ap->a_vp;
 2901         struct nfsnode *np = VTONFS(vp);
 2902 
 2903         printf("\tfileid %ld fsid 0x%x",
 2904            np->n_vattr.va_fileid, np->n_vattr.va_fsid);
 2905         if (vp->v_type == VFIFO)
 2906                 fifo_printinfo(vp);
 2907         printf("\n");
 2908         return (0);
 2909 }
 2910 
 2911 /*
 2912  * This is the "real" nfs::bwrite(struct buf*).
 2913  * B_WRITEINPROG isn't set unless the force flag is one and it
 2914  * handles the B_NEEDCOMMIT flag.
 2915  * We set B_CACHE if this is a VMIO buffer.
 2916  */
 2917 int
 2918 nfs_writebp(struct buf *bp, int force, struct thread *td)
 2919 {
 2920         int s;
 2921         int oldflags = bp->b_flags;
 2922 #if 0
 2923         int retv = 1;
 2924         off_t off;
 2925 #endif
 2926 
 2927         if (BUF_REFCNT(bp) == 0)
 2928                 panic("bwrite: buffer is not locked???");
 2929 
 2930         if (bp->b_flags & B_INVAL) {
 2931                 brelse(bp);
 2932                 return(0);
 2933         }
 2934 
 2935         bp->b_flags |= B_CACHE;
 2936 
 2937         /*
 2938          * Undirty the bp.  We will redirty it later if the I/O fails.
 2939          */
 2940 
 2941         s = splbio();
 2942         bundirty(bp);
 2943         bp->b_flags &= ~B_DONE;
 2944         bp->b_ioflags &= ~BIO_ERROR;
 2945         bp->b_iocmd = BIO_WRITE;
 2946 
 2947         VI_LOCK(bp->b_vp);
 2948         bp->b_vp->v_numoutput++;
 2949         VI_UNLOCK(bp->b_vp);
 2950         curthread->td_proc->p_stats->p_ru.ru_oublock++;
 2951         splx(s);
 2952 
 2953         /*
 2954          * Note: to avoid loopback deadlocks, we do not
 2955          * assign b_runningbufspace.
 2956          */
 2957         vfs_busy_pages(bp, 1);
 2958 
 2959         if (force)
 2960                 bp->b_flags |= B_WRITEINPROG;
 2961         BUF_KERNPROC(bp);
 2962         VOP_STRATEGY(bp->b_vp, bp);
 2963 
 2964         if( (oldflags & B_ASYNC) == 0) {
 2965                 int rtval = bufwait(bp);
 2966 
 2967                 if (oldflags & B_DELWRI) {
 2968                         s = splbio();
 2969                         reassignbuf(bp, bp->b_vp);
 2970                         splx(s);
 2971                 }
 2972 
 2973                 brelse(bp);
 2974                 return (rtval);
 2975         }
 2976 
 2977         return (0);
 2978 }
 2979 
 2980 /*
 2981  * nfs special file access vnode op.
 2982  * Essentially just get vattr and then imitate iaccess() since the device is
 2983  * local to the client.
 2984  */
 2985 static int
 2986 nfsspec_access(struct vop_access_args *ap)
 2987 {
 2988         struct vattr *vap;
 2989         struct ucred *cred = ap->a_cred;
 2990         struct vnode *vp = ap->a_vp;
 2991         mode_t mode = ap->a_mode;
 2992         struct vattr vattr;
 2993         int error;
 2994 
 2995         /*
 2996          * Disallow write attempts on filesystems mounted read-only;
 2997          * unless the file is a socket, fifo, or a block or character
 2998          * device resident on the filesystem.
 2999          */
 3000         if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
 3001                 switch (vp->v_type) {
 3002                 case VREG:
 3003                 case VDIR:
 3004                 case VLNK:
 3005                         return (EROFS);
 3006                 default:
 3007                         break;
 3008                 }
 3009         }
 3010         vap = &vattr;
 3011         error = VOP_GETATTR(vp, vap, cred, ap->a_td);
 3012         if (error)
 3013                 return (error);
 3014         return (vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid,
 3015             mode, cred, NULL));
 3016 }
 3017 
 3018 /*
 3019  * Read wrapper for special devices.
 3020  */
 3021 static int
 3022 nfsspec_read(struct vop_read_args *ap)
 3023 {
 3024         struct nfsnode *np = VTONFS(ap->a_vp);
 3025 
 3026         /*
 3027          * Set access flag.
 3028          */
 3029         np->n_flag |= NACC;
 3030         getnanotime(&np->n_atim);
 3031         return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
 3032 }
 3033 
 3034 /*
 3035  * Write wrapper for special devices.
 3036  */
 3037 static int
 3038 nfsspec_write(struct vop_write_args *ap)
 3039 {
 3040         struct nfsnode *np = VTONFS(ap->a_vp);
 3041 
 3042         /*
 3043          * Set update flag.
 3044          */
 3045         np->n_flag |= NUPD;
 3046         getnanotime(&np->n_mtim);
 3047         return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
 3048 }
 3049 
 3050 /*
 3051  * Close wrapper for special devices.
 3052  *
 3053  * Update the times on the nfsnode then do device close.
 3054  */
 3055 static int
 3056 nfsspec_close(struct vop_close_args *ap)
 3057 {
 3058         struct vnode *vp = ap->a_vp;
 3059         struct nfsnode *np = VTONFS(vp);
 3060         struct vattr vattr;
 3061 
 3062         if (np->n_flag & (NACC | NUPD)) {
 3063                 np->n_flag |= NCHG;
 3064                 if (vrefcnt(vp) == 1 &&
 3065                     (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
 3066                         VATTR_NULL(&vattr);
 3067                         if (np->n_flag & NACC)
 3068                                 vattr.va_atime = np->n_atim;
 3069                         if (np->n_flag & NUPD)
 3070                                 vattr.va_mtime = np->n_mtim;
 3071                         (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_td);
 3072                 }
 3073         }
 3074         return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
 3075 }
 3076 
 3077 /*
 3078  * Read wrapper for fifos.
 3079  */
 3080 static int
 3081 nfsfifo_read(struct vop_read_args *ap)
 3082 {
 3083         struct nfsnode *np = VTONFS(ap->a_vp);
 3084 
 3085         /*
 3086          * Set access flag.
 3087          */
 3088         np->n_flag |= NACC;
 3089         getnanotime(&np->n_atim);
 3090         return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
 3091 }
 3092 
 3093 /*
 3094  * Write wrapper for fifos.
 3095  */
 3096 static int
 3097 nfsfifo_write(struct vop_write_args *ap)
 3098 {
 3099         struct nfsnode *np = VTONFS(ap->a_vp);
 3100 
 3101         /*
 3102          * Set update flag.
 3103          */
 3104         np->n_flag |= NUPD;
 3105         getnanotime(&np->n_mtim);
 3106         return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
 3107 }
 3108 
 3109 /*
 3110  * Close wrapper for fifos.
 3111  *
 3112  * Update the times on the nfsnode then do fifo close.
 3113  */
 3114 static int
 3115 nfsfifo_close(struct vop_close_args *ap)
 3116 {
 3117         struct vnode *vp = ap->a_vp;
 3118         struct nfsnode *np = VTONFS(vp);
 3119         struct vattr vattr;
 3120         struct timespec ts;
 3121 
 3122         if (np->n_flag & (NACC | NUPD)) {
 3123                 getnanotime(&ts);
 3124                 if (np->n_flag & NACC)
 3125                         np->n_atim = ts;
 3126                 if (np->n_flag & NUPD)
 3127                         np->n_mtim = ts;
 3128                 np->n_flag |= NCHG;
 3129                 if (vrefcnt(vp) == 1 &&
 3130                     (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
 3131                         VATTR_NULL(&vattr);
 3132                         if (np->n_flag & NACC)
 3133                                 vattr.va_atime = np->n_atim;
 3134                         if (np->n_flag & NUPD)
 3135                                 vattr.va_mtime = np->n_mtim;
 3136                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
 3137                         (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_td);
 3138                         VOP_UNLOCK(vp, 0, ap->a_td);
 3139                 }
 3140         }
 3141         return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
 3142 }
 3143 

Cache object: 99f41d3489d3d40a1e46d5c781110b83


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.