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/nfs/nfs_vnops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: nfs_vnops.c,v 1.245.2.1 2007/02/17 23:27:51 tron Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Rick Macklem at The University of Guelph.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)nfs_vnops.c 8.19 (Berkeley) 7/31/95
   35  */
   36 
   37 /*
   38  * vnode op calls for Sun NFS version 2 and 3
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.245.2.1 2007/02/17 23:27:51 tron Exp $");
   43 
   44 #include "opt_inet.h"
   45 #include "opt_nfs.h"
   46 #include "opt_uvmhist.h"
   47 
   48 #include <sys/param.h>
   49 #include <sys/proc.h>
   50 #include <sys/kernel.h>
   51 #include <sys/systm.h>
   52 #include <sys/resourcevar.h>
   53 #include <sys/proc.h>
   54 #include <sys/mount.h>
   55 #include <sys/buf.h>
   56 #include <sys/disk.h>
   57 #include <sys/malloc.h>
   58 #include <sys/mbuf.h>
   59 #include <sys/namei.h>
   60 #include <sys/vnode.h>
   61 #include <sys/dirent.h>
   62 #include <sys/fcntl.h>
   63 #include <sys/hash.h>
   64 #include <sys/lockf.h>
   65 #include <sys/stat.h>
   66 #include <sys/unistd.h>
   67 #include <sys/kauth.h>
   68 
   69 #include <uvm/uvm_extern.h>
   70 #include <uvm/uvm.h>
   71 
   72 #include <miscfs/fifofs/fifo.h>
   73 #include <miscfs/genfs/genfs.h>
   74 #include <miscfs/genfs/genfs_node.h>
   75 #include <miscfs/specfs/specdev.h>
   76 
   77 #include <nfs/rpcv2.h>
   78 #include <nfs/nfsproto.h>
   79 #include <nfs/nfs.h>
   80 #include <nfs/nfsnode.h>
   81 #include <nfs/nfsmount.h>
   82 #include <nfs/xdr_subs.h>
   83 #include <nfs/nfsm_subs.h>
   84 #include <nfs/nqnfs.h>
   85 #include <nfs/nfs_var.h>
   86 
   87 #include <net/if.h>
   88 #include <netinet/in.h>
   89 #include <netinet/in_var.h>
   90 
   91 /*
   92  * Global vfs data structures for nfs
   93  */
   94 int (**nfsv2_vnodeop_p) __P((void *));
   95 const struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
   96         { &vop_default_desc, vn_default_error },
   97         { &vop_lookup_desc, nfs_lookup },               /* lookup */
   98         { &vop_create_desc, nfs_create },               /* create */
   99         { &vop_mknod_desc, nfs_mknod },                 /* mknod */
  100         { &vop_open_desc, nfs_open },                   /* open */
  101         { &vop_close_desc, nfs_close },                 /* close */
  102         { &vop_access_desc, nfs_access },               /* access */
  103         { &vop_getattr_desc, nfs_getattr },             /* getattr */
  104         { &vop_setattr_desc, nfs_setattr },             /* setattr */
  105         { &vop_read_desc, nfs_read },                   /* read */
  106         { &vop_write_desc, nfs_write },                 /* write */
  107         { &vop_lease_desc, nfs_lease_check },           /* lease */
  108         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  109         { &vop_ioctl_desc, nfs_ioctl },                 /* ioctl */
  110         { &vop_poll_desc, nfs_poll },                   /* poll */
  111         { &vop_kqfilter_desc, nfs_kqfilter },           /* kqfilter */
  112         { &vop_revoke_desc, nfs_revoke },               /* revoke */
  113         { &vop_mmap_desc, nfs_mmap },                   /* mmap */
  114         { &vop_fsync_desc, nfs_fsync },                 /* fsync */
  115         { &vop_seek_desc, nfs_seek },                   /* seek */
  116         { &vop_remove_desc, nfs_remove },               /* remove */
  117         { &vop_link_desc, nfs_link },                   /* link */
  118         { &vop_rename_desc, nfs_rename },               /* rename */
  119         { &vop_mkdir_desc, nfs_mkdir },                 /* mkdir */
  120         { &vop_rmdir_desc, nfs_rmdir },                 /* rmdir */
  121         { &vop_symlink_desc, nfs_symlink },             /* symlink */
  122         { &vop_readdir_desc, nfs_readdir },             /* readdir */
  123         { &vop_readlink_desc, nfs_readlink },           /* readlink */
  124         { &vop_abortop_desc, nfs_abortop },             /* abortop */
  125         { &vop_inactive_desc, nfs_inactive },           /* inactive */
  126         { &vop_reclaim_desc, nfs_reclaim },             /* reclaim */
  127         { &vop_lock_desc, nfs_lock },                   /* lock */
  128         { &vop_unlock_desc, nfs_unlock },               /* unlock */
  129         { &vop_bmap_desc, nfs_bmap },                   /* bmap */
  130         { &vop_strategy_desc, nfs_strategy },           /* strategy */
  131         { &vop_print_desc, nfs_print },                 /* print */
  132         { &vop_islocked_desc, nfs_islocked },           /* islocked */
  133         { &vop_pathconf_desc, nfs_pathconf },           /* pathconf */
  134         { &vop_advlock_desc, nfs_advlock },             /* advlock */
  135         { &vop_bwrite_desc, genfs_badop },              /* bwrite */
  136         { &vop_getpages_desc, nfs_getpages },           /* getpages */
  137         { &vop_putpages_desc, genfs_putpages },         /* putpages */
  138         { NULL, NULL }
  139 };
  140 const struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
  141         { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
  142 
  143 /*
  144  * Special device vnode ops
  145  */
  146 int (**spec_nfsv2nodeop_p) __P((void *));
  147 const struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = {
  148         { &vop_default_desc, vn_default_error },
  149         { &vop_lookup_desc, spec_lookup },              /* lookup */
  150         { &vop_create_desc, spec_create },              /* create */
  151         { &vop_mknod_desc, spec_mknod },                /* mknod */
  152         { &vop_open_desc, spec_open },                  /* open */
  153         { &vop_close_desc, nfsspec_close },             /* close */
  154         { &vop_access_desc, nfsspec_access },           /* access */
  155         { &vop_getattr_desc, nfs_getattr },             /* getattr */
  156         { &vop_setattr_desc, nfs_setattr },             /* setattr */
  157         { &vop_read_desc, nfsspec_read },               /* read */
  158         { &vop_write_desc, nfsspec_write },             /* write */
  159         { &vop_lease_desc, spec_lease_check },          /* lease */
  160         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  161         { &vop_ioctl_desc, spec_ioctl },                /* ioctl */
  162         { &vop_poll_desc, spec_poll },                  /* poll */
  163         { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
  164         { &vop_revoke_desc, spec_revoke },              /* revoke */
  165         { &vop_mmap_desc, spec_mmap },                  /* mmap */
  166         { &vop_fsync_desc, spec_fsync },                /* fsync */
  167         { &vop_seek_desc, spec_seek },                  /* seek */
  168         { &vop_remove_desc, spec_remove },              /* remove */
  169         { &vop_link_desc, spec_link },                  /* link */
  170         { &vop_rename_desc, spec_rename },              /* rename */
  171         { &vop_mkdir_desc, spec_mkdir },                /* mkdir */
  172         { &vop_rmdir_desc, spec_rmdir },                /* rmdir */
  173         { &vop_symlink_desc, spec_symlink },            /* symlink */
  174         { &vop_readdir_desc, spec_readdir },            /* readdir */
  175         { &vop_readlink_desc, spec_readlink },          /* readlink */
  176         { &vop_abortop_desc, spec_abortop },            /* abortop */
  177         { &vop_inactive_desc, nfs_inactive },           /* inactive */
  178         { &vop_reclaim_desc, nfs_reclaim },             /* reclaim */
  179         { &vop_lock_desc, nfs_lock },                   /* lock */
  180         { &vop_unlock_desc, nfs_unlock },               /* unlock */
  181         { &vop_bmap_desc, spec_bmap },                  /* bmap */
  182         { &vop_strategy_desc, spec_strategy },          /* strategy */
  183         { &vop_print_desc, nfs_print },                 /* print */
  184         { &vop_islocked_desc, nfs_islocked },           /* islocked */
  185         { &vop_pathconf_desc, spec_pathconf },          /* pathconf */
  186         { &vop_advlock_desc, spec_advlock },            /* advlock */
  187         { &vop_bwrite_desc, spec_bwrite },              /* bwrite */
  188         { &vop_getpages_desc, spec_getpages },          /* getpages */
  189         { &vop_putpages_desc, spec_putpages },          /* putpages */
  190         { NULL, NULL }
  191 };
  192 const struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
  193         { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries };
  194 
  195 int (**fifo_nfsv2nodeop_p) __P((void *));
  196 const struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = {
  197         { &vop_default_desc, vn_default_error },
  198         { &vop_lookup_desc, fifo_lookup },              /* lookup */
  199         { &vop_create_desc, fifo_create },              /* create */
  200         { &vop_mknod_desc, fifo_mknod },                /* mknod */
  201         { &vop_open_desc, fifo_open },                  /* open */
  202         { &vop_close_desc, nfsfifo_close },             /* close */
  203         { &vop_access_desc, nfsspec_access },           /* access */
  204         { &vop_getattr_desc, nfs_getattr },             /* getattr */
  205         { &vop_setattr_desc, nfs_setattr },             /* setattr */
  206         { &vop_read_desc, nfsfifo_read },               /* read */
  207         { &vop_write_desc, nfsfifo_write },             /* write */
  208         { &vop_lease_desc, fifo_lease_check },          /* lease */
  209         { &vop_fcntl_desc, genfs_fcntl },               /* fcntl */
  210         { &vop_ioctl_desc, fifo_ioctl },                /* ioctl */
  211         { &vop_poll_desc, fifo_poll },                  /* poll */
  212         { &vop_kqfilter_desc, fifo_kqfilter },          /* kqfilter */
  213         { &vop_revoke_desc, fifo_revoke },              /* revoke */
  214         { &vop_mmap_desc, fifo_mmap },                  /* mmap */
  215         { &vop_fsync_desc, nfs_fsync },                 /* fsync */
  216         { &vop_seek_desc, fifo_seek },                  /* seek */
  217         { &vop_remove_desc, fifo_remove },              /* remove */
  218         { &vop_link_desc, fifo_link },                  /* link */
  219         { &vop_rename_desc, fifo_rename },              /* rename */
  220         { &vop_mkdir_desc, fifo_mkdir },                /* mkdir */
  221         { &vop_rmdir_desc, fifo_rmdir },                /* rmdir */
  222         { &vop_symlink_desc, fifo_symlink },            /* symlink */
  223         { &vop_readdir_desc, fifo_readdir },            /* readdir */
  224         { &vop_readlink_desc, fifo_readlink },          /* readlink */
  225         { &vop_abortop_desc, fifo_abortop },            /* abortop */
  226         { &vop_inactive_desc, nfs_inactive },           /* inactive */
  227         { &vop_reclaim_desc, nfs_reclaim },             /* reclaim */
  228         { &vop_lock_desc, nfs_lock },                   /* lock */
  229         { &vop_unlock_desc, nfs_unlock },               /* unlock */
  230         { &vop_bmap_desc, fifo_bmap },                  /* bmap */
  231         { &vop_strategy_desc, genfs_badop },            /* strategy */
  232         { &vop_print_desc, nfs_print },                 /* print */
  233         { &vop_islocked_desc, nfs_islocked },           /* islocked */
  234         { &vop_pathconf_desc, fifo_pathconf },          /* pathconf */
  235         { &vop_advlock_desc, fifo_advlock },            /* advlock */
  236         { &vop_bwrite_desc, genfs_badop },              /* bwrite */
  237         { &vop_putpages_desc, fifo_putpages },          /* putpages */
  238         { NULL, NULL }
  239 };
  240 const struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
  241         { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };
  242 
  243 static int nfs_linkrpc(struct vnode *, struct vnode *, const char *,
  244     size_t, kauth_cred_t, struct lwp *);
  245 static void nfs_writerpc_extfree(struct mbuf *, caddr_t, size_t, void *);
  246 
  247 /*
  248  * Global variables
  249  */
  250 extern u_int32_t nfs_true, nfs_false;
  251 extern u_int32_t nfs_xdrneg1;
  252 extern const nfstype nfsv3_type[9];
  253 
  254 int nfs_numasync = 0;
  255 #define DIRHDSIZ        _DIRENT_NAMEOFF(dp)
  256 #define UIO_ADVANCE(uio, siz) \
  257     (void)((uio)->uio_resid -= (siz), \
  258     (uio)->uio_iov->iov_base = (char *)(uio)->uio_iov->iov_base + (siz), \
  259     (uio)->uio_iov->iov_len -= (siz))
  260 
  261 static void nfs_cache_enter(struct vnode *, struct vnode *,
  262     struct componentname *);
  263 
  264 static void
  265 nfs_cache_enter(struct vnode *dvp, struct vnode *vp,
  266     struct componentname *cnp)
  267 {
  268         struct nfsnode *dnp = VTONFS(dvp);
  269 
  270         if (vp != NULL) {
  271                 struct nfsnode *np = VTONFS(vp);
  272 
  273                 np->n_ctime = np->n_vattr->va_ctime.tv_sec;
  274         }
  275 
  276         if (!timespecisset(&dnp->n_nctime))
  277                 dnp->n_nctime = dnp->n_vattr->va_mtime;
  278 
  279         cache_enter(dvp, vp, cnp);
  280 }
  281 
  282 /*
  283  * nfs null call from vfs.
  284  */
  285 int
  286 nfs_null(vp, cred, l)
  287         struct vnode *vp;
  288         kauth_cred_t cred;
  289         struct lwp *l;
  290 {
  291         caddr_t bpos, dpos;
  292         int error = 0;
  293         struct mbuf *mreq, *mrep, *md, *mb;
  294         struct nfsnode *np = VTONFS(vp);
  295 
  296         nfsm_reqhead(np, NFSPROC_NULL, 0);
  297         nfsm_request(np, NFSPROC_NULL, l, cred);
  298         nfsm_reqdone;
  299         return (error);
  300 }
  301 
  302 /*
  303  * nfs access vnode op.
  304  * For nfs version 2, just return ok. File accesses may fail later.
  305  * For nfs version 3, use the access rpc to check accessibility. If file modes
  306  * are changed on the server, accesses might still fail later.
  307  */
  308 int
  309 nfs_access(v)
  310         void *v;
  311 {
  312         struct vop_access_args /* {
  313                 struct vnode *a_vp;
  314                 int  a_mode;
  315                 kauth_cred_t a_cred;
  316                 struct lwp *a_l;
  317         } */ *ap = v;
  318         struct vnode *vp = ap->a_vp;
  319 #ifndef NFS_V2_ONLY
  320         u_int32_t *tl;
  321         caddr_t cp;
  322         int32_t t1, t2;
  323         caddr_t bpos, dpos, cp2;
  324         int error = 0, attrflag;
  325         struct mbuf *mreq, *mrep, *md, *mb;
  326         u_int32_t mode, rmode;
  327         const int v3 = NFS_ISV3(vp);
  328 #endif
  329         int cachevalid;
  330         struct nfsnode *np = VTONFS(vp);
  331         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
  332 
  333         cachevalid = (np->n_accstamp != -1 &&
  334             (time_uptime - np->n_accstamp) < NFS_ATTRTIMEO(nmp, np) &&
  335             np->n_accuid == kauth_cred_geteuid(ap->a_cred));
  336 
  337         /*
  338          * Check access cache first. If this request has been made for this
  339          * uid shortly before, use the cached result.
  340          */
  341         if (cachevalid) {
  342                 if (!np->n_accerror) {
  343                         if  ((np->n_accmode & ap->a_mode) == ap->a_mode)
  344                                 return np->n_accerror;
  345                 } else if ((np->n_accmode & ap->a_mode) == np->n_accmode)
  346                         return np->n_accerror;
  347         }
  348 
  349 #ifndef NFS_V2_ONLY
  350         /*
  351          * For nfs v3, do an access rpc, otherwise you are stuck emulating
  352          * ufs_access() locally using the vattr. This may not be correct,
  353          * since the server may apply other access criteria such as
  354          * client uid-->server uid mapping that we do not know about, but
  355          * this is better than just returning anything that is lying about
  356          * in the cache.
  357          */
  358         if (v3) {
  359                 nfsstats.rpccnt[NFSPROC_ACCESS]++;
  360                 nfsm_reqhead(np, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
  361                 nfsm_fhtom(np, v3);
  362                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
  363                 if (ap->a_mode & VREAD)
  364                         mode = NFSV3ACCESS_READ;
  365                 else
  366                         mode = 0;
  367                 if (vp->v_type != VDIR) {
  368                         if (ap->a_mode & VWRITE)
  369                                 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
  370                         if (ap->a_mode & VEXEC)
  371                                 mode |= NFSV3ACCESS_EXECUTE;
  372                 } else {
  373                         if (ap->a_mode & VWRITE)
  374                                 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
  375                                          NFSV3ACCESS_DELETE);
  376                         if (ap->a_mode & VEXEC)
  377                                 mode |= NFSV3ACCESS_LOOKUP;
  378                 }
  379                 *tl = txdr_unsigned(mode);
  380                 nfsm_request(np, NFSPROC_ACCESS, ap->a_l, ap->a_cred);
  381                 nfsm_postop_attr(vp, attrflag, 0);
  382                 if (!error) {
  383                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
  384                         rmode = fxdr_unsigned(u_int32_t, *tl);
  385                         /*
  386                          * The NFS V3 spec does not clarify whether or not
  387                          * the returned access bits can be a superset of
  388                          * the ones requested, so...
  389                          */
  390                         if ((rmode & mode) != mode)
  391                                 error = EACCES;
  392                 }
  393                 nfsm_reqdone;
  394         } else
  395 #endif
  396                 return (nfsspec_access(ap));
  397 #ifndef NFS_V2_ONLY
  398         /*
  399          * Disallow write attempts on filesystems mounted read-only;
  400          * unless the file is a socket, fifo, or a block or character
  401          * device resident on the filesystem.
  402          */
  403         if (!error && (ap->a_mode & VWRITE) &&
  404             (vp->v_mount->mnt_flag & MNT_RDONLY)) {
  405                 switch (vp->v_type) {
  406                 case VREG:
  407                 case VDIR:
  408                 case VLNK:
  409                         error = EROFS;
  410                 default:
  411                         break;
  412                 }
  413         }
  414 
  415         if (!error || error == EACCES) {
  416                 /*
  417                  * If we got the same result as for a previous,
  418                  * different request, OR it in. Don't update
  419                  * the timestamp in that case.
  420                  */
  421                 if (cachevalid && np->n_accstamp != -1 &&
  422                     error == np->n_accerror) {
  423                         if (!error)
  424                                 np->n_accmode |= ap->a_mode;
  425                         else if ((np->n_accmode & ap->a_mode) == ap->a_mode)
  426                                 np->n_accmode = ap->a_mode;
  427                 } else {
  428                         np->n_accstamp = time_uptime;
  429                         np->n_accuid = kauth_cred_geteuid(ap->a_cred);
  430                         np->n_accmode = ap->a_mode;
  431                         np->n_accerror = error;
  432                 }
  433         }
  434 
  435         return (error);
  436 #endif
  437 }
  438 
  439 /*
  440  * nfs open vnode op
  441  * Check to see if the type is ok
  442  * and that deletion is not in progress.
  443  * For paged in text files, you will need to flush the page cache
  444  * if consistency is lost.
  445  */
  446 /* ARGSUSED */
  447 int
  448 nfs_open(v)
  449         void *v;
  450 {
  451         struct vop_open_args /* {
  452                 struct vnode *a_vp;
  453                 int  a_mode;
  454                 kauth_cred_t a_cred;
  455                 struct lwp *a_l;
  456         } */ *ap = v;
  457         struct vnode *vp = ap->a_vp;
  458         struct nfsnode *np = VTONFS(vp);
  459         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
  460         int error;
  461 
  462         if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
  463                 return (EACCES);
  464         }
  465 
  466         if (ap->a_mode & FREAD) {
  467                 if (np->n_rcred != NULL)
  468                         kauth_cred_free(np->n_rcred);
  469                 np->n_rcred = ap->a_cred;
  470                 kauth_cred_hold(np->n_rcred);
  471         }
  472         if (ap->a_mode & FWRITE) {
  473                 if (np->n_wcred != NULL)
  474                         kauth_cred_free(np->n_wcred);
  475                 np->n_wcred = ap->a_cred;
  476                 kauth_cred_hold(np->n_wcred);
  477         }
  478 
  479 #ifndef NFS_V2_ONLY
  480         /*
  481          * Get a valid lease. If cached data is stale, flush it.
  482          */
  483         if (nmp->nm_flag & NFSMNT_NQNFS) {
  484                 if (NQNFS_CKINVALID(vp, np, ND_READ)) {
  485                     do {
  486                         error = nqnfs_getlease(vp, ND_READ, ap->a_cred,
  487                             ap->a_l);
  488                     } while (error == NQNFS_EXPIRED);
  489                     if (error)
  490                         return (error);
  491                     if (np->n_lrev != np->n_brev ||
  492                         (np->n_flag & NQNFSNONCACHE)) {
  493                         if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
  494                                 ap->a_l, 1)) == EINTR)
  495                                 return (error);
  496                         np->n_brev = np->n_lrev;
  497                     }
  498                 }
  499         } else
  500 #endif
  501         {
  502                 error = nfs_flushstalebuf(vp, ap->a_cred, ap->a_l, 0);
  503                 if (error)
  504                         return error;
  505         }
  506         if ((nmp->nm_flag & NFSMNT_NQNFS) == 0)
  507                 NFS_INVALIDATE_ATTRCACHE(np); /* For Open/Close consistency */
  508         return (0);
  509 }
  510 
  511 /*
  512  * nfs close vnode op
  513  * What an NFS client should do upon close after writing is a debatable issue.
  514  * Most NFS clients push delayed writes to the server upon close, basically for
  515  * two reasons:
  516  * 1 - So that any write errors may be reported back to the client process
  517  *     doing the close system call. By far the two most likely errors are
  518  *     NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
  519  * 2 - To put a worst case upper bound on cache inconsistency between
  520  *     multiple clients for the file.
  521  * There is also a consistency problem for Version 2 of the protocol w.r.t.
  522  * not being able to tell if other clients are writing a file concurrently,
  523  * since there is no way of knowing if the changed modify time in the reply
  524  * is only due to the write for this client.
  525  * (NFS Version 3 provides weak cache consistency data in the reply that
  526  *  should be sufficient to detect and handle this case.)
  527  *
  528  * The current code does the following:
  529  * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
  530  * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
  531  *                     or commit them (this satisfies 1 and 2 except for the
  532  *                     case where the server crashes after this close but
  533  *                     before the commit RPC, which is felt to be "good
  534  *                     enough". Changing the last argument to nfs_flush() to
  535  *                     a 1 would force a commit operation, if it is felt a
  536  *                     commit is necessary now.
  537  * for NQNFS         - do nothing now, since 2 is dealt with via leases and
  538  *                     1 should be dealt with via an fsync() system call for
  539  *                     cases where write errors are important.
  540  */
  541 /* ARGSUSED */
  542 int
  543 nfs_close(v)
  544         void *v;
  545 {
  546         struct vop_close_args /* {
  547                 struct vnodeop_desc *a_desc;
  548                 struct vnode *a_vp;
  549                 int  a_fflag;
  550                 kauth_cred_t a_cred;
  551                 struct lwp *a_l;
  552         } */ *ap = v;
  553         struct vnode *vp = ap->a_vp;
  554         struct nfsnode *np = VTONFS(vp);
  555         int error = 0;
  556         UVMHIST_FUNC("nfs_close"); UVMHIST_CALLED(ubchist);
  557 
  558         if (vp->v_type == VREG) {
  559             if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
  560                 (np->n_flag & NMODIFIED)) {
  561 #ifndef NFS_V2_ONLY
  562                 if (NFS_ISV3(vp)) {
  563                     error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_l, 0);
  564                     np->n_flag &= ~NMODIFIED;
  565                 } else
  566 #endif
  567                     error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_l, 1);
  568                 NFS_INVALIDATE_ATTRCACHE(np);
  569             }
  570             if (np->n_flag & NWRITEERR) {
  571                 np->n_flag &= ~NWRITEERR;
  572                 error = np->n_error;
  573             }
  574         }
  575         UVMHIST_LOG(ubchist, "returning %d", error,0,0,0);
  576         return (error);
  577 }
  578 
  579 /*
  580  * nfs getattr call from vfs.
  581  */
  582 int
  583 nfs_getattr(v)
  584         void *v;
  585 {
  586         struct vop_getattr_args /* {
  587                 struct vnode *a_vp;
  588                 struct vattr *a_vap;
  589                 kauth_cred_t a_cred;
  590                 struct lwp *a_l;
  591         } */ *ap = v;
  592         struct vnode *vp = ap->a_vp;
  593         struct nfsnode *np = VTONFS(vp);
  594         caddr_t cp;
  595         u_int32_t *tl;
  596         int32_t t1, t2;
  597         caddr_t bpos, dpos;
  598         int error = 0;
  599         struct mbuf *mreq, *mrep, *md, *mb;
  600         const int v3 = NFS_ISV3(vp);
  601 
  602         /*
  603          * Update local times for special files.
  604          */
  605         if (np->n_flag & (NACC | NUPD))
  606                 np->n_flag |= NCHG;
  607 
  608         /*
  609          * if we have delayed truncation, do it now.
  610          */
  611         nfs_delayedtruncate(vp);
  612 
  613         /*
  614          * First look in the cache.
  615          */
  616         if (nfs_getattrcache(vp, ap->a_vap) == 0)
  617                 return (0);
  618         nfsstats.rpccnt[NFSPROC_GETATTR]++;
  619         nfsm_reqhead(np, NFSPROC_GETATTR, NFSX_FH(v3));
  620         nfsm_fhtom(np, v3);
  621         nfsm_request(np, NFSPROC_GETATTR, ap->a_l, ap->a_cred);
  622         if (!error) {
  623                 nfsm_loadattr(vp, ap->a_vap, 0);
  624                 if (vp->v_type == VDIR &&
  625                     ap->a_vap->va_blocksize < NFS_DIRFRAGSIZ)
  626                         ap->a_vap->va_blocksize = NFS_DIRFRAGSIZ;
  627         }
  628         nfsm_reqdone;
  629         return (error);
  630 }
  631 
  632 /*
  633  * nfs setattr call.
  634  */
  635 int
  636 nfs_setattr(v)
  637         void *v;
  638 {
  639         struct vop_setattr_args /* {
  640                 struct vnodeop_desc *a_desc;
  641                 struct vnode *a_vp;
  642                 struct vattr *a_vap;
  643                 kauth_cred_t a_cred;
  644                 struct lwp *a_l;
  645         } */ *ap = v;
  646         struct vnode *vp = ap->a_vp;
  647         struct nfsnode *np = VTONFS(vp);
  648         struct vattr *vap = ap->a_vap;
  649         int error = 0;
  650         u_quad_t tsize = 0;
  651 
  652         /*
  653          * Setting of flags is not supported.
  654          */
  655         if (vap->va_flags != VNOVAL)
  656                 return (EOPNOTSUPP);
  657 
  658         /*
  659          * Disallow write attempts if the filesystem is mounted read-only.
  660          */
  661         if ((vap->va_uid != (uid_t)VNOVAL ||
  662             vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
  663             vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
  664             (vp->v_mount->mnt_flag & MNT_RDONLY))
  665                 return (EROFS);
  666         if (vap->va_size != VNOVAL) {
  667                 switch (vp->v_type) {
  668                 case VDIR:
  669                         return (EISDIR);
  670                 case VCHR:
  671                 case VBLK:
  672                 case VSOCK:
  673                 case VFIFO:
  674                         if (vap->va_mtime.tv_sec == VNOVAL &&
  675                             vap->va_atime.tv_sec == VNOVAL &&
  676                             vap->va_mode == (mode_t)VNOVAL &&
  677                             vap->va_uid == (uid_t)VNOVAL &&
  678                             vap->va_gid == (gid_t)VNOVAL)
  679                                 return (0);
  680                         vap->va_size = VNOVAL;
  681                         break;
  682                 default:
  683                         /*
  684                          * Disallow write attempts if the filesystem is
  685                          * mounted read-only.
  686                          */
  687                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
  688                                 return (EROFS);
  689                         genfs_node_wrlock(vp);
  690                         uvm_vnp_setsize(vp, vap->va_size);
  691                         tsize = np->n_size;
  692                         np->n_size = vap->va_size;
  693                         if (vap->va_size == 0)
  694                                 error = nfs_vinvalbuf(vp, 0,
  695                                      ap->a_cred, ap->a_l, 1);
  696                         else
  697                                 error = nfs_vinvalbuf(vp, V_SAVE,
  698                                      ap->a_cred, ap->a_l, 1);
  699                         if (error) {
  700                                 uvm_vnp_setsize(vp, tsize);
  701                                 genfs_node_unlock(vp);
  702                                 return (error);
  703                         }
  704                         np->n_vattr->va_size = vap->va_size;
  705                 }
  706         } else {
  707                 /*
  708                  * flush files before setattr because a later write of
  709                  * cached data might change timestamps or reset sugid bits
  710                  */
  711                 if ((vap->va_mtime.tv_sec != VNOVAL ||
  712                      vap->va_atime.tv_sec != VNOVAL ||
  713                      vap->va_mode != VNOVAL) &&
  714                     vp->v_type == VREG &&
  715                     (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred,
  716                                            ap->a_l, 1)) == EINTR)
  717                         return (error);
  718         }
  719         error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_l);
  720         if (vap->va_size != VNOVAL) {
  721                 if (error) {
  722                         np->n_size = np->n_vattr->va_size = tsize;
  723                         uvm_vnp_setsize(vp, np->n_size);
  724                 }
  725                 genfs_node_unlock(vp);
  726         }
  727         VN_KNOTE(vp, NOTE_ATTRIB);
  728         return (error);
  729 }
  730 
  731 /*
  732  * Do an nfs setattr rpc.
  733  */
  734 int
  735 nfs_setattrrpc(vp, vap, cred, l)
  736         struct vnode *vp;
  737         struct vattr *vap;
  738         kauth_cred_t cred;
  739         struct lwp *l;
  740 {
  741         struct nfsv2_sattr *sp;
  742         caddr_t cp;
  743         int32_t t1, t2;
  744         caddr_t bpos, dpos;
  745         u_int32_t *tl;
  746         int error = 0;
  747         struct mbuf *mreq, *mrep, *md, *mb;
  748         const int v3 = NFS_ISV3(vp);
  749         struct nfsnode *np = VTONFS(vp);
  750 #ifndef NFS_V2_ONLY
  751         int wccflag = NFSV3_WCCRATTR;
  752         caddr_t cp2;
  753 #endif
  754 
  755         nfsstats.rpccnt[NFSPROC_SETATTR]++;
  756         nfsm_reqhead(np, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
  757         nfsm_fhtom(np, v3);
  758 #ifndef NFS_V2_ONLY
  759         if (v3) {
  760                 nfsm_v3attrbuild(vap, TRUE);
  761                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
  762                 *tl = nfs_false;
  763         } else {
  764 #endif
  765                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
  766                 if (vap->va_mode == (mode_t)VNOVAL)
  767                         sp->sa_mode = nfs_xdrneg1;
  768                 else
  769                         sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
  770                 if (vap->va_uid == (uid_t)VNOVAL)
  771                         sp->sa_uid = nfs_xdrneg1;
  772                 else
  773                         sp->sa_uid = txdr_unsigned(vap->va_uid);
  774                 if (vap->va_gid == (gid_t)VNOVAL)
  775                         sp->sa_gid = nfs_xdrneg1;
  776                 else
  777                         sp->sa_gid = txdr_unsigned(vap->va_gid);
  778                 sp->sa_size = txdr_unsigned(vap->va_size);
  779                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
  780                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
  781 #ifndef NFS_V2_ONLY
  782         }
  783 #endif
  784         nfsm_request(np, NFSPROC_SETATTR, l, cred);
  785 #ifndef NFS_V2_ONLY
  786         if (v3) {
  787                 nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC, FALSE);
  788         } else
  789 #endif
  790                 nfsm_loadattr(vp, (struct vattr *)0, NAC_NOTRUNC);
  791         nfsm_reqdone;
  792         return (error);
  793 }
  794 
  795 /*
  796  * nfs lookup call, one step at a time...
  797  * First look in cache
  798  * If not found, unlock the directory nfsnode and do the rpc
  799  *
  800  * This code is full of lock/unlock statements and checks, because
  801  * we continue after cache_lookup has finished (we need to check
  802  * with the attr cache and do an rpc if it has timed out). This means
  803  * that the locking effects of cache_lookup have to be taken into
  804  * account.
  805  */
  806 int
  807 nfs_lookup(v)
  808         void *v;
  809 {
  810         struct vop_lookup_args /* {
  811                 struct vnodeop_desc *a_desc;
  812                 struct vnode *a_dvp;
  813                 struct vnode **a_vpp;
  814                 struct componentname *a_cnp;
  815         } */ *ap = v;
  816         struct componentname *cnp = ap->a_cnp;
  817         struct vnode *dvp = ap->a_dvp;
  818         struct vnode **vpp = ap->a_vpp;
  819         int flags;
  820         struct vnode *newvp;
  821         u_int32_t *tl;
  822         caddr_t cp;
  823         int32_t t1, t2;
  824         caddr_t bpos, dpos, cp2;
  825         struct mbuf *mreq, *mrep, *md, *mb;
  826         long len;
  827         nfsfh_t *fhp;
  828         struct nfsnode *np;
  829         int error = 0, attrflag, fhsize;
  830         const int v3 = NFS_ISV3(dvp);
  831 
  832         flags = cnp->cn_flags;
  833 
  834         *vpp = NULLVP;
  835         newvp = NULLVP;
  836         if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
  837             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
  838                 return (EROFS);
  839         if (dvp->v_type != VDIR)
  840                 return (ENOTDIR);
  841 
  842         /*
  843          * RFC1813(nfsv3) 3.2 says clients should handle "." by themselves.
  844          */
  845         if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
  846                 error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_lwp);
  847                 if (error)
  848                         return error;
  849                 if (cnp->cn_nameiop == RENAME && (flags & ISLASTCN))
  850                         return EISDIR;
  851                 VREF(dvp);
  852                 *vpp = dvp;
  853                 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
  854                                 cnp->cn_flags |= SAVENAME;
  855                 return 0;
  856         }
  857 
  858         np = VTONFS(dvp);
  859 
  860         /*
  861          * Before tediously performing a linear scan of the directory,
  862          * check the name cache to see if the directory/name pair
  863          * we are looking for is known already.
  864          * If the directory/name pair is found in the name cache,
  865          * we have to ensure the directory has not changed from
  866          * the time the cache entry has been created. If it has,
  867          * the cache entry has to be ignored.
  868          */
  869         error = cache_lookup_raw(dvp, vpp, cnp);
  870         KASSERT(dvp != *vpp);
  871         if (error >= 0) {
  872                 struct vattr vattr;
  873                 int err2;
  874 
  875                 if (error && error != ENOENT) {
  876                         *vpp = NULLVP;
  877                         return error;
  878                 }
  879 
  880                 err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_lwp);
  881                 if (err2 != 0) {
  882                         if (error == 0)
  883                                 vrele(*vpp);
  884                         *vpp = NULLVP;
  885                         return err2;
  886                 }
  887 
  888                 if (VOP_GETATTR(dvp, &vattr, cnp->cn_cred,
  889                     cnp->cn_lwp) || timespeccmp(&vattr.va_mtime,
  890                     &VTONFS(dvp)->n_nctime, !=)) {
  891                         if (error == 0) {
  892                                 vrele(*vpp);
  893                                 *vpp = NULLVP;
  894                         }
  895                         cache_purge1(dvp, NULL, PURGE_CHILDREN);
  896                         timespecclear(&np->n_nctime);
  897                         goto dorpc;
  898                 }
  899 
  900                 if (error == ENOENT) {
  901                         goto noentry;
  902                 }
  903 
  904                 newvp = *vpp;
  905                 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_lwp)
  906                     && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) {
  907                         nfsstats.lookupcache_hits++;
  908                         if ((flags & ISDOTDOT) != 0) {
  909                                 VOP_UNLOCK(dvp, 0);
  910                         }
  911                         error = vn_lock(newvp, LK_EXCLUSIVE);
  912                         if ((flags & ISDOTDOT) != 0) {
  913                                 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
  914                         }
  915                         if (error) {
  916                                 /* newvp has been revoked. */
  917                                 vrele(newvp);
  918                                 *vpp = NULL;
  919                                 return error;
  920                         }
  921                         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
  922                                 cnp->cn_flags |= SAVENAME;
  923                         KASSERT(newvp->v_type != VNON);
  924                         return (0);
  925                 }
  926                 cache_purge1(newvp, NULL, PURGE_PARENTS);
  927                 vrele(newvp);
  928                 *vpp = NULLVP;
  929         }
  930 dorpc:
  931 #if 0
  932         /*
  933          * because nfsv3 has the same CREATE semantics as ours,
  934          * we don't have to perform LOOKUPs beforehand.
  935          *
  936          * XXX ideally we can do the same for nfsv2 in the case of !O_EXCL.
  937          * XXX although we have no way to know if O_EXCL is requested or not.
  938          */
  939 
  940         if (v3 && cnp->cn_nameiop == CREATE &&
  941             (flags & (ISLASTCN|ISDOTDOT)) == ISLASTCN &&
  942             (dvp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
  943                 cnp->cn_flags |= SAVENAME;
  944                 return (EJUSTRETURN);
  945         }
  946 #endif /* 0 */
  947 
  948         error = 0;
  949         newvp = NULLVP;
  950         nfsstats.lookupcache_misses++;
  951         nfsstats.rpccnt[NFSPROC_LOOKUP]++;
  952         len = cnp->cn_namelen;
  953         nfsm_reqhead(np, NFSPROC_LOOKUP,
  954                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
  955         nfsm_fhtom(np, v3);
  956         nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
  957         nfsm_request(np, NFSPROC_LOOKUP, cnp->cn_lwp, cnp->cn_cred);
  958         if (error) {
  959                 nfsm_postop_attr(dvp, attrflag, 0);
  960                 m_freem(mrep);
  961                 goto nfsmout;
  962         }
  963         nfsm_getfh(fhp, fhsize, v3);
  964 
  965         /*
  966          * Handle RENAME case...
  967          */
  968         if (cnp->cn_nameiop == RENAME && (flags & ISLASTCN)) {
  969                 if (NFS_CMPFH(np, fhp, fhsize)) {
  970                         m_freem(mrep);
  971                         return (EISDIR);
  972                 }
  973                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
  974                 if (error) {
  975                         m_freem(mrep);
  976                         return error;
  977                 }
  978                 newvp = NFSTOV(np);
  979 #ifndef NFS_V2_ONLY
  980                 if (v3) {
  981                         nfsm_postop_attr(newvp, attrflag, 0);
  982                         nfsm_postop_attr(dvp, attrflag, 0);
  983                 } else
  984 #endif
  985                         nfsm_loadattr(newvp, (struct vattr *)0, 0);
  986                 *vpp = newvp;
  987                 m_freem(mrep);
  988                 cnp->cn_flags |= SAVENAME;
  989                 goto validate;
  990         }
  991 
  992         /*
  993          * The postop attr handling is duplicated for each if case,
  994          * because it should be done while dvp is locked (unlocking
  995          * dvp is different for each case).
  996          */
  997 
  998         if (NFS_CMPFH(np, fhp, fhsize)) {
  999                 /*
 1000                  * "." lookup
 1001                  */
 1002                 VREF(dvp);
 1003                 newvp = dvp;
 1004 #ifndef NFS_V2_ONLY
 1005                 if (v3) {
 1006                         nfsm_postop_attr(newvp, attrflag, 0);
 1007                         nfsm_postop_attr(dvp, attrflag, 0);
 1008                 } else
 1009 #endif
 1010                         nfsm_loadattr(newvp, (struct vattr *)0, 0);
 1011         } else if (flags & ISDOTDOT) {
 1012                 /*
 1013                  * ".." lookup
 1014                  */
 1015                 VOP_UNLOCK(dvp, 0);
 1016                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
 1017                 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
 1018                 if (error) {
 1019                         m_freem(mrep);
 1020                         return error;
 1021                 }
 1022                 newvp = NFSTOV(np);
 1023 
 1024 #ifndef NFS_V2_ONLY
 1025                 if (v3) {
 1026                         nfsm_postop_attr(newvp, attrflag, 0);
 1027                         nfsm_postop_attr(dvp, attrflag, 0);
 1028                 } else
 1029 #endif
 1030                         nfsm_loadattr(newvp, (struct vattr *)0, 0);
 1031         } else {
 1032                 /*
 1033                  * Other lookups.
 1034                  */
 1035                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
 1036                 if (error) {
 1037                         m_freem(mrep);
 1038                         return error;
 1039                 }
 1040                 newvp = NFSTOV(np);
 1041 #ifndef NFS_V2_ONLY
 1042                 if (v3) {
 1043                         nfsm_postop_attr(newvp, attrflag, 0);
 1044                         nfsm_postop_attr(dvp, attrflag, 0);
 1045                 } else
 1046 #endif
 1047                         nfsm_loadattr(newvp, (struct vattr *)0, 0);
 1048         }
 1049         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
 1050                 cnp->cn_flags |= SAVENAME;
 1051         if ((cnp->cn_flags & MAKEENTRY) &&
 1052             (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) {
 1053                 nfs_cache_enter(dvp, newvp, cnp);
 1054         }
 1055         *vpp = newvp;
 1056         nfsm_reqdone;
 1057         if (error) {
 1058                 /*
 1059                  * We get here only because of errors returned by
 1060                  * the RPC. Otherwise we'll have returned above
 1061                  * (the nfsm_* macros will jump to nfsm_reqdone
 1062                  * on error).
 1063                  */
 1064                 if (error == ENOENT && (cnp->cn_flags & MAKEENTRY) &&
 1065                     cnp->cn_nameiop != CREATE) {
 1066                         nfs_cache_enter(dvp, NULL, cnp);
 1067                 }
 1068                 if (newvp != NULLVP) {
 1069                         if (newvp == dvp) {
 1070                                 vrele(newvp);
 1071                         } else {
 1072                                 vput(newvp);
 1073                         }
 1074                 }
 1075 noentry:
 1076                 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
 1077                     (flags & ISLASTCN) && error == ENOENT) {
 1078                         if (dvp->v_mount->mnt_flag & MNT_RDONLY) {
 1079                                 error = EROFS;
 1080                         } else {
 1081                                 error = EJUSTRETURN;
 1082                                 cnp->cn_flags |= SAVENAME;
 1083                         }
 1084                 }
 1085                 *vpp = NULL;
 1086                 return error;
 1087         }
 1088 
 1089 validate:
 1090         /*
 1091          * make sure we have valid type and size.
 1092          */
 1093 
 1094         newvp = *vpp;
 1095         if (newvp->v_type == VNON) {
 1096                 struct vattr vattr; /* dummy */
 1097 
 1098                 KASSERT(VTONFS(newvp)->n_attrstamp == 0);
 1099                 error = VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_lwp);
 1100                 if (error) {
 1101                         vput(newvp);
 1102                         *vpp = NULL;
 1103                 }
 1104         }
 1105 
 1106         return error;
 1107 }
 1108 
 1109 /*
 1110  * nfs read call.
 1111  * Just call nfs_bioread() to do the work.
 1112  */
 1113 int
 1114 nfs_read(v)
 1115         void *v;
 1116 {
 1117         struct vop_read_args /* {
 1118                 struct vnode *a_vp;
 1119                 struct uio *a_uio;
 1120                 int  a_ioflag;
 1121                 kauth_cred_t a_cred;
 1122         } */ *ap = v;
 1123         struct vnode *vp = ap->a_vp;
 1124 
 1125         if (vp->v_type != VREG)
 1126                 return EISDIR;
 1127         return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0));
 1128 }
 1129 
 1130 /*
 1131  * nfs readlink call
 1132  */
 1133 int
 1134 nfs_readlink(v)
 1135         void *v;
 1136 {
 1137         struct vop_readlink_args /* {
 1138                 struct vnode *a_vp;
 1139                 struct uio *a_uio;
 1140                 kauth_cred_t a_cred;
 1141         } */ *ap = v;
 1142         struct vnode *vp = ap->a_vp;
 1143         struct nfsnode *np = VTONFS(vp);
 1144 
 1145         if (vp->v_type != VLNK)
 1146                 return (EPERM);
 1147 
 1148         if (np->n_rcred != NULL) {
 1149                 kauth_cred_free(np->n_rcred);
 1150         }
 1151         np->n_rcred = ap->a_cred;
 1152         kauth_cred_hold(np->n_rcred);
 1153 
 1154         return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0));
 1155 }
 1156 
 1157 /*
 1158  * Do a readlink rpc.
 1159  * Called by nfs_doio() from below the buffer cache.
 1160  */
 1161 int
 1162 nfs_readlinkrpc(vp, uiop, cred)
 1163         struct vnode *vp;
 1164         struct uio *uiop;
 1165         kauth_cred_t cred;
 1166 {
 1167         u_int32_t *tl;
 1168         caddr_t cp;
 1169         int32_t t1, t2;
 1170         caddr_t bpos, dpos, cp2;
 1171         int error = 0;
 1172         uint32_t len;
 1173         struct mbuf *mreq, *mrep, *md, *mb;
 1174         const int v3 = NFS_ISV3(vp);
 1175         struct nfsnode *np = VTONFS(vp);
 1176 #ifndef NFS_V2_ONLY
 1177         int attrflag;
 1178 #endif
 1179 
 1180         nfsstats.rpccnt[NFSPROC_READLINK]++;
 1181         nfsm_reqhead(np, NFSPROC_READLINK, NFSX_FH(v3));
 1182         nfsm_fhtom(np, v3);
 1183         nfsm_request(np, NFSPROC_READLINK, curlwp, cred);
 1184 #ifndef NFS_V2_ONLY
 1185         if (v3)
 1186                 nfsm_postop_attr(vp, attrflag, 0);
 1187 #endif
 1188         if (!error) {
 1189 #ifndef NFS_V2_ONLY
 1190                 if (v3) {
 1191                         nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
 1192                         len = fxdr_unsigned(uint32_t, *tl);
 1193                         if (len > MAXPATHLEN) {
 1194                                 /*
 1195                                  * this pathname is too long for us.
 1196                                  */
 1197                                 m_freem(mrep);
 1198                                 /* Solaris returns EINVAL. should we follow? */
 1199                                 error = ENAMETOOLONG;
 1200                                 goto nfsmout;
 1201                         }
 1202                 } else
 1203 #endif
 1204                 {
 1205                         nfsm_strsiz(len, NFS_MAXPATHLEN);
 1206                 }
 1207                 nfsm_mtouio(uiop, len);
 1208         }
 1209         nfsm_reqdone;
 1210         return (error);
 1211 }
 1212 
 1213 /*
 1214  * nfs read rpc call
 1215  * Ditto above
 1216  */
 1217 int
 1218 nfs_readrpc(vp, uiop)
 1219         struct vnode *vp;
 1220         struct uio *uiop;
 1221 {
 1222         u_int32_t *tl;
 1223         caddr_t cp;
 1224         int32_t t1, t2;
 1225         caddr_t bpos, dpos, cp2;
 1226         struct mbuf *mreq, *mrep, *md, *mb;
 1227         struct nfsmount *nmp;
 1228         int error = 0, len, retlen, tsiz, eof, byte_count;
 1229         const int v3 = NFS_ISV3(vp);
 1230         struct nfsnode *np = VTONFS(vp);
 1231 #ifndef NFS_V2_ONLY
 1232         int attrflag;
 1233 #endif
 1234 
 1235 #ifndef nolint
 1236         eof = 0;
 1237 #endif
 1238         nmp = VFSTONFS(vp->v_mount);
 1239         tsiz = uiop->uio_resid;
 1240         if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
 1241                 return (EFBIG);
 1242         iostat_busy(nmp->nm_stats);
 1243         byte_count = 0; /* count bytes actually transferred */
 1244         while (tsiz > 0) {
 1245                 nfsstats.rpccnt[NFSPROC_READ]++;
 1246                 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
 1247                 nfsm_reqhead(np, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
 1248                 nfsm_fhtom(np, v3);
 1249                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
 1250 #ifndef NFS_V2_ONLY
 1251                 if (v3) {
 1252                         txdr_hyper(uiop->uio_offset, tl);
 1253                         *(tl + 2) = txdr_unsigned(len);
 1254                 } else
 1255 #endif
 1256                 {
 1257                         *tl++ = txdr_unsigned(uiop->uio_offset);
 1258                         *tl++ = txdr_unsigned(len);
 1259                         *tl = 0;
 1260                 }
 1261                 nfsm_request(np, NFSPROC_READ, curlwp, np->n_rcred);
 1262 #ifndef NFS_V2_ONLY
 1263                 if (v3) {
 1264                         nfsm_postop_attr(vp, attrflag, NAC_NOTRUNC);
 1265                         if (error) {
 1266                                 m_freem(mrep);
 1267                                 goto nfsmout;
 1268                         }
 1269                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1270                         eof = fxdr_unsigned(int, *(tl + 1));
 1271                 } else
 1272 #endif
 1273                         nfsm_loadattr(vp, (struct vattr *)0, NAC_NOTRUNC);
 1274                 nfsm_strsiz(retlen, nmp->nm_rsize);
 1275                 nfsm_mtouio(uiop, retlen);
 1276                 m_freem(mrep);
 1277                 tsiz -= retlen;
 1278                 byte_count += retlen;
 1279 #ifndef NFS_V2_ONLY
 1280                 if (v3) {
 1281                         if (eof || retlen == 0)
 1282                                 tsiz = 0;
 1283                 } else
 1284 #endif
 1285                 if (retlen < len)
 1286                         tsiz = 0;
 1287         }
 1288 nfsmout:
 1289         iostat_unbusy(nmp->nm_stats, byte_count, 1);
 1290         return (error);
 1291 }
 1292 
 1293 struct nfs_writerpc_context {
 1294         struct simplelock nwc_slock;
 1295         volatile int nwc_mbufcount;
 1296 };
 1297 
 1298 /*
 1299  * free mbuf used to refer protected pages while write rpc call.
 1300  * called at splvm.
 1301  */
 1302 static void
 1303 nfs_writerpc_extfree(struct mbuf *m, caddr_t tbuf, size_t size, void *arg)
 1304 {
 1305         struct nfs_writerpc_context *ctx = arg;
 1306 
 1307         KASSERT(m != NULL);
 1308         KASSERT(ctx != NULL);
 1309         pool_cache_put(&mbpool_cache, m);
 1310         simple_lock(&ctx->nwc_slock);
 1311         if (--ctx->nwc_mbufcount == 0) {
 1312                 wakeup(ctx);
 1313         }
 1314         simple_unlock(&ctx->nwc_slock);
 1315 }
 1316 
 1317 /*
 1318  * nfs write call
 1319  */
 1320 int
 1321 nfs_writerpc(vp, uiop, iomode, pageprotected, stalewriteverfp)
 1322         struct vnode *vp;
 1323         struct uio *uiop;
 1324         int *iomode;
 1325         boolean_t pageprotected;
 1326         boolean_t *stalewriteverfp;
 1327 {
 1328         u_int32_t *tl;
 1329         caddr_t cp;
 1330         int32_t t1, t2;
 1331         caddr_t bpos, dpos;
 1332         struct mbuf *mreq, *mrep, *md, *mb;
 1333         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 1334         int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR;
 1335         const int v3 = NFS_ISV3(vp);
 1336         int committed = NFSV3WRITE_FILESYNC;
 1337         struct nfsnode *np = VTONFS(vp);
 1338         struct nfs_writerpc_context ctx;
 1339         int s, byte_count;
 1340         struct lwp *l = NULL;
 1341         size_t origresid;
 1342 #ifndef NFS_V2_ONLY
 1343         caddr_t cp2;
 1344         int rlen, commit;
 1345 #endif
 1346 
 1347         simple_lock_init(&ctx.nwc_slock);
 1348         ctx.nwc_mbufcount = 1;
 1349 
 1350         if (vp->v_mount->mnt_flag & MNT_RDONLY) {
 1351                 panic("writerpc readonly vp %p", vp);
 1352         }
 1353 
 1354 #ifdef DIAGNOSTIC
 1355         if (uiop->uio_iovcnt != 1)
 1356                 panic("nfs: writerpc iovcnt > 1");
 1357 #endif
 1358         tsiz = uiop->uio_resid;
 1359         if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
 1360                 return (EFBIG);
 1361         if (pageprotected) {
 1362                 l = curlwp;
 1363                 PHOLD(l);
 1364         }
 1365 retry:
 1366         origresid = uiop->uio_resid;
 1367         KASSERT(origresid == uiop->uio_iov->iov_len);
 1368         iostat_busy(nmp->nm_stats);
 1369         byte_count = 0; /* count of bytes actually written */
 1370         while (tsiz > 0) {
 1371                 uint32_t datalen; /* data bytes need to be allocated in mbuf */
 1372                 uint32_t backup;
 1373                 boolean_t stalewriteverf = FALSE;
 1374 
 1375                 nfsstats.rpccnt[NFSPROC_WRITE]++;
 1376                 len = min(tsiz, nmp->nm_wsize);
 1377                 datalen = pageprotected ? 0 : nfsm_rndup(len);
 1378                 nfsm_reqhead(np, NFSPROC_WRITE,
 1379                         NFSX_FH(v3) + 5 * NFSX_UNSIGNED + datalen);
 1380                 nfsm_fhtom(np, v3);
 1381 #ifndef NFS_V2_ONLY
 1382                 if (v3) {
 1383                         nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 1384                         txdr_hyper(uiop->uio_offset, tl);
 1385                         tl += 2;
 1386                         *tl++ = txdr_unsigned(len);
 1387                         *tl++ = txdr_unsigned(*iomode);
 1388                         *tl = txdr_unsigned(len);
 1389                 } else
 1390 #endif
 1391                 {
 1392                         u_int32_t x;
 1393 
 1394                         nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 1395                         /* Set both "begin" and "current" to non-garbage. */
 1396                         x = txdr_unsigned((u_int32_t)uiop->uio_offset);
 1397                         *tl++ = x;      /* "begin offset" */
 1398                         *tl++ = x;      /* "current offset" */
 1399                         x = txdr_unsigned(len);
 1400                         *tl++ = x;      /* total to this offset */
 1401                         *tl = x;        /* size of this write */
 1402 
 1403                 }
 1404                 if (pageprotected) {
 1405                         /*
 1406                          * since we know pages can't be modified during i/o,
 1407                          * no need to copy them for us.
 1408                          */
 1409                         struct mbuf *m;
 1410                         struct iovec *iovp = uiop->uio_iov;
 1411 
 1412                         m = m_get(M_WAIT, MT_DATA);
 1413                         MCLAIM(m, &nfs_mowner);
 1414                         MEXTADD(m, iovp->iov_base, len, M_MBUF,
 1415                             nfs_writerpc_extfree, &ctx);
 1416                         m->m_flags |= M_EXT_ROMAP;
 1417                         m->m_len = len;
 1418                         mb->m_next = m;
 1419                         /*
 1420                          * no need to maintain mb and bpos here
 1421                          * because no one care them later.
 1422                          */
 1423 #if 0
 1424                         mb = m;
 1425                         bpos = mtod(caddr_t, mb) + mb->m_len;
 1426 #endif
 1427                         UIO_ADVANCE(uiop, len);
 1428                         uiop->uio_offset += len;
 1429                         s = splvm();
 1430                         simple_lock(&ctx.nwc_slock);
 1431                         ctx.nwc_mbufcount++;
 1432                         simple_unlock(&ctx.nwc_slock);
 1433                         splx(s);
 1434                         nfs_zeropad(mb, 0, nfsm_padlen(len));
 1435                 } else {
 1436                         nfsm_uiotom(uiop, len);
 1437                 }
 1438                 nfsm_request(np, NFSPROC_WRITE, curlwp, np->n_wcred);
 1439 #ifndef NFS_V2_ONLY
 1440                 if (v3) {
 1441                         wccflag = NFSV3_WCCCHK;
 1442                         nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC, !error);
 1443                         if (!error) {
 1444                                 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
 1445                                         + NFSX_V3WRITEVERF);
 1446                                 rlen = fxdr_unsigned(int, *tl++);
 1447                                 if (rlen == 0) {
 1448                                         error = NFSERR_IO;
 1449                                         m_freem(mrep);
 1450                                         break;
 1451                                 } else if (rlen < len) {
 1452                                         backup = len - rlen;
 1453                                         UIO_ADVANCE(uiop, -backup);
 1454                                         uiop->uio_offset -= backup;
 1455                                         len = rlen;
 1456                                 }
 1457                                 commit = fxdr_unsigned(int, *tl++);
 1458 
 1459                                 /*
 1460                                  * Return the lowest committment level
 1461                                  * obtained by any of the RPCs.
 1462                                  */
 1463                                 if (committed == NFSV3WRITE_FILESYNC)
 1464                                         committed = commit;
 1465                                 else if (committed == NFSV3WRITE_DATASYNC &&
 1466                                         commit == NFSV3WRITE_UNSTABLE)
 1467                                         committed = commit;
 1468                                 simple_lock(&nmp->nm_slock);
 1469                                 if ((nmp->nm_iflag & NFSMNT_HASWRITEVERF) == 0){
 1470                                         memcpy(nmp->nm_writeverf, tl,
 1471                                             NFSX_V3WRITEVERF);
 1472                                         nmp->nm_iflag |= NFSMNT_HASWRITEVERF;
 1473                                 } else if ((nmp->nm_iflag &
 1474                                     NFSMNT_STALEWRITEVERF) ||
 1475                                     memcmp(tl, nmp->nm_writeverf,
 1476                                     NFSX_V3WRITEVERF)) {
 1477                                         memcpy(nmp->nm_writeverf, tl,
 1478                                             NFSX_V3WRITEVERF);
 1479                                         /*
 1480                                          * note NFSMNT_STALEWRITEVERF
 1481                                          * if we're the first thread to
 1482                                          * notice it.
 1483                                          */
 1484                                         if ((nmp->nm_iflag &
 1485                                             NFSMNT_STALEWRITEVERF) == 0) {
 1486                                                 stalewriteverf = TRUE;
 1487                                                 nmp->nm_iflag |=
 1488                                                     NFSMNT_STALEWRITEVERF;
 1489                                         }
 1490                                 }
 1491                                 simple_unlock(&nmp->nm_slock);
 1492                         }
 1493                 } else
 1494 #endif
 1495                         nfsm_loadattr(vp, (struct vattr *)0, NAC_NOTRUNC);
 1496                 if (wccflag)
 1497                         VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr->va_mtime;
 1498                 m_freem(mrep);
 1499                 if (error)
 1500                         break;
 1501                 tsiz -= len;
 1502                 byte_count += len;
 1503                 if (stalewriteverf) {
 1504                         *stalewriteverfp = TRUE;
 1505                         stalewriteverf = FALSE;
 1506                         if (committed == NFSV3WRITE_UNSTABLE &&
 1507                             len != origresid) {
 1508                                 /*
 1509                                  * if our write requests weren't atomic but
 1510                                  * unstable, datas in previous iterations
 1511                                  * might have already been lost now.
 1512                                  * then, we should resend them to nfsd.
 1513                                  */
 1514                                 backup = origresid - tsiz;
 1515                                 UIO_ADVANCE(uiop, -backup);
 1516                                 uiop->uio_offset -= backup;
 1517                                 tsiz = origresid;
 1518                                 goto retry;
 1519                         }
 1520                 }
 1521         }
 1522 nfsmout:
 1523         iostat_unbusy(nmp->nm_stats, byte_count, 0);
 1524         if (pageprotected) {
 1525                 /*
 1526                  * wait until mbufs go away.
 1527                  * retransmitted mbufs can survive longer than rpc requests
 1528                  * themselves.
 1529                  */
 1530                 s = splvm();
 1531                 simple_lock(&ctx.nwc_slock);
 1532                 ctx.nwc_mbufcount--;
 1533                 while (ctx.nwc_mbufcount > 0) {
 1534                         ltsleep(&ctx, PRIBIO, "nfsmblk", 0, &ctx.nwc_slock);
 1535                 }
 1536                 simple_unlock(&ctx.nwc_slock);
 1537                 splx(s);
 1538                 PRELE(l);
 1539         }
 1540         *iomode = committed;
 1541         if (error)
 1542                 uiop->uio_resid = tsiz;
 1543         return (error);
 1544 }
 1545 
 1546 /*
 1547  * nfs mknod rpc
 1548  * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
 1549  * mode set to specify the file type and the size field for rdev.
 1550  */
 1551 int
 1552 nfs_mknodrpc(dvp, vpp, cnp, vap)
 1553         struct vnode *dvp;
 1554         struct vnode **vpp;
 1555         struct componentname *cnp;
 1556         struct vattr *vap;
 1557 {
 1558         struct nfsv2_sattr *sp;
 1559         u_int32_t *tl;
 1560         caddr_t cp;
 1561         int32_t t1, t2;
 1562         struct vnode *newvp = (struct vnode *)0;
 1563         struct nfsnode *dnp, *np;
 1564         char *cp2;
 1565         caddr_t bpos, dpos;
 1566         int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
 1567         struct mbuf *mreq, *mrep, *md, *mb;
 1568         u_int32_t rdev;
 1569         const int v3 = NFS_ISV3(dvp);
 1570 
 1571         if (vap->va_type == VCHR || vap->va_type == VBLK)
 1572                 rdev = txdr_unsigned(vap->va_rdev);
 1573         else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
 1574                 rdev = nfs_xdrneg1;
 1575         else {
 1576                 VOP_ABORTOP(dvp, cnp);
 1577                 vput(dvp);
 1578                 return (EOPNOTSUPP);
 1579         }
 1580         nfsstats.rpccnt[NFSPROC_MKNOD]++;
 1581         dnp = VTONFS(dvp);
 1582         nfsm_reqhead(dnp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
 1583                 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
 1584         nfsm_fhtom(dnp, v3);
 1585         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 1586 #ifndef NFS_V2_ONLY
 1587         if (v3) {
 1588                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
 1589                 *tl++ = vtonfsv3_type(vap->va_type);
 1590                 nfsm_v3attrbuild(vap, FALSE);
 1591                 if (vap->va_type == VCHR || vap->va_type == VBLK) {
 1592                         nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 1593                         *tl++ = txdr_unsigned(major(vap->va_rdev));
 1594                         *tl = txdr_unsigned(minor(vap->va_rdev));
 1595                 }
 1596         } else
 1597 #endif
 1598         {
 1599                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
 1600                 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
 1601                 sp->sa_uid = nfs_xdrneg1;
 1602                 sp->sa_gid = nfs_xdrneg1;
 1603                 sp->sa_size = rdev;
 1604                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
 1605                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
 1606         }
 1607         nfsm_request(dnp, NFSPROC_MKNOD, cnp->cn_lwp, cnp->cn_cred);
 1608         if (!error) {
 1609                 nfsm_mtofh(dvp, newvp, v3, gotvp);
 1610                 if (!gotvp) {
 1611                         error = nfs_lookitup(dvp, cnp->cn_nameptr,
 1612                             cnp->cn_namelen, cnp->cn_cred, cnp->cn_lwp, &np);
 1613                         if (!error)
 1614                                 newvp = NFSTOV(np);
 1615                 }
 1616         }
 1617 #ifndef NFS_V2_ONLY
 1618         if (v3)
 1619                 nfsm_wcc_data(dvp, wccflag, 0, !error);
 1620 #endif
 1621         nfsm_reqdone;
 1622         if (error) {
 1623                 if (newvp)
 1624                         vput(newvp);
 1625         } else {
 1626                 if (cnp->cn_flags & MAKEENTRY)
 1627                         nfs_cache_enter(dvp, newvp, cnp);
 1628                 *vpp = newvp;
 1629         }
 1630         PNBUF_PUT(cnp->cn_pnbuf);
 1631         VTONFS(dvp)->n_flag |= NMODIFIED;
 1632         if (!wccflag)
 1633                 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
 1634         vput(dvp);
 1635         return (error);
 1636 }
 1637 
 1638 /*
 1639  * nfs mknod vop
 1640  * just call nfs_mknodrpc() to do the work.
 1641  */
 1642 /* ARGSUSED */
 1643 int
 1644 nfs_mknod(v)
 1645         void *v;
 1646 {
 1647         struct vop_mknod_args /* {
 1648                 struct vnode *a_dvp;
 1649                 struct vnode **a_vpp;
 1650                 struct componentname *a_cnp;
 1651                 struct vattr *a_vap;
 1652         } */ *ap = v;
 1653         struct vnode *dvp = ap->a_dvp;
 1654         struct componentname *cnp = ap->a_cnp;
 1655         int error;
 1656 
 1657         error = nfs_mknodrpc(dvp, ap->a_vpp, cnp, ap->a_vap);
 1658         VN_KNOTE(dvp, NOTE_WRITE);
 1659         if (error == 0 || error == EEXIST)
 1660                 cache_purge1(dvp, cnp, 0);
 1661         return (error);
 1662 }
 1663 
 1664 #ifndef NFS_V2_ONLY
 1665 static u_long create_verf;
 1666 #endif
 1667 /*
 1668  * nfs file create call
 1669  */
 1670 int
 1671 nfs_create(v)
 1672         void *v;
 1673 {
 1674         struct vop_create_args /* {
 1675                 struct vnode *a_dvp;
 1676                 struct vnode **a_vpp;
 1677                 struct componentname *a_cnp;
 1678                 struct vattr *a_vap;
 1679         } */ *ap = v;
 1680         struct vnode *dvp = ap->a_dvp;
 1681         struct vattr *vap = ap->a_vap;
 1682         struct componentname *cnp = ap->a_cnp;
 1683         struct nfsv2_sattr *sp;
 1684         u_int32_t *tl;
 1685         caddr_t cp;
 1686         int32_t t1, t2;
 1687         struct nfsnode *dnp, *np = (struct nfsnode *)0;
 1688         struct vnode *newvp = (struct vnode *)0;
 1689         caddr_t bpos, dpos, cp2;
 1690         int error, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
 1691         struct mbuf *mreq, *mrep, *md, *mb;
 1692         const int v3 = NFS_ISV3(dvp);
 1693 
 1694         /*
 1695          * Oops, not for me..
 1696          */
 1697         if (vap->va_type == VSOCK)
 1698                 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
 1699 
 1700         KASSERT(vap->va_type == VREG);
 1701 
 1702 #ifdef VA_EXCLUSIVE
 1703         if (vap->va_vaflags & VA_EXCLUSIVE)
 1704                 fmode |= O_EXCL;
 1705 #endif
 1706 again:
 1707         error = 0;
 1708         nfsstats.rpccnt[NFSPROC_CREATE]++;
 1709         dnp = VTONFS(dvp);
 1710         nfsm_reqhead(dnp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
 1711                 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
 1712         nfsm_fhtom(dnp, v3);
 1713         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 1714 #ifndef NFS_V2_ONLY
 1715         if (v3) {
 1716                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
 1717                 if (fmode & O_EXCL) {
 1718                         *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
 1719                         nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
 1720 #ifdef INET
 1721                         if (TAILQ_FIRST(&in_ifaddrhead))
 1722                                 *tl++ = TAILQ_FIRST(&in_ifaddrhead)->
 1723                                     ia_addr.sin_addr.s_addr;
 1724                         else
 1725                                 *tl++ = create_verf;
 1726 #else
 1727                         *tl++ = create_verf;
 1728 #endif
 1729                         *tl = ++create_verf;
 1730                 } else {
 1731                         *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
 1732                         nfsm_v3attrbuild(vap, FALSE);
 1733                 }
 1734         } else
 1735 #endif
 1736         {
 1737                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
 1738                 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
 1739                 sp->sa_uid = nfs_xdrneg1;
 1740                 sp->sa_gid = nfs_xdrneg1;
 1741                 sp->sa_size = 0;
 1742                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
 1743                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
 1744         }
 1745         nfsm_request(dnp, NFSPROC_CREATE, cnp->cn_lwp, cnp->cn_cred);
 1746         if (!error) {
 1747                 nfsm_mtofh(dvp, newvp, v3, gotvp);
 1748                 if (!gotvp) {
 1749                         error = nfs_lookitup(dvp, cnp->cn_nameptr,
 1750                             cnp->cn_namelen, cnp->cn_cred, cnp->cn_lwp, &np);
 1751                         if (!error)
 1752                                 newvp = NFSTOV(np);
 1753                 }
 1754         }
 1755 #ifndef NFS_V2_ONLY
 1756         if (v3)
 1757                 nfsm_wcc_data(dvp, wccflag, 0, !error);
 1758 #endif
 1759         nfsm_reqdone;
 1760         if (error) {
 1761                 /*
 1762                  * nfs_request maps NFSERR_NOTSUPP to ENOTSUP.
 1763                  */
 1764                 if (v3 && (fmode & O_EXCL) && error == ENOTSUP) {
 1765                         fmode &= ~O_EXCL;
 1766                         goto again;
 1767                 }
 1768         } else if (v3 && (fmode & O_EXCL)) {
 1769                 struct timespec ts;
 1770 
 1771                 getnanotime(&ts);
 1772 
 1773                 /*
 1774                  * make sure that we'll update timestamps as
 1775                  * most server implementations use them to store
 1776                  * the create verifier.
 1777                  *
 1778                  * XXX it's better to use TOSERVER always.
 1779                  */
 1780 
 1781                 if (vap->va_atime.tv_sec == VNOVAL)
 1782                         vap->va_atime = ts;
 1783                 if (vap->va_mtime.tv_sec == VNOVAL)
 1784                         vap->va_mtime = ts;
 1785 
 1786                 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_lwp);
 1787         }
 1788         if (error == 0) {
 1789                 if (cnp->cn_flags & MAKEENTRY)
 1790                         nfs_cache_enter(dvp, newvp, cnp);
 1791                 else
 1792                         cache_purge1(dvp, cnp, 0);
 1793                 *ap->a_vpp = newvp;
 1794         } else {
 1795                 if (newvp)
 1796                         vput(newvp);
 1797                 if (error == EEXIST)
 1798                         cache_purge1(dvp, cnp, 0);
 1799         }
 1800         PNBUF_PUT(cnp->cn_pnbuf);
 1801         VTONFS(dvp)->n_flag |= NMODIFIED;
 1802         if (!wccflag)
 1803                 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
 1804         VN_KNOTE(ap->a_dvp, NOTE_WRITE);
 1805         vput(dvp);
 1806         return (error);
 1807 }
 1808 
 1809 /*
 1810  * nfs file remove call
 1811  * To try and make nfs semantics closer to ufs semantics, a file that has
 1812  * other processes using the vnode is renamed instead of removed and then
 1813  * removed later on the last close.
 1814  * - If v_usecount > 1
 1815  *        If a rename is not already in the works
 1816  *           call nfs_sillyrename() to set it up
 1817  *     else
 1818  *        do the remove rpc
 1819  */
 1820 int
 1821 nfs_remove(v)
 1822         void *v;
 1823 {
 1824         struct vop_remove_args /* {
 1825                 struct vnodeop_desc *a_desc;
 1826                 struct vnode * a_dvp;
 1827                 struct vnode * a_vp;
 1828                 struct componentname * a_cnp;
 1829         } */ *ap = v;
 1830         struct vnode *vp = ap->a_vp;
 1831         struct vnode *dvp = ap->a_dvp;
 1832         struct componentname *cnp = ap->a_cnp;
 1833         struct nfsnode *np = VTONFS(vp);
 1834         int error = 0;
 1835         struct vattr vattr;
 1836 
 1837 #ifndef DIAGNOSTIC
 1838         if ((cnp->cn_flags & HASBUF) == 0)
 1839                 panic("nfs_remove: no name");
 1840         if (vp->v_usecount < 1)
 1841                 panic("nfs_remove: bad v_usecount");
 1842 #endif
 1843         if (vp->v_type == VDIR)
 1844                 error = EPERM;
 1845         else if (vp->v_usecount == 1 || (np->n_sillyrename &&
 1846             VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_lwp) == 0 &&
 1847             vattr.va_nlink > 1)) {
 1848                 /*
 1849                  * Purge the name cache so that the chance of a lookup for
 1850                  * the name succeeding while the remove is in progress is
 1851                  * minimized. Without node locking it can still happen, such
 1852                  * that an I/O op returns ESTALE, but since you get this if
 1853                  * another host removes the file..
 1854                  */
 1855                 cache_purge(vp);
 1856                 /*
 1857                  * throw away biocache buffers, mainly to avoid
 1858                  * unnecessary delayed writes later.
 1859                  */
 1860                 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_lwp, 1);
 1861                 /* Do the rpc */
 1862                 if (error != EINTR)
 1863                         error = nfs_removerpc(dvp, cnp->cn_nameptr,
 1864                                 cnp->cn_namelen, cnp->cn_cred, cnp->cn_lwp);
 1865         } else if (!np->n_sillyrename)
 1866                 error = nfs_sillyrename(dvp, vp, cnp, FALSE);
 1867         PNBUF_PUT(cnp->cn_pnbuf);
 1868         if (!error && nfs_getattrcache(vp, &vattr) == 0 &&
 1869             vattr.va_nlink == 1) {
 1870                 np->n_flag |= NREMOVED;
 1871         }
 1872         NFS_INVALIDATE_ATTRCACHE(np);
 1873         VN_KNOTE(vp, NOTE_DELETE);
 1874         VN_KNOTE(dvp, NOTE_WRITE);
 1875         if (dvp == vp)
 1876                 vrele(vp);
 1877         else
 1878                 vput(vp);
 1879         vput(dvp);
 1880         return (error);
 1881 }
 1882 
 1883 /*
 1884  * nfs file remove rpc called from nfs_inactive
 1885  */
 1886 int
 1887 nfs_removeit(sp)
 1888         struct sillyrename *sp;
 1889 {
 1890 
 1891         return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred,
 1892                 (struct lwp *)0));
 1893 }
 1894 
 1895 /*
 1896  * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
 1897  */
 1898 int
 1899 nfs_removerpc(dvp, name, namelen, cred, l)
 1900         struct vnode *dvp;
 1901         const char *name;
 1902         int namelen;
 1903         kauth_cred_t cred;
 1904         struct lwp *l;
 1905 {
 1906         u_int32_t *tl;
 1907         caddr_t cp;
 1908 #ifndef NFS_V2_ONLY
 1909         int32_t t1;
 1910         caddr_t cp2;
 1911 #endif
 1912         int32_t t2;
 1913         caddr_t bpos, dpos;
 1914         int error = 0, wccflag = NFSV3_WCCRATTR;
 1915         struct mbuf *mreq, *mrep, *md, *mb;
 1916         const int v3 = NFS_ISV3(dvp);
 1917         int rexmit = 0;
 1918         struct nfsnode *dnp = VTONFS(dvp);
 1919 
 1920         nfsstats.rpccnt[NFSPROC_REMOVE]++;
 1921         nfsm_reqhead(dnp, NFSPROC_REMOVE,
 1922                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
 1923         nfsm_fhtom(dnp, v3);
 1924         nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
 1925         nfsm_request1(dnp, NFSPROC_REMOVE, l, cred, &rexmit);
 1926 #ifndef NFS_V2_ONLY
 1927         if (v3)
 1928                 nfsm_wcc_data(dvp, wccflag, 0, !error);
 1929 #endif
 1930         nfsm_reqdone;
 1931         VTONFS(dvp)->n_flag |= NMODIFIED;
 1932         if (!wccflag)
 1933                 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
 1934         /*
 1935          * Kludge City: If the first reply to the remove rpc is lost..
 1936          *   the reply to the retransmitted request will be ENOENT
 1937          *   since the file was in fact removed
 1938          *   Therefore, we cheat and return success.
 1939          */
 1940         if (rexmit && error == ENOENT)
 1941                 error = 0;
 1942         return (error);
 1943 }
 1944 
 1945 /*
 1946  * nfs file rename call
 1947  */
 1948 int
 1949 nfs_rename(v)
 1950         void *v;
 1951 {
 1952         struct vop_rename_args  /* {
 1953                 struct vnode *a_fdvp;
 1954                 struct vnode *a_fvp;
 1955                 struct componentname *a_fcnp;
 1956                 struct vnode *a_tdvp;
 1957                 struct vnode *a_tvp;
 1958                 struct componentname *a_tcnp;
 1959         } */ *ap = v;
 1960         struct vnode *fvp = ap->a_fvp;
 1961         struct vnode *tvp = ap->a_tvp;
 1962         struct vnode *fdvp = ap->a_fdvp;
 1963         struct vnode *tdvp = ap->a_tdvp;
 1964         struct componentname *tcnp = ap->a_tcnp;
 1965         struct componentname *fcnp = ap->a_fcnp;
 1966         int error;
 1967 
 1968 #ifndef DIAGNOSTIC
 1969         if ((tcnp->cn_flags & HASBUF) == 0 ||
 1970             (fcnp->cn_flags & HASBUF) == 0)
 1971                 panic("nfs_rename: no name");
 1972 #endif
 1973         /* Check for cross-device rename */
 1974         if ((fvp->v_mount != tdvp->v_mount) ||
 1975             (tvp && (fvp->v_mount != tvp->v_mount))) {
 1976                 error = EXDEV;
 1977                 goto out;
 1978         }
 1979 
 1980         /*
 1981          * If the tvp exists and is in use, sillyrename it before doing the
 1982          * rename of the new file over it.
 1983          *
 1984          * Have sillyrename use link instead of rename if possible,
 1985          * so that we don't lose the file if the rename fails, and so
 1986          * that there's no window when the "to" file doesn't exist.
 1987          */
 1988         if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
 1989             tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp, TRUE)) {
 1990                 VN_KNOTE(tvp, NOTE_DELETE);
 1991                 vput(tvp);
 1992                 tvp = NULL;
 1993         }
 1994 
 1995         error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
 1996                 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
 1997                 tcnp->cn_lwp);
 1998 
 1999         VN_KNOTE(fdvp, NOTE_WRITE);
 2000         VN_KNOTE(tdvp, NOTE_WRITE);
 2001         if (error == 0 || error == EEXIST) {
 2002                 if (fvp->v_type == VDIR)
 2003                         cache_purge(fvp);
 2004                 else
 2005                         cache_purge1(fdvp, fcnp, 0);
 2006                 if (tvp != NULL && tvp->v_type == VDIR)
 2007                         cache_purge(tvp);
 2008                 else
 2009                         cache_purge1(tdvp, tcnp, 0);
 2010         }
 2011 out:
 2012         if (tdvp == tvp)
 2013                 vrele(tdvp);
 2014         else
 2015                 vput(tdvp);
 2016         if (tvp)
 2017                 vput(tvp);
 2018         vrele(fdvp);
 2019         vrele(fvp);
 2020         return (error);
 2021 }
 2022 
 2023 /*
 2024  * nfs file rename rpc called from nfs_remove() above
 2025  */
 2026 int
 2027 nfs_renameit(sdvp, scnp, sp)
 2028         struct vnode *sdvp;
 2029         struct componentname *scnp;
 2030         struct sillyrename *sp;
 2031 {
 2032         return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
 2033                 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_lwp));
 2034 }
 2035 
 2036 /*
 2037  * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
 2038  */
 2039 int
 2040 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, l)
 2041         struct vnode *fdvp;
 2042         const char *fnameptr;
 2043         int fnamelen;
 2044         struct vnode *tdvp;
 2045         const char *tnameptr;
 2046         int tnamelen;
 2047         kauth_cred_t cred;
 2048         struct lwp *l;
 2049 {
 2050         u_int32_t *tl;
 2051         caddr_t cp;
 2052 #ifndef NFS_V2_ONLY
 2053         int32_t t1;
 2054         caddr_t cp2;
 2055 #endif
 2056         int32_t t2;
 2057         caddr_t bpos, dpos;
 2058         int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
 2059         struct mbuf *mreq, *mrep, *md, *mb;
 2060         const int v3 = NFS_ISV3(fdvp);
 2061         int rexmit = 0;
 2062         struct nfsnode *fdnp = VTONFS(fdvp);
 2063 
 2064         nfsstats.rpccnt[NFSPROC_RENAME]++;
 2065         nfsm_reqhead(fdnp, NFSPROC_RENAME,
 2066                 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
 2067                 nfsm_rndup(tnamelen));
 2068         nfsm_fhtom(fdnp, v3);
 2069         nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
 2070         nfsm_fhtom(VTONFS(tdvp), v3);
 2071         nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
 2072         nfsm_request1(fdnp, NFSPROC_RENAME, l, cred, &rexmit);
 2073 #ifndef NFS_V2_ONLY
 2074         if (v3) {
 2075                 nfsm_wcc_data(fdvp, fwccflag, 0, !error);
 2076                 nfsm_wcc_data(tdvp, twccflag, 0, !error);
 2077         }
 2078 #endif
 2079         nfsm_reqdone;
 2080         VTONFS(fdvp)->n_flag |= NMODIFIED;
 2081         VTONFS(tdvp)->n_flag |= NMODIFIED;
 2082         if (!fwccflag)
 2083                 NFS_INVALIDATE_ATTRCACHE(VTONFS(fdvp));
 2084         if (!twccflag)
 2085                 NFS_INVALIDATE_ATTRCACHE(VTONFS(tdvp));
 2086         /*
 2087          * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
 2088          */
 2089         if (rexmit && error == ENOENT)
 2090                 error = 0;
 2091         return (error);
 2092 }
 2093 
 2094 /*
 2095  * NFS link RPC, called from nfs_link.
 2096  * Assumes dvp and vp locked, and leaves them that way.
 2097  */
 2098 
 2099 static int
 2100 nfs_linkrpc(struct vnode *dvp, struct vnode *vp, const char *name,
 2101     size_t namelen, kauth_cred_t cred, struct lwp *l)
 2102 {
 2103         u_int32_t *tl;
 2104         caddr_t cp;
 2105 #ifndef NFS_V2_ONLY
 2106         int32_t t1;
 2107         caddr_t cp2;
 2108 #endif
 2109         int32_t t2;
 2110         caddr_t bpos, dpos;
 2111         int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
 2112         struct mbuf *mreq, *mrep, *md, *mb;
 2113         const int v3 = NFS_ISV3(dvp);
 2114         int rexmit = 0;
 2115         struct nfsnode *np = VTONFS(vp);
 2116 
 2117         nfsstats.rpccnt[NFSPROC_LINK]++;
 2118         nfsm_reqhead(np, NFSPROC_LINK,
 2119             NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(namelen));
 2120         nfsm_fhtom(np, v3);
 2121         nfsm_fhtom(VTONFS(dvp), v3);
 2122         nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
 2123         nfsm_request1(np, NFSPROC_LINK, l, cred, &rexmit);
 2124 #ifndef NFS_V2_ONLY
 2125         if (v3) {
 2126                 nfsm_postop_attr(vp, attrflag, 0);
 2127                 nfsm_wcc_data(dvp, wccflag, 0, !error);
 2128         }
 2129 #endif
 2130         nfsm_reqdone;
 2131 
 2132         VTONFS(dvp)->n_flag |= NMODIFIED;
 2133         if (!attrflag)
 2134                 NFS_INVALIDATE_ATTRCACHE(VTONFS(vp));
 2135         if (!wccflag)
 2136                 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
 2137 
 2138         /*
 2139          * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
 2140          */
 2141         if (rexmit && error == EEXIST)
 2142                 error = 0;
 2143 
 2144         return error;
 2145 }
 2146 
 2147 /*
 2148  * nfs hard link create call
 2149  */
 2150 int
 2151 nfs_link(v)
 2152         void *v;
 2153 {
 2154         struct vop_link_args /* {
 2155                 struct vnode *a_dvp;
 2156                 struct vnode *a_vp;
 2157                 struct componentname *a_cnp;
 2158         } */ *ap = v;
 2159         struct vnode *vp = ap->a_vp;
 2160         struct vnode *dvp = ap->a_dvp;
 2161         struct componentname *cnp = ap->a_cnp;
 2162         int error = 0;
 2163 
 2164         if (dvp->v_mount != vp->v_mount) {
 2165                 VOP_ABORTOP(dvp, cnp);
 2166                 vput(dvp);
 2167                 return (EXDEV);
 2168         }
 2169         if (dvp != vp) {
 2170                 error = vn_lock(vp, LK_EXCLUSIVE);
 2171                 if (error != 0) {
 2172                         VOP_ABORTOP(dvp, cnp);
 2173                         vput(dvp);
 2174                         return error;
 2175                 }
 2176         }
 2177 
 2178         /*
 2179          * Push all writes to the server, so that the attribute cache
 2180          * doesn't get "out of sync" with the server.
 2181          * XXX There should be a better way!
 2182          */
 2183         VOP_FSYNC(vp, cnp->cn_cred, FSYNC_WAIT, 0, 0, cnp->cn_lwp);
 2184 
 2185         error = nfs_linkrpc(dvp, vp, cnp->cn_nameptr, cnp->cn_namelen,
 2186             cnp->cn_cred, cnp->cn_lwp);
 2187 
 2188         if (error == 0)
 2189                 cache_purge1(dvp, cnp, 0);
 2190         PNBUF_PUT(cnp->cn_pnbuf);
 2191         if (dvp != vp)
 2192                 VOP_UNLOCK(vp, 0);
 2193         VN_KNOTE(vp, NOTE_LINK);
 2194         VN_KNOTE(dvp, NOTE_WRITE);
 2195         vput(dvp);
 2196         return (error);
 2197 }
 2198 
 2199 /*
 2200  * nfs symbolic link create call
 2201  */
 2202 int
 2203 nfs_symlink(v)
 2204         void *v;
 2205 {
 2206         struct vop_symlink_args /* {
 2207                 struct vnode *a_dvp;
 2208                 struct vnode **a_vpp;
 2209                 struct componentname *a_cnp;
 2210                 struct vattr *a_vap;
 2211                 char *a_target;
 2212         } */ *ap = v;
 2213         struct vnode *dvp = ap->a_dvp;
 2214         struct vattr *vap = ap->a_vap;
 2215         struct componentname *cnp = ap->a_cnp;
 2216         struct nfsv2_sattr *sp;
 2217         u_int32_t *tl;
 2218         caddr_t cp;
 2219         int32_t t1, t2;
 2220         caddr_t bpos, dpos, cp2;
 2221         int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
 2222         struct mbuf *mreq, *mrep, *md, *mb;
 2223         struct vnode *newvp = (struct vnode *)0;
 2224         const int v3 = NFS_ISV3(dvp);
 2225         int rexmit = 0;
 2226         struct nfsnode *dnp = VTONFS(dvp);
 2227 
 2228         *ap->a_vpp = NULL;
 2229         nfsstats.rpccnt[NFSPROC_SYMLINK]++;
 2230         slen = strlen(ap->a_target);
 2231         nfsm_reqhead(dnp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
 2232             nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
 2233         nfsm_fhtom(dnp, v3);
 2234         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 2235 #ifndef NFS_V2_ONlY
 2236         if (v3)
 2237                 nfsm_v3attrbuild(vap, FALSE);
 2238 #endif
 2239         nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
 2240 #ifndef NFS_V2_ONlY
 2241         if (!v3) {
 2242                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
 2243                 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
 2244                 sp->sa_uid = nfs_xdrneg1;
 2245                 sp->sa_gid = nfs_xdrneg1;
 2246                 sp->sa_size = nfs_xdrneg1;
 2247                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
 2248                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
 2249         }
 2250 #endif
 2251         nfsm_request1(dnp, NFSPROC_SYMLINK, cnp->cn_lwp, cnp->cn_cred,
 2252             &rexmit);
 2253 #ifndef NFS_V2_ONlY
 2254         if (v3) {
 2255                 if (!error)
 2256                         nfsm_mtofh(dvp, newvp, v3, gotvp);
 2257                 nfsm_wcc_data(dvp, wccflag, 0, !error);
 2258         }
 2259 #endif
 2260         nfsm_reqdone;
 2261         /*
 2262          * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
 2263          */
 2264         if (rexmit && error == EEXIST)
 2265                 error = 0;
 2266         if (error == 0 || error == EEXIST)
 2267                 cache_purge1(dvp, cnp, 0);
 2268         if (error == 0 && newvp == NULL) {
 2269                 struct nfsnode *np = NULL;
 2270 
 2271                 error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
 2272                     cnp->cn_cred, cnp->cn_lwp, &np);
 2273                 if (error == 0)
 2274                         newvp = NFSTOV(np);
 2275         }
 2276         if (error) {
 2277                 if (newvp != NULL)
 2278                         vput(newvp);
 2279         } else {
 2280                 *ap->a_vpp = newvp;
 2281         }
 2282         PNBUF_PUT(cnp->cn_pnbuf);
 2283         VTONFS(dvp)->n_flag |= NMODIFIED;
 2284         if (!wccflag)
 2285                 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
 2286         VN_KNOTE(dvp, NOTE_WRITE);
 2287         vput(dvp);
 2288         return (error);
 2289 }
 2290 
 2291 /*
 2292  * nfs make dir call
 2293  */
 2294 int
 2295 nfs_mkdir(v)
 2296         void *v;
 2297 {
 2298         struct vop_mkdir_args /* {
 2299                 struct vnode *a_dvp;
 2300                 struct vnode **a_vpp;
 2301                 struct componentname *a_cnp;
 2302                 struct vattr *a_vap;
 2303         } */ *ap = v;
 2304         struct vnode *dvp = ap->a_dvp;
 2305         struct vattr *vap = ap->a_vap;
 2306         struct componentname *cnp = ap->a_cnp;
 2307         struct nfsv2_sattr *sp;
 2308         u_int32_t *tl;
 2309         caddr_t cp;
 2310         int32_t t1, t2;
 2311         int len;
 2312         struct nfsnode *dnp = VTONFS(dvp), *np = (struct nfsnode *)0;
 2313         struct vnode *newvp = (struct vnode *)0;
 2314         caddr_t bpos, dpos, cp2;
 2315         int error = 0, wccflag = NFSV3_WCCRATTR;
 2316         int gotvp = 0;
 2317         int rexmit = 0;
 2318         struct mbuf *mreq, *mrep, *md, *mb;
 2319         const int v3 = NFS_ISV3(dvp);
 2320 
 2321         len = cnp->cn_namelen;
 2322         nfsstats.rpccnt[NFSPROC_MKDIR]++;
 2323         nfsm_reqhead(dnp, NFSPROC_MKDIR,
 2324           NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
 2325         nfsm_fhtom(dnp, v3);
 2326         nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
 2327 #ifndef NFS_V2_ONLY
 2328         if (v3) {
 2329                 nfsm_v3attrbuild(vap, FALSE);
 2330         } else
 2331 #endif
 2332         {
 2333                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
 2334                 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
 2335                 sp->sa_uid = nfs_xdrneg1;
 2336                 sp->sa_gid = nfs_xdrneg1;
 2337                 sp->sa_size = nfs_xdrneg1;
 2338                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
 2339                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
 2340         }
 2341         nfsm_request1(dnp, NFSPROC_MKDIR, cnp->cn_lwp, cnp->cn_cred, &rexmit);
 2342         if (!error)
 2343                 nfsm_mtofh(dvp, newvp, v3, gotvp);
 2344         if (v3)
 2345                 nfsm_wcc_data(dvp, wccflag, 0, !error);
 2346         nfsm_reqdone;
 2347         VTONFS(dvp)->n_flag |= NMODIFIED;
 2348         if (!wccflag)
 2349                 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
 2350         /*
 2351          * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
 2352          * if we can succeed in looking up the directory.
 2353          */
 2354         if ((rexmit && error == EEXIST) || (!error && !gotvp)) {
 2355                 if (newvp) {
 2356                         vput(newvp);
 2357                         newvp = (struct vnode *)0;
 2358                 }
 2359                 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
 2360                         cnp->cn_lwp, &np);
 2361                 if (!error) {
 2362                         newvp = NFSTOV(np);
 2363                         if (newvp->v_type != VDIR || newvp == dvp)
 2364                                 error = EEXIST;
 2365                 }
 2366         }
 2367         if (error) {
 2368                 if (newvp) {
 2369                         if (dvp != newvp)
 2370                                 vput(newvp);
 2371                         else
 2372                                 vrele(newvp);
 2373                 }
 2374         } else {
 2375                 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
 2376                 if (cnp->cn_flags & MAKEENTRY)
 2377                         nfs_cache_enter(dvp, newvp, cnp);
 2378                 *ap->a_vpp = newvp;
 2379         }
 2380         PNBUF_PUT(cnp->cn_pnbuf);
 2381         vput(dvp);
 2382         return (error);
 2383 }
 2384 
 2385 /*
 2386  * nfs remove directory call
 2387  */
 2388 int
 2389 nfs_rmdir(v)
 2390         void *v;
 2391 {
 2392         struct vop_rmdir_args /* {
 2393                 struct vnode *a_dvp;
 2394                 struct vnode *a_vp;
 2395                 struct componentname *a_cnp;
 2396         } */ *ap = v;
 2397         struct vnode *vp = ap->a_vp;
 2398         struct vnode *dvp = ap->a_dvp;
 2399         struct componentname *cnp = ap->a_cnp;
 2400         u_int32_t *tl;
 2401         caddr_t cp;
 2402 #ifndef NFS_V2_ONLY
 2403         int32_t t1;
 2404         caddr_t cp2;
 2405 #endif
 2406         int32_t t2;
 2407         caddr_t bpos, dpos;
 2408         int error = 0, wccflag = NFSV3_WCCRATTR;
 2409         int rexmit = 0;
 2410         struct mbuf *mreq, *mrep, *md, *mb;
 2411         const int v3 = NFS_ISV3(dvp);
 2412         struct nfsnode *dnp;
 2413 
 2414         if (dvp == vp) {
 2415                 vrele(dvp);
 2416                 vput(dvp);
 2417                 PNBUF_PUT(cnp->cn_pnbuf);
 2418                 return (EINVAL);
 2419         }
 2420         nfsstats.rpccnt[NFSPROC_RMDIR]++;
 2421         dnp = VTONFS(dvp);
 2422         nfsm_reqhead(dnp, NFSPROC_RMDIR,
 2423                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
 2424         nfsm_fhtom(dnp, v3);
 2425         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
 2426         nfsm_request1(dnp, NFSPROC_RMDIR, cnp->cn_lwp, cnp->cn_cred, &rexmit);
 2427 #ifndef NFS_V2_ONLY
 2428         if (v3)
 2429                 nfsm_wcc_data(dvp, wccflag, 0, !error);
 2430 #endif
 2431         nfsm_reqdone;
 2432         PNBUF_PUT(cnp->cn_pnbuf);
 2433         VTONFS(dvp)->n_flag |= NMODIFIED;
 2434         if (!wccflag)
 2435                 NFS_INVALIDATE_ATTRCACHE(VTONFS(dvp));
 2436         VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
 2437         VN_KNOTE(vp, NOTE_DELETE);
 2438         cache_purge(vp);
 2439         vput(vp);
 2440         vput(dvp);
 2441         /*
 2442          * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
 2443          */
 2444         if (rexmit && error == ENOENT)
 2445                 error = 0;
 2446         return (error);
 2447 }
 2448 
 2449 /*
 2450  * nfs readdir call
 2451  */
 2452 int
 2453 nfs_readdir(v)
 2454         void *v;
 2455 {
 2456         struct vop_readdir_args /* {
 2457                 struct vnode *a_vp;
 2458                 struct uio *a_uio;
 2459                 kauth_cred_t a_cred;
 2460                 int *a_eofflag;
 2461                 off_t **a_cookies;
 2462                 int *a_ncookies;
 2463         } */ *ap = v;
 2464         struct vnode *vp = ap->a_vp;
 2465         struct uio *uio = ap->a_uio;
 2466         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 2467         char *base = uio->uio_iov->iov_base;
 2468         int tresid, error;
 2469         size_t count, lost;
 2470         struct dirent *dp;
 2471         off_t *cookies = NULL;
 2472         int ncookies = 0, nc;
 2473 
 2474         if (vp->v_type != VDIR)
 2475                 return (EPERM);
 2476 
 2477         lost = uio->uio_resid & (NFS_DIRFRAGSIZ - 1);
 2478         count = uio->uio_resid - lost;
 2479         if (count <= 0)
 2480                 return (EINVAL);
 2481 
 2482         /*
 2483          * Call nfs_bioread() to do the real work.
 2484          */
 2485         tresid = uio->uio_resid = count;
 2486         error = nfs_bioread(vp, uio, 0, ap->a_cred,
 2487                     ap->a_cookies ? NFSBIO_CACHECOOKIES : 0);
 2488 
 2489         if (!error && ap->a_cookies) {
 2490                 ncookies = count / 16;
 2491                 cookies = malloc(sizeof (off_t) * ncookies, M_TEMP, M_WAITOK);
 2492                 *ap->a_cookies = cookies;
 2493         }
 2494 
 2495         if (!error && uio->uio_resid == tresid) {
 2496                 uio->uio_resid += lost;
 2497                 nfsstats.direofcache_misses++;
 2498                 if (ap->a_cookies)
 2499                         *ap->a_ncookies = 0;
 2500                 *ap->a_eofflag = 1;
 2501                 return (0);
 2502         }
 2503 
 2504         if (!error && ap->a_cookies) {
 2505                 /*
 2506                  * Only the NFS server and emulations use cookies, and they
 2507                  * load the directory block into system space, so we can
 2508                  * just look at it directly.
 2509                  */
 2510                 if (!VMSPACE_IS_KERNEL_P(uio->uio_vmspace) ||
 2511                     uio->uio_iovcnt != 1)
 2512                         panic("nfs_readdir: lost in space");
 2513                 for (nc = 0; ncookies-- &&
 2514                      base < (char *)uio->uio_iov->iov_base; nc++){
 2515                         dp = (struct dirent *) base;
 2516                         if (dp->d_reclen == 0)
 2517                                 break;
 2518                         if (nmp->nm_flag & NFSMNT_XLATECOOKIE)
 2519                                 *(cookies++) = (off_t)NFS_GETCOOKIE32(dp);
 2520                         else
 2521                                 *(cookies++) = NFS_GETCOOKIE(dp);
 2522                         base += dp->d_reclen;
 2523                 }
 2524                 uio->uio_resid +=
 2525                     ((caddr_t)uio->uio_iov->iov_base - base);
 2526                 uio->uio_iov->iov_len +=
 2527                     ((caddr_t)uio->uio_iov->iov_base - base);
 2528                 uio->uio_iov->iov_base = base;
 2529                 *ap->a_ncookies = nc;
 2530         }
 2531 
 2532         uio->uio_resid += lost;
 2533         *ap->a_eofflag = 0;
 2534         return (error);
 2535 }
 2536 
 2537 /*
 2538  * Readdir rpc call.
 2539  * Called from below the buffer cache by nfs_doio().
 2540  */
 2541 int
 2542 nfs_readdirrpc(vp, uiop, cred)
 2543         struct vnode *vp;
 2544         struct uio *uiop;
 2545         kauth_cred_t cred;
 2546 {
 2547         int len, left;
 2548         struct dirent *dp = NULL;
 2549         u_int32_t *tl;
 2550         caddr_t cp;
 2551         int32_t t1, t2;
 2552         caddr_t bpos, dpos, cp2;
 2553         struct mbuf *mreq, *mrep, *md, *mb;
 2554         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 2555         struct nfsnode *dnp = VTONFS(vp);
 2556         u_quad_t fileno;
 2557         int error = 0, more_dirs = 1, blksiz = 0, bigenough = 1;
 2558 #ifndef NFS_V2_ONLY
 2559         int attrflag;
 2560 #endif
 2561         int nrpcs = 0, reclen;
 2562         const int v3 = NFS_ISV3(vp);
 2563 
 2564 #ifdef DIAGNOSTIC
 2565         /*
 2566          * Should be called from buffer cache, so only amount of
 2567          * NFS_DIRBLKSIZ will be requested.
 2568          */
 2569         if (uiop->uio_iovcnt != 1 || uiop->uio_resid != NFS_DIRBLKSIZ)
 2570                 panic("nfs readdirrpc bad uio");
 2571 #endif
 2572 
 2573         /*
 2574          * Loop around doing readdir rpc's of size nm_readdirsize
 2575          * truncated to a multiple of NFS_DIRFRAGSIZ.
 2576          * The stopping criteria is EOF or buffer full.
 2577          */
 2578         while (more_dirs && bigenough) {
 2579                 /*
 2580                  * Heuristic: don't bother to do another RPC to further
 2581                  * fill up this block if there is not much room left. (< 50%
 2582                  * of the readdir RPC size). This wastes some buffer space
 2583                  * but can save up to 50% in RPC calls.
 2584                  */
 2585                 if (nrpcs > 0 && uiop->uio_resid < (nmp->nm_readdirsize / 2)) {
 2586                         bigenough = 0;
 2587                         break;
 2588                 }
 2589                 nfsstats.rpccnt[NFSPROC_READDIR]++;
 2590                 nfsm_reqhead(dnp, NFSPROC_READDIR, NFSX_FH(v3) +
 2591                         NFSX_READDIR(v3));
 2592                 nfsm_fhtom(dnp, v3);
 2593 #ifndef NFS_V2_ONLY
 2594                 if (v3) {
 2595                         nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 2596                         if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE) {
 2597                                 txdr_swapcookie3(uiop->uio_offset, tl);
 2598                         } else {
 2599                                 txdr_cookie3(uiop->uio_offset, tl);
 2600                         }
 2601                         tl += 2;
 2602                         *tl++ = dnp->n_cookieverf.nfsuquad[0];
 2603                         *tl++ = dnp->n_cookieverf.nfsuquad[1];
 2604                 } else
 2605 #endif
 2606                 {
 2607                         nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 2608                         *tl++ = txdr_unsigned(uiop->uio_offset);
 2609                 }
 2610                 *tl = txdr_unsigned(nmp->nm_readdirsize);
 2611                 nfsm_request(dnp, NFSPROC_READDIR, curlwp, cred);
 2612                 nrpcs++;
 2613 #ifndef NFS_V2_ONLY
 2614                 if (v3) {
 2615                         nfsm_postop_attr(vp, attrflag, 0);
 2616                         if (!error) {
 2617                                 nfsm_dissect(tl, u_int32_t *,
 2618                                     2 * NFSX_UNSIGNED);
 2619                                 dnp->n_cookieverf.nfsuquad[0] = *tl++;
 2620                                 dnp->n_cookieverf.nfsuquad[1] = *tl;
 2621                         } else {
 2622                                 m_freem(mrep);
 2623                                 goto nfsmout;
 2624                         }
 2625                 }
 2626 #endif
 2627                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 2628                 more_dirs = fxdr_unsigned(int, *tl);
 2629 
 2630                 /* loop thru the dir entries, doctoring them to 4bsd form */
 2631                 while (more_dirs && bigenough) {
 2632 #ifndef NFS_V2_ONLY
 2633                         if (v3) {
 2634                                 nfsm_dissect(tl, u_int32_t *,
 2635                                     3 * NFSX_UNSIGNED);
 2636                                 fileno = fxdr_hyper(tl);
 2637                                 len = fxdr_unsigned(int, *(tl + 2));
 2638                         } else
 2639 #endif
 2640                         {
 2641                                 nfsm_dissect(tl, u_int32_t *,
 2642                                     2 * NFSX_UNSIGNED);
 2643                                 fileno = fxdr_unsigned(u_quad_t, *tl++);
 2644                                 len = fxdr_unsigned(int, *tl);
 2645                         }
 2646                         if (len <= 0 || len > NFS_MAXNAMLEN) {
 2647                                 error = EBADRPC;
 2648                                 m_freem(mrep);
 2649                                 goto nfsmout;
 2650                         }
 2651                         /* for cookie stashing */
 2652                         reclen = _DIRENT_RECLEN(dp, len) + 2 * sizeof(off_t);
 2653                         left = NFS_DIRFRAGSIZ - blksiz;
 2654                         if (reclen > left) {
 2655                                 memset(uiop->uio_iov->iov_base, 0, left);
 2656                                 dp->d_reclen += left;
 2657                                 UIO_ADVANCE(uiop, left);
 2658                                 blksiz = 0;
 2659                                 NFS_STASHCOOKIE(dp, uiop->uio_offset);
 2660                         }
 2661                         if (reclen > uiop->uio_resid)
 2662                                 bigenough = 0;
 2663                         if (bigenough) {
 2664                                 int tlen;
 2665 
 2666                                 dp = (struct dirent *)uiop->uio_iov->iov_base;
 2667                                 dp->d_fileno = fileno;
 2668                                 dp->d_namlen = len;
 2669                                 dp->d_reclen = reclen;
 2670                                 dp->d_type = DT_UNKNOWN;
 2671                                 blksiz += reclen;
 2672                                 if (blksiz == NFS_DIRFRAGSIZ)
 2673                                         blksiz = 0;
 2674                                 UIO_ADVANCE(uiop, DIRHDSIZ);
 2675                                 nfsm_mtouio(uiop, len);
 2676                                 tlen = reclen - (DIRHDSIZ + len);
 2677                                 (void)memset(uiop->uio_iov->iov_base, 0, tlen);
 2678                                 UIO_ADVANCE(uiop, tlen);
 2679                         } else
 2680                                 nfsm_adv(nfsm_rndup(len));
 2681 #ifndef NFS_V2_ONLY
 2682                         if (v3) {
 2683                                 nfsm_dissect(tl, u_int32_t *,
 2684                                     3 * NFSX_UNSIGNED);
 2685                         } else
 2686 #endif
 2687                         {
 2688                                 nfsm_dissect(tl, u_int32_t *,
 2689                                     2 * NFSX_UNSIGNED);
 2690                         }
 2691                         if (bigenough) {
 2692 #ifndef NFS_V2_ONLY
 2693                                 if (v3) {
 2694                                         if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE)
 2695                                                 uiop->uio_offset =
 2696                                                     fxdr_swapcookie3(tl);
 2697                                         else
 2698                                                 uiop->uio_offset =
 2699                                                     fxdr_cookie3(tl);
 2700                                 }
 2701                                 else
 2702 #endif
 2703                                 {
 2704                                         uiop->uio_offset =
 2705                                             fxdr_unsigned(off_t, *tl);
 2706                                 }
 2707                                 NFS_STASHCOOKIE(dp, uiop->uio_offset);
 2708                         }
 2709                         if (v3)
 2710                                 tl += 2;
 2711                         else
 2712                                 tl++;
 2713                         more_dirs = fxdr_unsigned(int, *tl);
 2714                 }
 2715                 /*
 2716                  * If at end of rpc data, get the eof boolean
 2717                  */
 2718                 if (!more_dirs) {
 2719                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 2720                         more_dirs = (fxdr_unsigned(int, *tl) == 0);
 2721 
 2722                         /*
 2723                          * kludge: if we got no entries, treat it as EOF.
 2724                          * some server sometimes send a reply without any
 2725                          * entries or EOF.
 2726                          * although it might mean the server has very long name,
 2727                          * we can't handle such entries anyway.
 2728                          */
 2729 
 2730                         if (uiop->uio_resid >= NFS_DIRBLKSIZ)
 2731                                 more_dirs = 0;
 2732                 }
 2733                 m_freem(mrep);
 2734         }
 2735         /*
 2736          * Fill last record, iff any, out to a multiple of NFS_DIRFRAGSIZ
 2737          * by increasing d_reclen for the last record.
 2738          */
 2739         if (blksiz > 0) {
 2740                 left = NFS_DIRFRAGSIZ - blksiz;
 2741                 memset(uiop->uio_iov->iov_base, 0, left);
 2742                 dp->d_reclen += left;
 2743                 NFS_STASHCOOKIE(dp, uiop->uio_offset);
 2744                 UIO_ADVANCE(uiop, left);
 2745         }
 2746 
 2747         /*
 2748          * We are now either at the end of the directory or have filled the
 2749          * block.
 2750          */
 2751         if (bigenough) {
 2752                 dnp->n_direofoffset = uiop->uio_offset;
 2753                 dnp->n_flag |= NEOFVALID;
 2754         }
 2755 nfsmout:
 2756         return (error);
 2757 }
 2758 
 2759 #ifndef NFS_V2_ONLY
 2760 /*
 2761  * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
 2762  */
 2763 int
 2764 nfs_readdirplusrpc(vp, uiop, cred)
 2765         struct vnode *vp;
 2766         struct uio *uiop;
 2767         kauth_cred_t cred;
 2768 {
 2769         int len, left;
 2770         struct dirent *dp = NULL;
 2771         u_int32_t *tl;
 2772         caddr_t cp;
 2773         int32_t t1, t2;
 2774         struct vnode *newvp;
 2775         caddr_t bpos, dpos, cp2;
 2776         struct mbuf *mreq, *mrep, *md, *mb;
 2777         struct nameidata nami, *ndp = &nami;
 2778         struct componentname *cnp = &ndp->ni_cnd;
 2779         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 2780         struct nfsnode *dnp = VTONFS(vp), *np;
 2781         nfsfh_t *fhp;
 2782         u_quad_t fileno;
 2783         int error = 0, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
 2784         int attrflag, fhsize, nrpcs = 0, reclen;
 2785         struct nfs_fattr fattr, *fp;
 2786 
 2787 #ifdef DIAGNOSTIC
 2788         if (uiop->uio_iovcnt != 1 || uiop->uio_resid != NFS_DIRBLKSIZ)
 2789                 panic("nfs readdirplusrpc bad uio");
 2790 #endif
 2791         ndp->ni_dvp = vp;
 2792         newvp = NULLVP;
 2793 
 2794         /*
 2795          * Loop around doing readdir rpc's of size nm_readdirsize
 2796          * truncated to a multiple of NFS_DIRFRAGSIZ.
 2797          * The stopping criteria is EOF or buffer full.
 2798          */
 2799         while (more_dirs && bigenough) {
 2800                 if (nrpcs > 0 && uiop->uio_resid < (nmp->nm_readdirsize / 2)) {
 2801                         bigenough = 0;
 2802                         break;
 2803                 }
 2804                 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
 2805                 nfsm_reqhead(dnp, NFSPROC_READDIRPLUS,
 2806                         NFSX_FH(1) + 6 * NFSX_UNSIGNED);
 2807                 nfsm_fhtom(dnp, 1);
 2808                 nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
 2809                 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE) {
 2810                         txdr_swapcookie3(uiop->uio_offset, tl);
 2811                 } else {
 2812                         txdr_cookie3(uiop->uio_offset, tl);
 2813                 }
 2814                 tl += 2;
 2815                 *tl++ = dnp->n_cookieverf.nfsuquad[0];
 2816                 *tl++ = dnp->n_cookieverf.nfsuquad[1];
 2817                 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
 2818                 *tl = txdr_unsigned(nmp->nm_rsize);
 2819                 nfsm_request(dnp, NFSPROC_READDIRPLUS, curlwp, cred);
 2820                 nfsm_postop_attr(vp, attrflag, 0);
 2821                 if (error) {
 2822                         m_freem(mrep);
 2823                         goto nfsmout;
 2824                 }
 2825                 nrpcs++;
 2826                 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 2827                 dnp->n_cookieverf.nfsuquad[0] = *tl++;
 2828                 dnp->n_cookieverf.nfsuquad[1] = *tl++;
 2829                 more_dirs = fxdr_unsigned(int, *tl);
 2830 
 2831                 /* loop thru the dir entries, doctoring them to 4bsd form */
 2832                 while (more_dirs && bigenough) {
 2833                         nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 2834                         fileno = fxdr_hyper(tl);
 2835                         len = fxdr_unsigned(int, *(tl + 2));
 2836                         if (len <= 0 || len > NFS_MAXNAMLEN) {
 2837                                 error = EBADRPC;
 2838                                 m_freem(mrep);
 2839                                 goto nfsmout;
 2840                         }
 2841                         /* for cookie stashing */
 2842                         reclen = _DIRENT_RECLEN(dp, len) + 2 * sizeof(off_t);
 2843                         left = NFS_DIRFRAGSIZ - blksiz;
 2844                         if (reclen > left) {
 2845                                 /*
 2846                                  * DIRFRAGSIZ is aligned, no need to align
 2847                                  * again here.
 2848                                  */
 2849                                 memset(uiop->uio_iov->iov_base, 0, left);
 2850                                 dp->d_reclen += left;
 2851                                 UIO_ADVANCE(uiop, left);
 2852                                 NFS_STASHCOOKIE(dp, uiop->uio_offset);
 2853                                 blksiz = 0;
 2854                         }
 2855                         if (reclen > uiop->uio_resid)
 2856                                 bigenough = 0;
 2857                         if (bigenough) {
 2858                                 int tlen;
 2859 
 2860                                 dp = (struct dirent *)uiop->uio_iov->iov_base;
 2861                                 dp->d_fileno = fileno;
 2862                                 dp->d_namlen = len;
 2863                                 dp->d_reclen = reclen;
 2864                                 dp->d_type = DT_UNKNOWN;
 2865                                 blksiz += reclen;
 2866                                 if (blksiz == NFS_DIRFRAGSIZ)
 2867                                         blksiz = 0;
 2868                                 UIO_ADVANCE(uiop, DIRHDSIZ);
 2869                                 nfsm_mtouio(uiop, len);
 2870                                 tlen = reclen - (DIRHDSIZ + len);
 2871                                 (void)memset(uiop->uio_iov->iov_base, 0, tlen);
 2872                                 UIO_ADVANCE(uiop, tlen);
 2873                                 cnp->cn_nameptr = dp->d_name;
 2874                                 cnp->cn_namelen = dp->d_namlen;
 2875                         } else
 2876                                 nfsm_adv(nfsm_rndup(len));
 2877                         nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 2878                         if (bigenough) {
 2879                                 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE)
 2880                                         uiop->uio_offset =
 2881                                                 fxdr_swapcookie3(tl);
 2882                                 else
 2883                                         uiop->uio_offset =
 2884                                                 fxdr_cookie3(tl);
 2885                                 NFS_STASHCOOKIE(dp, uiop->uio_offset);
 2886                         }
 2887                         tl += 2;
 2888 
 2889                         /*
 2890                          * Since the attributes are before the file handle
 2891                          * (sigh), we must skip over the attributes and then
 2892                          * come back and get them.
 2893                          */
 2894                         attrflag = fxdr_unsigned(int, *tl);
 2895                         if (attrflag) {
 2896                             nfsm_dissect(fp, struct nfs_fattr *, NFSX_V3FATTR);
 2897                             memcpy(&fattr, fp, NFSX_V3FATTR);
 2898                             nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 2899                             doit = fxdr_unsigned(int, *tl);
 2900                             if (doit) {
 2901                                 nfsm_getfh(fhp, fhsize, 1);
 2902                                 if (NFS_CMPFH(dnp, fhp, fhsize)) {
 2903                                     VREF(vp);
 2904                                     newvp = vp;
 2905                                     np = dnp;
 2906                                 } else {
 2907                                     error = nfs_nget1(vp->v_mount, fhp,
 2908                                         fhsize, &np, LK_NOWAIT);
 2909                                     if (!error)
 2910                                         newvp = NFSTOV(np);
 2911                                 }
 2912                                 if (!error) {
 2913                                     const char *xcp;
 2914 
 2915                                     nfs_loadattrcache(&newvp, &fattr, 0, 0);
 2916                                     if (bigenough) {
 2917                                         dp->d_type =
 2918                                            IFTODT(VTTOIF(np->n_vattr->va_type));
 2919                                         if (cnp->cn_namelen <= NCHNAMLEN) {
 2920                                             ndp->ni_vp = newvp;
 2921                                             xcp = cnp->cn_nameptr +
 2922                                                 cnp->cn_namelen;
 2923                                             cnp->cn_hash =
 2924                                                namei_hash(cnp->cn_nameptr, &xcp);
 2925                                             nfs_cache_enter(ndp->ni_dvp,
 2926                                                 ndp->ni_vp, cnp);
 2927                                         }
 2928                                     }
 2929                                 }
 2930                                 error = 0;
 2931                            }
 2932                         } else {
 2933                             /* Just skip over the file handle */
 2934                             nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 2935                             i = fxdr_unsigned(int, *tl);
 2936                             nfsm_adv(nfsm_rndup(i));
 2937                         }
 2938                         if (newvp != NULLVP) {
 2939                             if (newvp == vp)
 2940                                 vrele(newvp);
 2941                             else
 2942                                 vput(newvp);
 2943                             newvp = NULLVP;
 2944                         }
 2945                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 2946                         more_dirs = fxdr_unsigned(int, *tl);
 2947                 }
 2948                 /*
 2949                  * If at end of rpc data, get the eof boolean
 2950                  */
 2951                 if (!more_dirs) {
 2952                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
 2953                         more_dirs = (fxdr_unsigned(int, *tl) == 0);
 2954 
 2955                         /*
 2956                          * kludge: see a comment in nfs_readdirrpc.
 2957                          */
 2958 
 2959                         if (uiop->uio_resid >= NFS_DIRBLKSIZ)
 2960                                 more_dirs = 0;
 2961                 }
 2962                 m_freem(mrep);
 2963         }
 2964         /*
 2965          * Fill last record, iff any, out to a multiple of NFS_DIRFRAGSIZ
 2966          * by increasing d_reclen for the last record.
 2967          */
 2968         if (blksiz > 0) {
 2969                 left = NFS_DIRFRAGSIZ - blksiz;
 2970                 memset(uiop->uio_iov->iov_base, 0, left);
 2971                 dp->d_reclen += left;
 2972                 NFS_STASHCOOKIE(dp, uiop->uio_offset);
 2973                 UIO_ADVANCE(uiop, left);
 2974         }
 2975 
 2976         /*
 2977          * We are now either at the end of the directory or have filled the
 2978          * block.
 2979          */
 2980         if (bigenough) {
 2981                 dnp->n_direofoffset = uiop->uio_offset;
 2982                 dnp->n_flag |= NEOFVALID;
 2983         }
 2984 nfsmout:
 2985         if (newvp != NULLVP) {
 2986                 if(newvp == vp)
 2987                     vrele(newvp);
 2988                 else
 2989                     vput(newvp);
 2990         }
 2991         return (error);
 2992 }
 2993 #endif
 2994 
 2995 /*
 2996  * Silly rename. To make the NFS filesystem that is stateless look a little
 2997  * more like the "ufs" a remove of an active vnode is translated to a rename
 2998  * to a funny looking filename that is removed by nfs_inactive on the
 2999  * nfsnode. There is the potential for another process on a different client
 3000  * to create the same funny name between the nfs_lookitup() fails and the
 3001  * nfs_rename() completes, but...
 3002  */
 3003 int
 3004 nfs_sillyrename(dvp, vp, cnp, dolink)
 3005         struct vnode *dvp, *vp;
 3006         struct componentname *cnp;
 3007         boolean_t dolink;
 3008 {
 3009         struct sillyrename *sp;
 3010         struct nfsnode *np;
 3011         int error;
 3012         short pid;
 3013 
 3014         cache_purge(dvp);
 3015         np = VTONFS(vp);
 3016 #ifndef DIAGNOSTIC
 3017         if (vp->v_type == VDIR)
 3018                 panic("nfs: sillyrename dir");
 3019 #endif
 3020         MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
 3021                 M_NFSREQ, M_WAITOK);
 3022         sp->s_cred = kauth_cred_dup(cnp->cn_cred);
 3023         sp->s_dvp = dvp;
 3024         VREF(dvp);
 3025 
 3026         /* Fudge together a funny name */
 3027         pid = cnp->cn_lwp->l_proc->p_pid;
 3028         memcpy(sp->s_name, ".nfsAxxxx4.4", 13);
 3029         sp->s_namlen = 12;
 3030         sp->s_name[8] = hexdigits[pid & 0xf];
 3031         sp->s_name[7] = hexdigits[(pid >> 4) & 0xf];
 3032         sp->s_name[6] = hexdigits[(pid >> 8) & 0xf];
 3033         sp->s_name[5] = hexdigits[(pid >> 12) & 0xf];
 3034 
 3035         /* Try lookitups until we get one that isn't there */
 3036         while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
 3037                 cnp->cn_lwp, (struct nfsnode **)0) == 0) {
 3038                 sp->s_name[4]++;
 3039                 if (sp->s_name[4] > 'z') {
 3040                         error = EINVAL;
 3041                         goto bad;
 3042                 }
 3043         }
 3044         if (dolink) {
 3045                 error = nfs_linkrpc(dvp, vp, sp->s_name, sp->s_namlen,
 3046                     sp->s_cred, cnp->cn_lwp);
 3047                 /*
 3048                  * nfs_request maps NFSERR_NOTSUPP to ENOTSUP.
 3049                  */
 3050                 if (error == ENOTSUP) {
 3051                         error = nfs_renameit(dvp, cnp, sp);
 3052                 }
 3053         } else {
 3054                 error = nfs_renameit(dvp, cnp, sp);
 3055         }
 3056         if (error)
 3057                 goto bad;
 3058         error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
 3059                 cnp->cn_lwp, &np);
 3060         np->n_sillyrename = sp;
 3061         return (0);
 3062 bad:
 3063         vrele(sp->s_dvp);
 3064         kauth_cred_free(sp->s_cred);
 3065         free((caddr_t)sp, M_NFSREQ);
 3066         return (error);
 3067 }
 3068 
 3069 /*
 3070  * Look up a file name and optionally either update the file handle or
 3071  * allocate an nfsnode, depending on the value of npp.
 3072  * npp == NULL  --> just do the lookup
 3073  * *npp == NULL --> allocate a new nfsnode and make sure attributes are
 3074  *                      handled too
 3075  * *npp != NULL --> update the file handle in the vnode
 3076  */
 3077 int
 3078 nfs_lookitup(dvp, name, len, cred, l, npp)
 3079         struct vnode *dvp;
 3080         const char *name;
 3081         int len;
 3082         kauth_cred_t cred;
 3083         struct lwp *l;
 3084         struct nfsnode **npp;
 3085 {
 3086         u_int32_t *tl;
 3087         caddr_t cp;
 3088         int32_t t1, t2;
 3089         struct vnode *newvp = (struct vnode *)0;
 3090         struct nfsnode *np, *dnp = VTONFS(dvp);
 3091         caddr_t bpos, dpos, cp2;
 3092         int error = 0, fhlen;
 3093 #ifndef NFS_V2_ONLY
 3094         int attrflag;
 3095 #endif
 3096         struct mbuf *mreq, *mrep, *md, *mb;
 3097         nfsfh_t *nfhp;
 3098         const int v3 = NFS_ISV3(dvp);
 3099 
 3100         nfsstats.rpccnt[NFSPROC_LOOKUP]++;
 3101         nfsm_reqhead(dnp, NFSPROC_LOOKUP,
 3102                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
 3103         nfsm_fhtom(dnp, v3);
 3104         nfsm_strtom(name, len, NFS_MAXNAMLEN);
 3105         nfsm_request(dnp, NFSPROC_LOOKUP, l, cred);
 3106         if (npp && !error) {
 3107                 nfsm_getfh(nfhp, fhlen, v3);
 3108                 if (*npp) {
 3109                     np = *npp;
 3110                     if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
 3111                         free((caddr_t)np->n_fhp, M_NFSBIGFH);
 3112                         np->n_fhp = &np->n_fh;
 3113                     }
 3114 #if NFS_SMALLFH < NFSX_V3FHMAX
 3115                     else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
 3116                         np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK);
 3117 #endif
 3118                     memcpy((caddr_t)np->n_fhp, (caddr_t)nfhp, fhlen);
 3119                     np->n_fhsize = fhlen;
 3120                     newvp = NFSTOV(np);
 3121                 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
 3122                     VREF(dvp);
 3123                     newvp = dvp;
 3124                     np = dnp;
 3125                 } else {
 3126                     error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
 3127                     if (error) {
 3128                         m_freem(mrep);
 3129                         return (error);
 3130                     }
 3131                     newvp = NFSTOV(np);
 3132                 }
 3133 #ifndef NFS_V2_ONLY
 3134                 if (v3) {
 3135                         nfsm_postop_attr(newvp, attrflag, 0);
 3136                         if (!attrflag && *npp == NULL) {
 3137                                 m_freem(mrep);
 3138                                 vput(newvp);
 3139                                 return (ENOENT);
 3140                         }
 3141                 } else
 3142 #endif
 3143                         nfsm_loadattr(newvp, (struct vattr *)0, 0);
 3144         }
 3145         nfsm_reqdone;
 3146         if (npp && *npp == NULL) {
 3147                 if (error) {
 3148                         if (newvp)
 3149                                 vput(newvp);
 3150                 } else
 3151                         *npp = np;
 3152         }
 3153         return (error);
 3154 }
 3155 
 3156 #ifndef NFS_V2_ONLY
 3157 /*
 3158  * Nfs Version 3 commit rpc
 3159  */
 3160 int
 3161 nfs_commit(vp, offset, cnt, l)
 3162         struct vnode *vp;
 3163         off_t offset;
 3164         uint32_t cnt;
 3165         struct lwp *l;
 3166 {
 3167         caddr_t cp;
 3168         u_int32_t *tl;
 3169         int32_t t1, t2;
 3170         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
 3171         caddr_t bpos, dpos, cp2;
 3172         int error = 0, wccflag = NFSV3_WCCRATTR;
 3173         struct mbuf *mreq, *mrep, *md, *mb;
 3174         struct nfsnode *np;
 3175 
 3176         KASSERT(NFS_ISV3(vp));
 3177 
 3178 #ifdef NFS_DEBUG_COMMIT
 3179         printf("commit %lu - %lu\n", (unsigned long)offset,
 3180             (unsigned long)(offset + cnt));
 3181 #endif
 3182 
 3183         simple_lock(&nmp->nm_slock);
 3184         if ((nmp->nm_iflag & NFSMNT_HASWRITEVERF) == 0) {
 3185                 simple_unlock(&nmp->nm_slock);
 3186                 return (0);
 3187         }
 3188         simple_unlock(&nmp->nm_slock);
 3189         nfsstats.rpccnt[NFSPROC_COMMIT]++;
 3190         np = VTONFS(vp);
 3191         nfsm_reqhead(np, NFSPROC_COMMIT, NFSX_FH(1));
 3192         nfsm_fhtom(np, 1);
 3193         nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
 3194         txdr_hyper(offset, tl);
 3195         tl += 2;
 3196         *tl = txdr_unsigned(cnt);
 3197         nfsm_request(np, NFSPROC_COMMIT, l, np->n_wcred);
 3198         nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC, FALSE);
 3199         if (!error) {
 3200                 nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
 3201                 simple_lock(&nmp->nm_slock);
 3202                 if ((nmp->nm_iflag & NFSMNT_STALEWRITEVERF) ||
 3203                     memcmp(nmp->nm_writeverf, tl, NFSX_V3WRITEVERF)) {
 3204                         memcpy(nmp->nm_writeverf, tl, NFSX_V3WRITEVERF);
 3205                         error = NFSERR_STALEWRITEVERF;
 3206                         nmp->nm_iflag |= NFSMNT_STALEWRITEVERF;
 3207                 }
 3208                 simple_unlock(&nmp->nm_slock);
 3209         }
 3210         nfsm_reqdone;
 3211         return (error);
 3212 }
 3213 #endif
 3214 
 3215 /*
 3216  * Kludge City..
 3217  * - make nfs_bmap() essentially a no-op that does no translation
 3218  * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
 3219  *   (Maybe I could use the process's page mapping, but I was concerned that
 3220  *    Kernel Write might not be enabled and also figured copyout() would do
 3221  *    a lot more work than memcpy() and also it currently happens in the
 3222  *    context of the swapper process (2).
 3223  */
 3224 int
 3225 nfs_bmap(v)
 3226         void *v;
 3227 {
 3228         struct vop_bmap_args /* {
 3229                 struct vnode *a_vp;
 3230                 daddr_t  a_bn;
 3231                 struct vnode **a_vpp;
 3232                 daddr_t *a_bnp;
 3233                 int *a_runp;
 3234         } */ *ap = v;
 3235         struct vnode *vp = ap->a_vp;
 3236         int bshift = vp->v_mount->mnt_fs_bshift - vp->v_mount->mnt_dev_bshift;
 3237 
 3238         if (ap->a_vpp != NULL)
 3239                 *ap->a_vpp = vp;
 3240         if (ap->a_bnp != NULL)
 3241                 *ap->a_bnp = ap->a_bn << bshift;
 3242         if (ap->a_runp != NULL)
 3243                 *ap->a_runp = 1024 * 1024; /* XXX */
 3244         return (0);
 3245 }
 3246 
 3247 /*
 3248  * Strategy routine.
 3249  * For async requests when nfsiod(s) are running, queue the request by
 3250  * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
 3251  * request.
 3252  */
 3253 int
 3254 nfs_strategy(v)
 3255         void *v;
 3256 {
 3257         struct vop_strategy_args *ap = v;
 3258         struct buf *bp = ap->a_bp;
 3259         int error = 0;
 3260 
 3261         if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC))
 3262                 panic("nfs physio/async");
 3263 
 3264         /*
 3265          * If the op is asynchronous and an i/o daemon is waiting
 3266          * queue the request, wake it up and wait for completion
 3267          * otherwise just do it ourselves.
 3268          */
 3269         if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp))
 3270                 error = nfs_doio(bp);
 3271         return (error);
 3272 }
 3273 
 3274 /*
 3275  * fsync vnode op. Just call nfs_flush() with commit == 1.
 3276  */
 3277 /* ARGSUSED */
 3278 int
 3279 nfs_fsync(v)
 3280         void *v;
 3281 {
 3282         struct vop_fsync_args /* {
 3283                 struct vnodeop_desc *a_desc;
 3284                 struct vnode * a_vp;
 3285                 kauth_cred_t  a_cred;
 3286                 int  a_flags;
 3287                 off_t offlo;
 3288                 off_t offhi;
 3289                 struct lwp * a_l;
 3290         } */ *ap = v;
 3291 
 3292         struct vnode *vp = ap->a_vp;
 3293 
 3294         if (vp->v_type != VREG)
 3295                 return 0;
 3296 
 3297         return (nfs_flush(vp, ap->a_cred,
 3298             (ap->a_flags & FSYNC_WAIT) != 0 ? MNT_WAIT : 0, ap->a_l, 1));
 3299 }
 3300 
 3301 /*
 3302  * Flush all the data associated with a vnode.
 3303  */
 3304 int
 3305 nfs_flush(struct vnode *vp, kauth_cred_t cred, int waitfor, struct lwp *l,
 3306     int commit)
 3307 {
 3308         struct nfsnode *np = VTONFS(vp);
 3309         int error;
 3310         int flushflags = PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO;
 3311         UVMHIST_FUNC("nfs_flush"); UVMHIST_CALLED(ubchist);
 3312 
 3313         simple_lock(&vp->v_interlock);
 3314         error = VOP_PUTPAGES(vp, 0, 0, flushflags);
 3315         if (np->n_flag & NWRITEERR) {
 3316                 error = np->n_error;
 3317                 np->n_flag &= ~NWRITEERR;
 3318         }
 3319         UVMHIST_LOG(ubchist, "returning %d", error,0,0,0);
 3320         return (error);
 3321 }
 3322 
 3323 /*
 3324  * Return POSIX pathconf information applicable to nfs.
 3325  *
 3326  * N.B. The NFS V2 protocol doesn't support this RPC.
 3327  */
 3328 /* ARGSUSED */
 3329 int
 3330 nfs_pathconf(v)
 3331         void *v;
 3332 {
 3333         struct vop_pathconf_args /* {
 3334                 struct vnode *a_vp;
 3335                 int a_name;
 3336                 register_t *a_retval;
 3337         } */ *ap = v;
 3338         struct nfsv3_pathconf *pcp;
 3339         struct vnode *vp = ap->a_vp;
 3340         struct mbuf *mreq, *mrep, *md, *mb;
 3341         int32_t t1, t2;
 3342         u_int32_t *tl;
 3343         caddr_t bpos, dpos, cp, cp2;
 3344         int error = 0, attrflag;
 3345 #ifndef NFS_V2_ONLY
 3346         struct nfsmount *nmp;
 3347         unsigned int l;
 3348         u_int64_t maxsize;
 3349 #endif
 3350         const int v3 = NFS_ISV3(vp);
 3351         struct nfsnode *np = VTONFS(vp);
 3352 
 3353         switch (ap->a_name) {
 3354                 /* Names that can be resolved locally. */
 3355         case _PC_PIPE_BUF:
 3356                 *ap->a_retval = PIPE_BUF;
 3357                 break;
 3358         case _PC_SYNC_IO:
 3359                 *ap->a_retval = 1;
 3360                 break;
 3361         /* Names that cannot be resolved locally; do an RPC, if possible. */
 3362         case _PC_LINK_MAX:
 3363         case _PC_NAME_MAX:
 3364         case _PC_CHOWN_RESTRICTED:
 3365         case _PC_NO_TRUNC:
 3366                 if (!v3) {
 3367                         error = EINVAL;
 3368                         break;
 3369                 }
 3370                 nfsstats.rpccnt[NFSPROC_PATHCONF]++;
 3371                 nfsm_reqhead(np, NFSPROC_PATHCONF, NFSX_FH(1));
 3372                 nfsm_fhtom(np, 1);
 3373                 nfsm_request(np, NFSPROC_PATHCONF,
 3374                     curlwp, curlwp->l_cred);    /* XXX */
 3375                 nfsm_postop_attr(vp, attrflag, 0);
 3376                 if (!error) {
 3377                         nfsm_dissect(pcp, struct nfsv3_pathconf *,
 3378                             NFSX_V3PATHCONF);
 3379                         switch (ap->a_name) {
 3380                         case _PC_LINK_MAX:
 3381                                 *ap->a_retval =
 3382                                     fxdr_unsigned(register_t, pcp->pc_linkmax);
 3383                                 break;
 3384                         case _PC_NAME_MAX:
 3385                                 *ap->a_retval =
 3386                                     fxdr_unsigned(register_t, pcp->pc_namemax);
 3387                                 break;
 3388                         case _PC_CHOWN_RESTRICTED:
 3389                                 *ap->a_retval =
 3390                                     (pcp->pc_chownrestricted == nfs_true);
 3391                                 break;
 3392                         case _PC_NO_TRUNC:
 3393                                 *ap->a_retval =
 3394                                     (pcp->pc_notrunc == nfs_true);
 3395                                 break;
 3396                         }
 3397                 }
 3398                 nfsm_reqdone;
 3399                 break;
 3400         case _PC_FILESIZEBITS:
 3401 #ifndef NFS_V2_ONLY
 3402                 if (v3) {
 3403                         nmp = VFSTONFS(vp->v_mount);
 3404                         if ((nmp->nm_iflag & NFSMNT_GOTFSINFO) == 0)
 3405                                 if ((error = nfs_fsinfo(nmp, vp,
 3406                                     curlwp->l_cred, curlwp)) != 0) /* XXX */
 3407                                         break;
 3408                         for (l = 0, maxsize = nmp->nm_maxfilesize;
 3409                             (maxsize >> l) > 0; l++)
 3410                                 ;
 3411                         *ap->a_retval = l + 1;
 3412                 } else
 3413 #endif
 3414                 {
 3415                         *ap->a_retval = 32;     /* NFS V2 limitation */
 3416                 }
 3417                 break;
 3418         default:
 3419                 error = EINVAL;
 3420                 break;
 3421         }
 3422 
 3423         return (error);
 3424 }
 3425 
 3426 /*
 3427  * NFS advisory byte-level locks.
 3428  */
 3429 int
 3430 nfs_advlock(v)
 3431         void *v;
 3432 {
 3433         struct vop_advlock_args /* {
 3434                 struct vnode *a_vp;
 3435                 caddr_t  a_id;
 3436                 int  a_op;
 3437                 struct flock *a_fl;
 3438                 int  a_flags;
 3439         } */ *ap = v;
 3440         struct nfsnode *np = VTONFS(ap->a_vp);
 3441 
 3442         return lf_advlock(ap, &np->n_lockf, np->n_size);
 3443 }
 3444 
 3445 /*
 3446  * Print out the contents of an nfsnode.
 3447  */
 3448 int
 3449 nfs_print(v)
 3450         void *v;
 3451 {
 3452         struct vop_print_args /* {
 3453                 struct vnode *a_vp;
 3454         } */ *ap = v;
 3455         struct vnode *vp = ap->a_vp;
 3456         struct nfsnode *np = VTONFS(vp);
 3457 
 3458         printf("tag VT_NFS, fileid %lld fsid 0x%lx",
 3459             (unsigned long long)np->n_vattr->va_fileid, np->n_vattr->va_fsid);
 3460         if (vp->v_type == VFIFO)
 3461                 fifo_printinfo(vp);
 3462         printf("\n");
 3463         return (0);
 3464 }
 3465 
 3466 /*
 3467  * nfs unlock wrapper.
 3468  */
 3469 int
 3470 nfs_unlock(void *v)
 3471 {
 3472         struct vop_unlock_args /* {
 3473                 struct vnode *a_vp;
 3474                 int a_flags;
 3475         } */ *ap = v;
 3476         struct vnode *vp = ap->a_vp;
 3477 
 3478         /*
 3479          * VOP_UNLOCK can be called by nfs_loadattrcache
 3480          * with v_data == 0.
 3481          */
 3482         if (VTONFS(vp)) {
 3483                 nfs_delayedtruncate(vp);
 3484         }
 3485 
 3486         return genfs_unlock(v);
 3487 }
 3488 
 3489 /*
 3490  * nfs special file access vnode op.
 3491  * Essentially just get vattr and then imitate iaccess() since the device is
 3492  * local to the client.
 3493  */
 3494 int
 3495 nfsspec_access(v)
 3496         void *v;
 3497 {
 3498         struct vop_access_args /* {
 3499                 struct vnode *a_vp;
 3500                 int  a_mode;
 3501                 kauth_cred_t a_cred;
 3502                 struct lwp *a_l;
 3503         } */ *ap = v;
 3504         struct vattr va;
 3505         struct vnode *vp = ap->a_vp;
 3506         int error;
 3507 
 3508         error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_l);
 3509         if (error)
 3510                 return (error);
 3511 
 3512         /*
 3513          * Disallow write attempts on filesystems mounted read-only;
 3514          * unless the file is a socket, fifo, or a block or character
 3515          * device resident on the filesystem.
 3516          */
 3517         if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
 3518                 switch (vp->v_type) {
 3519                 case VREG:
 3520                 case VDIR:
 3521                 case VLNK:
 3522                         return (EROFS);
 3523                 default:
 3524                         break;
 3525                 }
 3526         }
 3527 
 3528         return (vaccess(va.va_type, va.va_mode,
 3529             va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
 3530 }
 3531 
 3532 /*
 3533  * Read wrapper for special devices.
 3534  */
 3535 int
 3536 nfsspec_read(v)
 3537         void *v;
 3538 {
 3539         struct vop_read_args /* {
 3540                 struct vnode *a_vp;
 3541                 struct uio *a_uio;
 3542                 int  a_ioflag;
 3543                 kauth_cred_t a_cred;
 3544         } */ *ap = v;
 3545         struct nfsnode *np = VTONFS(ap->a_vp);
 3546 
 3547         /*
 3548          * Set access flag.
 3549          */
 3550         np->n_flag |= NACC;
 3551         getnanotime(&np->n_atim);
 3552         return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
 3553 }
 3554 
 3555 /*
 3556  * Write wrapper for special devices.
 3557  */
 3558 int
 3559 nfsspec_write(v)
 3560         void *v;
 3561 {
 3562         struct vop_write_args /* {
 3563                 struct vnode *a_vp;
 3564                 struct uio *a_uio;
 3565                 int  a_ioflag;
 3566                 kauth_cred_t a_cred;
 3567         } */ *ap = v;
 3568         struct nfsnode *np = VTONFS(ap->a_vp);
 3569 
 3570         /*
 3571          * Set update flag.
 3572          */
 3573         np->n_flag |= NUPD;
 3574         getnanotime(&np->n_mtim);
 3575         return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
 3576 }
 3577 
 3578 /*
 3579  * Close wrapper for special devices.
 3580  *
 3581  * Update the times on the nfsnode then do device close.
 3582  */
 3583 int
 3584 nfsspec_close(v)
 3585         void *v;
 3586 {
 3587         struct vop_close_args /* {
 3588                 struct vnode *a_vp;
 3589                 int  a_fflag;
 3590                 kauth_cred_t a_cred;
 3591                 struct lwp *a_l;
 3592         } */ *ap = v;
 3593         struct vnode *vp = ap->a_vp;
 3594         struct nfsnode *np = VTONFS(vp);
 3595         struct vattr vattr;
 3596 
 3597         if (np->n_flag & (NACC | NUPD)) {
 3598                 np->n_flag |= NCHG;
 3599                 if (vp->v_usecount == 1 &&
 3600                     (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
 3601                         VATTR_NULL(&vattr);
 3602                         if (np->n_flag & NACC)
 3603                                 vattr.va_atime = np->n_atim;
 3604                         if (np->n_flag & NUPD)
 3605                                 vattr.va_mtime = np->n_mtim;
 3606                         (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_l);
 3607                 }
 3608         }
 3609         return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
 3610 }
 3611 
 3612 /*
 3613  * Read wrapper for fifos.
 3614  */
 3615 int
 3616 nfsfifo_read(v)
 3617         void *v;
 3618 {
 3619         struct vop_read_args /* {
 3620                 struct vnode *a_vp;
 3621                 struct uio *a_uio;
 3622                 int  a_ioflag;
 3623                 kauth_cred_t a_cred;
 3624         } */ *ap = v;
 3625         struct nfsnode *np = VTONFS(ap->a_vp);
 3626 
 3627         /*
 3628          * Set access flag.
 3629          */
 3630         np->n_flag |= NACC;
 3631         getnanotime(&np->n_atim);
 3632         return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
 3633 }
 3634 
 3635 /*
 3636  * Write wrapper for fifos.
 3637  */
 3638 int
 3639 nfsfifo_write(v)
 3640         void *v;
 3641 {
 3642         struct vop_write_args /* {
 3643                 struct vnode *a_vp;
 3644                 struct uio *a_uio;
 3645                 int  a_ioflag;
 3646                 kauth_cred_t a_cred;
 3647         } */ *ap = v;
 3648         struct nfsnode *np = VTONFS(ap->a_vp);
 3649 
 3650         /*
 3651          * Set update flag.
 3652          */
 3653         np->n_flag |= NUPD;
 3654         getnanotime(&np->n_mtim);
 3655         return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
 3656 }
 3657 
 3658 /*
 3659  * Close wrapper for fifos.
 3660  *
 3661  * Update the times on the nfsnode then do fifo close.
 3662  */
 3663 int
 3664 nfsfifo_close(v)
 3665         void *v;
 3666 {
 3667         struct vop_close_args /* {
 3668                 struct vnode *a_vp;
 3669                 int  a_fflag;
 3670                 kauth_cred_t a_cred;
 3671                 struct lwp *a_l;
 3672         } */ *ap = v;
 3673         struct vnode *vp = ap->a_vp;
 3674         struct nfsnode *np = VTONFS(vp);
 3675         struct vattr vattr;
 3676 
 3677         if (np->n_flag & (NACC | NUPD)) {
 3678                 struct timespec ts;
 3679 
 3680                 getnanotime(&ts);
 3681                 if (np->n_flag & NACC)
 3682                         np->n_atim = ts;
 3683                 if (np->n_flag & NUPD)
 3684                         np->n_mtim = ts;
 3685                 np->n_flag |= NCHG;
 3686                 if (vp->v_usecount == 1 &&
 3687                     (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
 3688                         VATTR_NULL(&vattr);
 3689                         if (np->n_flag & NACC)
 3690                                 vattr.va_atime = np->n_atim;
 3691                         if (np->n_flag & NUPD)
 3692                                 vattr.va_mtime = np->n_mtim;
 3693                         (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_l);
 3694                 }
 3695         }
 3696         return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
 3697 }

Cache object: f67eb2ae5fd9b8837219e4298de77b52


[ 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.