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/fs/nfsclient/nfs_clvfsops.c

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

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1989, 1993, 1995
    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  *      from nfs_vfsops.c       8.12 (Berkeley) 5/20/95
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD: stable/12/sys/fs/nfsclient/nfs_clvfsops.c 371026 2021-11-17 01:48:03Z rmacklem $");
   39 
   40 
   41 #include "opt_bootp.h"
   42 #include "opt_nfsroot.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/bio.h>
   48 #include <sys/buf.h>
   49 #include <sys/clock.h>
   50 #include <sys/jail.h>
   51 #include <sys/limits.h>
   52 #include <sys/lock.h>
   53 #include <sys/malloc.h>
   54 #include <sys/mbuf.h>
   55 #include <sys/module.h>
   56 #include <sys/mount.h>
   57 #include <sys/proc.h>
   58 #include <sys/socket.h>
   59 #include <sys/socketvar.h>
   60 #include <sys/sockio.h>
   61 #include <sys/sysctl.h>
   62 #include <sys/vnode.h>
   63 #include <sys/signalvar.h>
   64 
   65 #include <vm/vm.h>
   66 #include <vm/vm_extern.h>
   67 #include <vm/uma.h>
   68 
   69 #include <net/if.h>
   70 #include <net/route.h>
   71 #include <netinet/in.h>
   72 
   73 #include <fs/nfs/nfsport.h>
   74 #include <fs/nfsclient/nfsnode.h>
   75 #include <fs/nfsclient/nfsmount.h>
   76 #include <fs/nfsclient/nfs.h>
   77 #include <nfs/nfsdiskless.h>
   78 
   79 FEATURE(nfscl, "NFSv4 client");
   80 
   81 extern int nfscl_ticks;
   82 extern struct timeval nfsboottime;
   83 extern int nfsrv_useacl;
   84 extern int nfscl_debuglevel;
   85 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
   86 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
   87 extern struct mtx ncl_iod_mutex;
   88 NFSCLSTATEMUTEX;
   89 extern struct mtx nfsrv_dslock_mtx;
   90 
   91 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
   92 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
   93 
   94 SYSCTL_DECL(_vfs_nfs);
   95 static int nfs_ip_paranoia = 1;
   96 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
   97     &nfs_ip_paranoia, 0, "");
   98 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
   99 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
  100         downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
  101 /* how long between console messages "nfs server foo not responding" */
  102 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
  103 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
  104         downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
  105 #ifdef NFS_DEBUG
  106 int nfs_debug;
  107 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
  108     "Toggle debug flag");
  109 #endif
  110 
  111 static int      nfs_mountroot(struct mount *);
  112 static void     nfs_sec_name(char *, int *);
  113 static void     nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
  114                     struct nfs_args *argp, const char *, struct ucred *,
  115                     struct thread *);
  116 static int      mountnfs(struct nfs_args *, struct mount *,
  117                     struct sockaddr *, char *, u_char *, int, u_char *, int,
  118                     u_char *, int, struct vnode **, struct ucred *,
  119                     struct thread *, int, int, int);
  120 static void     nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
  121                     struct sockaddr_storage *, int *, off_t *,
  122                     struct timeval *);
  123 static vfs_mount_t nfs_mount;
  124 static vfs_cmount_t nfs_cmount;
  125 static vfs_unmount_t nfs_unmount;
  126 static vfs_root_t nfs_root;
  127 static vfs_statfs_t nfs_statfs;
  128 static vfs_sync_t nfs_sync;
  129 static vfs_sysctl_t nfs_sysctl;
  130 static vfs_purge_t nfs_purge;
  131 
  132 /*
  133  * nfs vfs operations.
  134  */
  135 static struct vfsops nfs_vfsops = {
  136         .vfs_init =             ncl_init,
  137         .vfs_mount =            nfs_mount,
  138         .vfs_cmount =           nfs_cmount,
  139         .vfs_root =             nfs_root,
  140         .vfs_statfs =           nfs_statfs,
  141         .vfs_sync =             nfs_sync,
  142         .vfs_uninit =           ncl_uninit,
  143         .vfs_unmount =          nfs_unmount,
  144         .vfs_sysctl =           nfs_sysctl,
  145         .vfs_purge =            nfs_purge,
  146 };
  147 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
  148 
  149 /* So that loader and kldload(2) can find us, wherever we are.. */
  150 MODULE_VERSION(nfs, 1);
  151 MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
  152 MODULE_DEPEND(nfs, krpc, 1, 1, 1);
  153 MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
  154 MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
  155 MODULE_DEPEND(nfs, xdr, 1, 1, 1);
  156 
  157 /*
  158  * This structure is now defined in sys/nfs/nfs_diskless.c so that it
  159  * can be shared by both NFS clients. It is declared here so that it
  160  * will be defined for kernels built without NFS_ROOT, although it
  161  * isn't used in that case.
  162  */
  163 #if !defined(NFS_ROOT)
  164 struct nfs_diskless     nfs_diskless = { { { 0 } } };
  165 struct nfsv3_diskless   nfsv3_diskless = { { { 0 } } };
  166 int                     nfs_diskless_valid = 0;
  167 #endif
  168 
  169 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
  170     &nfs_diskless_valid, 0,
  171     "Has the diskless struct been filled correctly");
  172 
  173 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
  174     nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
  175 
  176 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
  177     &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
  178     "%Ssockaddr_in", "Diskless root nfs address");
  179 
  180 
  181 void            newnfsargs_ntoh(struct nfs_args *);
  182 static int      nfs_mountdiskless(char *,
  183                     struct sockaddr_in *, struct nfs_args *,
  184                     struct thread *, struct vnode **, struct mount *);
  185 static void     nfs_convert_diskless(void);
  186 static void     nfs_convert_oargs(struct nfs_args *args,
  187                     struct onfs_args *oargs);
  188 
  189 int
  190 newnfs_iosize(struct nfsmount *nmp)
  191 {
  192         int iosize, maxio;
  193 
  194         /* First, set the upper limit for iosize */
  195         if (nmp->nm_flag & NFSMNT_NFSV4) {
  196                 maxio = NFS_MAXBSIZE;
  197         } else if (nmp->nm_flag & NFSMNT_NFSV3) {
  198                 if (nmp->nm_sotype == SOCK_DGRAM)
  199                         maxio = NFS_MAXDGRAMDATA;
  200                 else
  201                         maxio = NFS_MAXBSIZE;
  202         } else {
  203                 maxio = NFS_V2MAXDATA;
  204         }
  205         if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
  206                 nmp->nm_rsize = maxio;
  207         if (nmp->nm_rsize > NFS_MAXBSIZE)
  208                 nmp->nm_rsize = NFS_MAXBSIZE;
  209         if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
  210                 nmp->nm_readdirsize = maxio;
  211         if (nmp->nm_readdirsize > nmp->nm_rsize)
  212                 nmp->nm_readdirsize = nmp->nm_rsize;
  213         if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
  214                 nmp->nm_wsize = maxio;
  215         if (nmp->nm_wsize > NFS_MAXBSIZE)
  216                 nmp->nm_wsize = NFS_MAXBSIZE;
  217 
  218         /*
  219          * Calculate the size used for io buffers.  Use the larger
  220          * of the two sizes to minimise nfs requests but make sure
  221          * that it is at least one VM page to avoid wasting buffer
  222          * space.  It must also be at least NFS_DIRBLKSIZ, since
  223          * that is the buffer size used for directories.
  224          */
  225         iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
  226         iosize = imax(iosize, PAGE_SIZE);
  227         iosize = imax(iosize, NFS_DIRBLKSIZ);
  228         nmp->nm_mountp->mnt_stat.f_iosize = iosize;
  229         return (iosize);
  230 }
  231 
  232 static void
  233 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
  234 {
  235 
  236         args->version = NFS_ARGSVERSION;
  237         args->addr = oargs->addr;
  238         args->addrlen = oargs->addrlen;
  239         args->sotype = oargs->sotype;
  240         args->proto = oargs->proto;
  241         args->fh = oargs->fh;
  242         args->fhsize = oargs->fhsize;
  243         args->flags = oargs->flags;
  244         args->wsize = oargs->wsize;
  245         args->rsize = oargs->rsize;
  246         args->readdirsize = oargs->readdirsize;
  247         args->timeo = oargs->timeo;
  248         args->retrans = oargs->retrans;
  249         args->readahead = oargs->readahead;
  250         args->hostname = oargs->hostname;
  251 }
  252 
  253 static void
  254 nfs_convert_diskless(void)
  255 {
  256 
  257         bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
  258                 sizeof(struct ifaliasreq));
  259         bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
  260                 sizeof(struct sockaddr_in));
  261         nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
  262         if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
  263                 nfsv3_diskless.root_fhsize = NFSX_MYFH;
  264                 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
  265         } else {
  266                 nfsv3_diskless.root_fhsize = NFSX_V2FH;
  267                 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
  268         }
  269         bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
  270                 sizeof(struct sockaddr_in));
  271         bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
  272         nfsv3_diskless.root_time = nfs_diskless.root_time;
  273         bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
  274                 MAXHOSTNAMELEN);
  275         nfs_diskless_valid = 3;
  276 }
  277 
  278 /*
  279  * nfs statfs call
  280  */
  281 static int
  282 nfs_statfs(struct mount *mp, struct statfs *sbp)
  283 {
  284         struct vnode *vp;
  285         struct thread *td;
  286         struct nfsmount *nmp = VFSTONFS(mp);
  287         struct nfsvattr nfsva;
  288         struct nfsfsinfo fs;
  289         struct nfsstatfs sb;
  290         int error = 0, attrflag, gotfsinfo = 0, ret;
  291         struct nfsnode *np;
  292 
  293         td = curthread;
  294 
  295         error = vfs_busy(mp, MBF_NOWAIT);
  296         if (error)
  297                 return (error);
  298         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
  299         if (error) {
  300                 vfs_unbusy(mp);
  301                 return (error);
  302         }
  303         vp = NFSTOV(np);
  304         mtx_lock(&nmp->nm_mtx);
  305         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
  306                 mtx_unlock(&nmp->nm_mtx);
  307                 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
  308                     &attrflag, NULL);
  309                 if (!error)
  310                         gotfsinfo = 1;
  311         } else
  312                 mtx_unlock(&nmp->nm_mtx);
  313         if (!error)
  314                 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
  315                     &attrflag, NULL);
  316         if (error != 0)
  317                 NFSCL_DEBUG(2, "statfs=%d\n", error);
  318         if (attrflag == 0) {
  319                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
  320                     td->td_ucred, td, &nfsva, NULL, NULL);
  321                 if (ret) {
  322                         /*
  323                          * Just set default values to get things going.
  324                          */
  325                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
  326                         nfsva.na_vattr.va_type = VDIR;
  327                         nfsva.na_vattr.va_mode = 0777;
  328                         nfsva.na_vattr.va_nlink = 100;
  329                         nfsva.na_vattr.va_uid = (uid_t)0;
  330                         nfsva.na_vattr.va_gid = (gid_t)0;
  331                         nfsva.na_vattr.va_fileid = 2;
  332                         nfsva.na_vattr.va_gen = 1;
  333                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
  334                         nfsva.na_vattr.va_size = 512 * 1024;
  335                 }
  336         }
  337         (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
  338         if (!error) {
  339             mtx_lock(&nmp->nm_mtx);
  340             if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
  341                 nfscl_loadfsinfo(nmp, &fs);
  342             nfscl_loadsbinfo(nmp, &sb, sbp);
  343             sbp->f_iosize = newnfs_iosize(nmp);
  344             mtx_unlock(&nmp->nm_mtx);
  345             if (sbp != &mp->mnt_stat) {
  346                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  347                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
  348             }
  349             strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
  350         } else if (NFS_ISV4(vp)) {
  351                 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
  352         }
  353         vput(vp);
  354         vfs_unbusy(mp);
  355         return (error);
  356 }
  357 
  358 /*
  359  * nfs version 3 fsinfo rpc call
  360  */
  361 int
  362 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
  363     struct thread *td)
  364 {
  365         struct nfsfsinfo fs;
  366         struct nfsvattr nfsva;
  367         int error, attrflag;
  368         
  369         error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
  370         if (!error) {
  371                 if (attrflag)
  372                         (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
  373                             1);
  374                 mtx_lock(&nmp->nm_mtx);
  375                 nfscl_loadfsinfo(nmp, &fs);
  376                 mtx_unlock(&nmp->nm_mtx);
  377         }
  378         return (error);
  379 }
  380 
  381 /*
  382  * Mount a remote root fs via. nfs. This depends on the info in the
  383  * nfs_diskless structure that has been filled in properly by some primary
  384  * bootstrap.
  385  * It goes something like this:
  386  * - do enough of "ifconfig" by calling ifioctl() so that the system
  387  *   can talk to the server
  388  * - If nfs_diskless.mygateway is filled in, use that address as
  389  *   a default gateway.
  390  * - build the rootfs mount point and call mountnfs() to do the rest.
  391  *
  392  * It is assumed to be safe to read, modify, and write the nfsv3_diskless
  393  * structure, as well as other global NFS client variables here, as
  394  * nfs_mountroot() will be called once in the boot before any other NFS
  395  * client activity occurs.
  396  */
  397 static int
  398 nfs_mountroot(struct mount *mp)
  399 {
  400         struct thread *td = curthread;
  401         struct nfsv3_diskless *nd = &nfsv3_diskless;
  402         struct socket *so;
  403         struct vnode *vp;
  404         struct ifreq ir;
  405         int error;
  406         u_long l;
  407         char buf[128];
  408         char *cp;
  409 
  410 #if defined(BOOTP_NFSROOT) && defined(BOOTP)
  411         bootpc_init();          /* use bootp to get nfs_diskless filled in */
  412 #elif defined(NFS_ROOT)
  413         nfs_setup_diskless();
  414 #endif
  415 
  416         if (nfs_diskless_valid == 0)
  417                 return (-1);
  418         if (nfs_diskless_valid == 1)
  419                 nfs_convert_diskless();
  420 
  421         /*
  422          * Do enough of ifconfig(8) so that the critical net interface can
  423          * talk to the server.
  424          */
  425         error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
  426             td->td_ucred, td);
  427         if (error)
  428                 panic("nfs_mountroot: socreate(%04x): %d",
  429                         nd->myif.ifra_addr.sa_family, error);
  430 
  431 #if 0 /* XXX Bad idea */
  432         /*
  433          * We might not have been told the right interface, so we pass
  434          * over the first ten interfaces of the same kind, until we get
  435          * one of them configured.
  436          */
  437 
  438         for (i = strlen(nd->myif.ifra_name) - 1;
  439                 nd->myif.ifra_name[i] >= '' &&
  440                 nd->myif.ifra_name[i] <= '9';
  441                 nd->myif.ifra_name[i] ++) {
  442                 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
  443                 if(!error)
  444                         break;
  445         }
  446 #endif
  447         error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
  448         if (error)
  449                 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
  450         if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
  451                 ir.ifr_mtu = strtol(cp, NULL, 10);
  452                 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
  453                 freeenv(cp);
  454                 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
  455                 if (error)
  456                         printf("nfs_mountroot: SIOCSIFMTU: %d", error);
  457         }
  458         soclose(so);
  459 
  460         /*
  461          * If the gateway field is filled in, set it as the default route.
  462          * Note that pxeboot will set a default route of 0 if the route
  463          * is not set by the DHCP server.  Check also for a value of 0
  464          * to avoid panicking inappropriately in that situation.
  465          */
  466         if (nd->mygateway.sin_len != 0 &&
  467             nd->mygateway.sin_addr.s_addr != 0) {
  468                 struct sockaddr_in mask, sin;
  469 
  470                 bzero((caddr_t)&mask, sizeof(mask));
  471                 sin = mask;
  472                 sin.sin_family = AF_INET;
  473                 sin.sin_len = sizeof(sin);
  474                 /* XXX MRT use table 0 for this sort of thing */
  475                 CURVNET_SET(TD_TO_VNET(td));
  476                 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
  477                     (struct sockaddr *)&nd->mygateway,
  478                     (struct sockaddr *)&mask,
  479                     RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
  480                 CURVNET_RESTORE();
  481                 if (error)
  482                         panic("nfs_mountroot: RTM_ADD: %d", error);
  483         }
  484 
  485         /*
  486          * Create the rootfs mount point.
  487          */
  488         nd->root_args.fh = nd->root_fh;
  489         nd->root_args.fhsize = nd->root_fhsize;
  490         l = ntohl(nd->root_saddr.sin_addr.s_addr);
  491         snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
  492                 (l >> 24) & 0xff, (l >> 16) & 0xff,
  493                 (l >>  8) & 0xff, (l >>  0) & 0xff, nd->root_hostnam);
  494         printf("NFS ROOT: %s\n", buf);
  495         nd->root_args.hostname = buf;
  496         if ((error = nfs_mountdiskless(buf,
  497             &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
  498                 return (error);
  499         }
  500 
  501         /*
  502          * This is not really an nfs issue, but it is much easier to
  503          * set hostname here and then let the "/etc/rc.xxx" files
  504          * mount the right /var based upon its preset value.
  505          */
  506         mtx_lock(&prison0.pr_mtx);
  507         strlcpy(prison0.pr_hostname, nd->my_hostnam,
  508             sizeof(prison0.pr_hostname));
  509         mtx_unlock(&prison0.pr_mtx);
  510         inittodr(ntohl(nd->root_time));
  511         return (0);
  512 }
  513 
  514 /*
  515  * Internal version of mount system call for diskless setup.
  516  */
  517 static int
  518 nfs_mountdiskless(char *path,
  519     struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
  520     struct vnode **vpp, struct mount *mp)
  521 {
  522         struct sockaddr *nam;
  523         int dirlen, error;
  524         char *dirpath;
  525 
  526         /*
  527          * Find the directory path in "path", which also has the server's
  528          * name/ip address in it.
  529          */
  530         dirpath = strchr(path, ':');
  531         if (dirpath != NULL)
  532                 dirlen = strlen(++dirpath);
  533         else
  534                 dirlen = 0;
  535         nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
  536         if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
  537             NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO, 
  538             NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
  539                 printf("nfs_mountroot: mount %s on /: %d\n", path, error);
  540                 return (error);
  541         }
  542         return (0);
  543 }
  544 
  545 static void
  546 nfs_sec_name(char *sec, int *flagsp)
  547 {
  548         if (!strcmp(sec, "krb5"))
  549                 *flagsp |= NFSMNT_KERB;
  550         else if (!strcmp(sec, "krb5i"))
  551                 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
  552         else if (!strcmp(sec, "krb5p"))
  553                 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
  554 }
  555 
  556 static void
  557 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
  558     const char *hostname, struct ucred *cred, struct thread *td)
  559 {
  560         int adjsock;
  561         char *p;
  562 
  563         /*
  564          * Set read-only flag if requested; otherwise, clear it if this is
  565          * an update.  If this is not an update, then either the read-only
  566          * flag is already clear, or this is a root mount and it was set
  567          * intentionally at some previous point.
  568          */
  569         if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
  570                 MNT_ILOCK(mp);
  571                 mp->mnt_flag |= MNT_RDONLY;
  572                 MNT_IUNLOCK(mp);
  573         } else if (mp->mnt_flag & MNT_UPDATE) {
  574                 MNT_ILOCK(mp);
  575                 mp->mnt_flag &= ~MNT_RDONLY;
  576                 MNT_IUNLOCK(mp);
  577         }
  578 
  579         /*
  580          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
  581          * no sense in that context.  Also, set up appropriate retransmit
  582          * and soft timeout behavior.
  583          */
  584         if (argp->sotype == SOCK_STREAM) {
  585                 nmp->nm_flag &= ~NFSMNT_NOCONN;
  586                 nmp->nm_timeo = NFS_MAXTIMEO;
  587                 if ((argp->flags & NFSMNT_NFSV4) != 0)
  588                         nmp->nm_retry = INT_MAX;
  589                 else
  590                         nmp->nm_retry = NFS_RETRANS_TCP;
  591         }
  592 
  593         /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
  594         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
  595                 argp->flags &= ~NFSMNT_RDIRPLUS;
  596                 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
  597         }
  598 
  599         /* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */
  600         if (nmp->nm_minorvers == 0) {
  601                 argp->flags &= ~NFSMNT_ONEOPENOWN;
  602                 nmp->nm_flag &= ~NFSMNT_ONEOPENOWN;
  603         }
  604 
  605         /* Re-bind if rsrvd port requested and wasn't on one */
  606         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
  607                   && (argp->flags & NFSMNT_RESVPORT);
  608         /* Also re-bind if we're switching to/from a connected UDP socket */
  609         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
  610                     (argp->flags & NFSMNT_NOCONN));
  611 
  612         /* Update flags atomically.  Don't change the lock bits. */
  613         nmp->nm_flag = argp->flags | nmp->nm_flag;
  614 
  615         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
  616                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
  617                 if (nmp->nm_timeo < NFS_MINTIMEO)
  618                         nmp->nm_timeo = NFS_MINTIMEO;
  619                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
  620                         nmp->nm_timeo = NFS_MAXTIMEO;
  621         }
  622 
  623         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
  624                 nmp->nm_retry = argp->retrans;
  625                 if (nmp->nm_retry > NFS_MAXREXMIT)
  626                         nmp->nm_retry = NFS_MAXREXMIT;
  627         }
  628 
  629         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
  630                 nmp->nm_wsize = argp->wsize;
  631                 /*
  632                  * Clip at the power of 2 below the size. There is an
  633                  * issue (not isolated) that causes intermittent page
  634                  * faults if this is not done.
  635                  */
  636                 if (nmp->nm_wsize > NFS_FABLKSIZE)
  637                         nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
  638                 else
  639                         nmp->nm_wsize = NFS_FABLKSIZE;
  640         }
  641 
  642         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
  643                 nmp->nm_rsize = argp->rsize;
  644                 /*
  645                  * Clip at the power of 2 below the size. There is an
  646                  * issue (not isolated) that causes intermittent page
  647                  * faults if this is not done.
  648                  */
  649                 if (nmp->nm_rsize > NFS_FABLKSIZE)
  650                         nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
  651                 else
  652                         nmp->nm_rsize = NFS_FABLKSIZE;
  653         }
  654 
  655         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
  656                 nmp->nm_readdirsize = argp->readdirsize;
  657         }
  658 
  659         if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
  660                 nmp->nm_acregmin = argp->acregmin;
  661         else
  662                 nmp->nm_acregmin = NFS_MINATTRTIMO;
  663         if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
  664                 nmp->nm_acregmax = argp->acregmax;
  665         else
  666                 nmp->nm_acregmax = NFS_MAXATTRTIMO;
  667         if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
  668                 nmp->nm_acdirmin = argp->acdirmin;
  669         else
  670                 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
  671         if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
  672                 nmp->nm_acdirmax = argp->acdirmax;
  673         else
  674                 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
  675         if (nmp->nm_acdirmin > nmp->nm_acdirmax)
  676                 nmp->nm_acdirmin = nmp->nm_acdirmax;
  677         if (nmp->nm_acregmin > nmp->nm_acregmax)
  678                 nmp->nm_acregmin = nmp->nm_acregmax;
  679 
  680         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
  681                 if (argp->readahead <= NFS_MAXRAHEAD)
  682                         nmp->nm_readahead = argp->readahead;
  683                 else
  684                         nmp->nm_readahead = NFS_MAXRAHEAD;
  685         }
  686         if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
  687                 if (argp->wcommitsize < nmp->nm_wsize)
  688                         nmp->nm_wcommitsize = nmp->nm_wsize;
  689                 else
  690                         nmp->nm_wcommitsize = argp->wcommitsize;
  691         }
  692 
  693         adjsock |= ((nmp->nm_sotype != argp->sotype) ||
  694                     (nmp->nm_soproto != argp->proto));
  695 
  696         if (nmp->nm_client != NULL && adjsock) {
  697                 int haslock = 0, error = 0;
  698 
  699                 if (nmp->nm_sotype == SOCK_STREAM) {
  700                         error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
  701                         if (!error)
  702                                 haslock = 1;
  703                 }
  704                 if (!error) {
  705                     newnfs_disconnect(&nmp->nm_sockreq);
  706                     if (haslock)
  707                         newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
  708                     nmp->nm_sotype = argp->sotype;
  709                     nmp->nm_soproto = argp->proto;
  710                     if (nmp->nm_sotype == SOCK_DGRAM)
  711                         while (newnfs_connect(nmp, &nmp->nm_sockreq,
  712                             cred, td, 0)) {
  713                                 printf("newnfs_args: retrying connect\n");
  714                                 (void) nfs_catnap(PSOCK, 0, "nfscon");
  715                         }
  716                 }
  717         } else {
  718                 nmp->nm_sotype = argp->sotype;
  719                 nmp->nm_soproto = argp->proto;
  720         }
  721 
  722         if (hostname != NULL) {
  723                 strlcpy(nmp->nm_hostname, hostname,
  724                     sizeof(nmp->nm_hostname));
  725                 p = strchr(nmp->nm_hostname, ':');
  726                 if (p != NULL)
  727                         *p = '\0';
  728         }
  729 }
  730 
  731 static const char *nfs_opts[] = { "from", "nfs_args",
  732     "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
  733     "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
  734     "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
  735     "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
  736     "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
  737     "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
  738     "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
  739     "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
  740     "pnfs", "wcommitsize", "oneopenown",
  741     NULL };
  742 
  743 /*
  744  * Parse the "from" mountarg, passed by the generic mount(8) program
  745  * or the mountroot code.  This is used when rerooting into NFS.
  746  *
  747  * Note that the "hostname" is actually a "hostname:/share/path" string.
  748  */
  749 static int
  750 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
  751     struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
  752 {
  753         char *nam, *delimp, *hostp, *spec;
  754         int error, have_bracket = 0, offset, rv, speclen;
  755         struct sockaddr_in *sin;
  756         size_t len;
  757 
  758         error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
  759         if (error != 0)
  760                 return (error);
  761         nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK);
  762 
  763         /*
  764          * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
  765          */
  766         if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
  767             *(delimp + 1) == ':') {
  768                 hostp = spec + 1;
  769                 spec = delimp + 2;
  770                 have_bracket = 1;
  771         } else if ((delimp = strrchr(spec, ':')) != NULL) {
  772                 hostp = spec;
  773                 spec = delimp + 1;
  774         } else if ((delimp = strrchr(spec, '@')) != NULL) {
  775                 printf("%s: path@server syntax is deprecated, "
  776                     "use server:path\n", __func__);
  777                 hostp = delimp + 1;
  778         } else {
  779                 printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
  780                 free(nam, M_TEMP);
  781                 return (EINVAL);
  782         }
  783         *delimp = '\0';
  784 
  785         /*
  786          * If there has been a trailing slash at mounttime it seems
  787          * that some mountd implementations fail to remove the mount
  788          * entries from their mountlist while unmounting.
  789          */
  790         for (speclen = strlen(spec);
  791             speclen > 1 && spec[speclen - 1] == '/';
  792             speclen--)
  793                 spec[speclen - 1] = '\0';
  794         if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
  795                 printf("%s: %s:%s: name too long", __func__, hostp, spec);
  796                 free(nam, M_TEMP);
  797                 return (EINVAL);
  798         }
  799         /* Make both '@' and ':' notations equal */
  800         if (*hostp != '\0') {
  801                 len = strlen(hostp);
  802                 offset = 0;
  803                 if (have_bracket)
  804                         nam[offset++] = '[';
  805                 memmove(nam + offset, hostp, len);
  806                 if (have_bracket)
  807                         nam[len + offset++] = ']';
  808                 nam[len + offset++] = ':';
  809                 memmove(nam + len + offset, spec, speclen);
  810                 nam[len + speclen + offset] = '\0';
  811         } else
  812                 nam[0] = '\0';
  813 
  814         /*
  815          * XXX: IPv6
  816          */
  817         sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
  818         rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
  819         if (rv != 1) {
  820                 printf("%s: cannot parse '%s', inet_pton() returned %d\n",
  821                     __func__, hostp, rv);
  822                 free(nam, M_TEMP);
  823                 free(sin, M_SONAME);
  824                 return (EINVAL);
  825         }
  826 
  827         sin->sin_len = sizeof(*sin);
  828         sin->sin_family = AF_INET;
  829         /*
  830          * XXX: hardcoded port number.
  831          */
  832         sin->sin_port = htons(2049);
  833 
  834         *hostnamep = strdup(nam, M_NEWNFSMNT);
  835         *sinp = sin;
  836         strlcpy(dirpath, spec, dirpathsize);
  837         *dirlenp = strlen(dirpath);
  838 
  839         free(nam, M_TEMP);
  840         return (0);
  841 }
  842 
  843 /*
  844  * VFS Operations.
  845  *
  846  * mount system call
  847  * It seems a bit dumb to copyinstr() the host and path here and then
  848  * bcopy() them in mountnfs(), but I wanted to detect errors before
  849  * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
  850  * an error after that means that I have to release the mbuf.
  851  */
  852 /* ARGSUSED */
  853 static int
  854 nfs_mount(struct mount *mp)
  855 {
  856         struct nfs_args args = {
  857             .version = NFS_ARGSVERSION,
  858             .addr = NULL,
  859             .addrlen = sizeof (struct sockaddr_in),
  860             .sotype = SOCK_STREAM,
  861             .proto = 0,
  862             .fh = NULL,
  863             .fhsize = 0,
  864             .flags = NFSMNT_RESVPORT,
  865             .wsize = NFS_WSIZE,
  866             .rsize = NFS_RSIZE,
  867             .readdirsize = NFS_READDIRSIZE,
  868             .timeo = 10,
  869             .retrans = NFS_RETRANS,
  870             .readahead = NFS_DEFRAHEAD,
  871             .wcommitsize = 0,                   /* was: NQ_DEFLEASE */
  872             .hostname = NULL,
  873             .acregmin = NFS_MINATTRTIMO,
  874             .acregmax = NFS_MAXATTRTIMO,
  875             .acdirmin = NFS_MINDIRATTRTIMO,
  876             .acdirmax = NFS_MAXDIRATTRTIMO,
  877         };
  878         int error = 0, ret, len;
  879         struct sockaddr *nam = NULL;
  880         struct vnode *vp;
  881         struct thread *td;
  882         char *hst;
  883         u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
  884         char *cp, *opt, *name, *secname;
  885         int nametimeo = NFS_DEFAULT_NAMETIMEO;
  886         int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
  887         int minvers = 0;
  888         int dirlen, has_nfs_args_opt, has_nfs_from_opt,
  889             krbnamelen, srvkrbnamelen;
  890         size_t hstlen;
  891 
  892         has_nfs_args_opt = 0;
  893         has_nfs_from_opt = 0;
  894         hst = malloc(MNAMELEN, M_TEMP, M_WAITOK);
  895         if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
  896                 error = EINVAL;
  897                 goto out;
  898         }
  899 
  900         td = curthread;
  901         if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
  902             nfs_diskless_valid != 0) {
  903                 error = nfs_mountroot(mp);
  904                 goto out;
  905         }
  906 
  907         nfscl_init();
  908 
  909         /*
  910          * The old mount_nfs program passed the struct nfs_args
  911          * from userspace to kernel.  The new mount_nfs program
  912          * passes string options via nmount() from userspace to kernel
  913          * and we populate the struct nfs_args in the kernel.
  914          */
  915         if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
  916                 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
  917                     sizeof(args));
  918                 if (error != 0)
  919                         goto out;
  920 
  921                 if (args.version != NFS_ARGSVERSION) {
  922                         error = EPROGMISMATCH;
  923                         goto out;
  924                 }
  925                 has_nfs_args_opt = 1;
  926         }
  927 
  928         /* Handle the new style options. */
  929         if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
  930                 args.acdirmin = args.acdirmax =
  931                     args.acregmin = args.acregmax = 0;
  932                 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
  933                     NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
  934         }
  935         if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
  936                 args.flags |= NFSMNT_NOCONN;
  937         if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
  938                 args.flags &= ~NFSMNT_NOCONN;
  939         if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
  940                 args.flags |= NFSMNT_NOLOCKD;
  941         if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
  942                 args.flags &= ~NFSMNT_NOLOCKD;
  943         if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
  944                 args.flags |= NFSMNT_INT;
  945         if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
  946                 args.flags |= NFSMNT_RDIRPLUS;
  947         if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
  948                 args.flags |= NFSMNT_RESVPORT;
  949         if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
  950                 args.flags &= ~NFSMNT_RESVPORT;
  951         if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
  952                 args.flags |= NFSMNT_SOFT;
  953         if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
  954                 args.flags &= ~NFSMNT_SOFT;
  955         if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
  956                 args.sotype = SOCK_DGRAM;
  957         if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
  958                 args.sotype = SOCK_DGRAM;
  959         if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
  960                 args.sotype = SOCK_STREAM;
  961         if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
  962                 args.flags |= NFSMNT_NFSV3;
  963         if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
  964                 args.flags |= NFSMNT_NFSV4;
  965                 args.sotype = SOCK_STREAM;
  966         }
  967         if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
  968                 args.flags |= NFSMNT_ALLGSSNAME;
  969         if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
  970                 args.flags |= NFSMNT_NOCTO;
  971         if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
  972                 args.flags |= NFSMNT_NONCONTIGWR;
  973         if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
  974                 args.flags |= NFSMNT_PNFS;
  975         if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0)
  976                 args.flags |= NFSMNT_ONEOPENOWN;
  977         if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
  978                 if (opt == NULL) { 
  979                         vfs_mount_error(mp, "illegal readdirsize");
  980                         error = EINVAL;
  981                         goto out;
  982                 }
  983                 ret = sscanf(opt, "%d", &args.readdirsize);
  984                 if (ret != 1 || args.readdirsize <= 0) {
  985                         vfs_mount_error(mp, "illegal readdirsize: %s",
  986                             opt);
  987                         error = EINVAL;
  988                         goto out;
  989                 }
  990                 args.flags |= NFSMNT_READDIRSIZE;
  991         }
  992         if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
  993                 if (opt == NULL) { 
  994                         vfs_mount_error(mp, "illegal readahead");
  995                         error = EINVAL;
  996                         goto out;
  997                 }
  998                 ret = sscanf(opt, "%d", &args.readahead);
  999                 if (ret != 1 || args.readahead <= 0) {
 1000                         vfs_mount_error(mp, "illegal readahead: %s",
 1001                             opt);
 1002                         error = EINVAL;
 1003                         goto out;
 1004                 }
 1005                 args.flags |= NFSMNT_READAHEAD;
 1006         }
 1007         if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
 1008                 if (opt == NULL) { 
 1009                         vfs_mount_error(mp, "illegal wsize");
 1010                         error = EINVAL;
 1011                         goto out;
 1012                 }
 1013                 ret = sscanf(opt, "%d", &args.wsize);
 1014                 if (ret != 1 || args.wsize <= 0) {
 1015                         vfs_mount_error(mp, "illegal wsize: %s",
 1016                             opt);
 1017                         error = EINVAL;
 1018                         goto out;
 1019                 }
 1020                 args.flags |= NFSMNT_WSIZE;
 1021         }
 1022         if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
 1023                 if (opt == NULL) { 
 1024                         vfs_mount_error(mp, "illegal rsize");
 1025                         error = EINVAL;
 1026                         goto out;
 1027                 }
 1028                 ret = sscanf(opt, "%d", &args.rsize);
 1029                 if (ret != 1 || args.rsize <= 0) {
 1030                         vfs_mount_error(mp, "illegal wsize: %s",
 1031                             opt);
 1032                         error = EINVAL;
 1033                         goto out;
 1034                 }
 1035                 args.flags |= NFSMNT_RSIZE;
 1036         }
 1037         if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
 1038                 if (opt == NULL) { 
 1039                         vfs_mount_error(mp, "illegal retrans");
 1040                         error = EINVAL;
 1041                         goto out;
 1042                 }
 1043                 ret = sscanf(opt, "%d", &args.retrans);
 1044                 if (ret != 1 || args.retrans <= 0) {
 1045                         vfs_mount_error(mp, "illegal retrans: %s",
 1046                             opt);
 1047                         error = EINVAL;
 1048                         goto out;
 1049                 }
 1050                 args.flags |= NFSMNT_RETRANS;
 1051         }
 1052         if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
 1053                 ret = sscanf(opt, "%d", &args.acregmin);
 1054                 if (ret != 1 || args.acregmin < 0) {
 1055                         vfs_mount_error(mp, "illegal actimeo: %s",
 1056                             opt);
 1057                         error = EINVAL;
 1058                         goto out;
 1059                 }
 1060                 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
 1061                 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
 1062                     NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
 1063         }
 1064         if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
 1065                 ret = sscanf(opt, "%d", &args.acregmin);
 1066                 if (ret != 1 || args.acregmin < 0) {
 1067                         vfs_mount_error(mp, "illegal acregmin: %s",
 1068                             opt);
 1069                         error = EINVAL;
 1070                         goto out;
 1071                 }
 1072                 args.flags |= NFSMNT_ACREGMIN;
 1073         }
 1074         if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
 1075                 ret = sscanf(opt, "%d", &args.acregmax);
 1076                 if (ret != 1 || args.acregmax < 0) {
 1077                         vfs_mount_error(mp, "illegal acregmax: %s",
 1078                             opt);
 1079                         error = EINVAL;
 1080                         goto out;
 1081                 }
 1082                 args.flags |= NFSMNT_ACREGMAX;
 1083         }
 1084         if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
 1085                 ret = sscanf(opt, "%d", &args.acdirmin);
 1086                 if (ret != 1 || args.acdirmin < 0) {
 1087                         vfs_mount_error(mp, "illegal acdirmin: %s",
 1088                             opt);
 1089                         error = EINVAL;
 1090                         goto out;
 1091                 }
 1092                 args.flags |= NFSMNT_ACDIRMIN;
 1093         }
 1094         if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
 1095                 ret = sscanf(opt, "%d", &args.acdirmax);
 1096                 if (ret != 1 || args.acdirmax < 0) {
 1097                         vfs_mount_error(mp, "illegal acdirmax: %s",
 1098                             opt);
 1099                         error = EINVAL;
 1100                         goto out;
 1101                 }
 1102                 args.flags |= NFSMNT_ACDIRMAX;
 1103         }
 1104         if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
 1105                 ret = sscanf(opt, "%d", &args.wcommitsize);
 1106                 if (ret != 1 || args.wcommitsize < 0) {
 1107                         vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
 1108                         error = EINVAL;
 1109                         goto out;
 1110                 }
 1111                 args.flags |= NFSMNT_WCOMMITSIZE;
 1112         }
 1113         if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
 1114                 ret = sscanf(opt, "%d", &args.timeo);
 1115                 if (ret != 1 || args.timeo <= 0) {
 1116                         vfs_mount_error(mp, "illegal timeo: %s",
 1117                             opt);
 1118                         error = EINVAL;
 1119                         goto out;
 1120                 }
 1121                 args.flags |= NFSMNT_TIMEO;
 1122         }
 1123         if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
 1124                 ret = sscanf(opt, "%d", &args.timeo);
 1125                 if (ret != 1 || args.timeo <= 0) {
 1126                         vfs_mount_error(mp, "illegal timeout: %s",
 1127                             opt);
 1128                         error = EINVAL;
 1129                         goto out;
 1130                 }
 1131                 args.flags |= NFSMNT_TIMEO;
 1132         }
 1133         if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
 1134                 ret = sscanf(opt, "%d", &nametimeo);
 1135                 if (ret != 1 || nametimeo < 0) {
 1136                         vfs_mount_error(mp, "illegal nametimeo: %s", opt);
 1137                         error = EINVAL;
 1138                         goto out;
 1139                 }
 1140         }
 1141         if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
 1142             == 0) {
 1143                 ret = sscanf(opt, "%d", &negnametimeo);
 1144                 if (ret != 1 || negnametimeo < 0) {
 1145                         vfs_mount_error(mp, "illegal negnametimeo: %s",
 1146                             opt);
 1147                         error = EINVAL;
 1148                         goto out;
 1149                 }
 1150         }
 1151         if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
 1152             0) {
 1153                 ret = sscanf(opt, "%d", &minvers);
 1154                 if (ret != 1 || minvers < 0 || minvers > 1 ||
 1155                     (args.flags & NFSMNT_NFSV4) == 0) {
 1156                         vfs_mount_error(mp, "illegal minorversion: %s", opt);
 1157                         error = EINVAL;
 1158                         goto out;
 1159                 }
 1160         }
 1161         if (vfs_getopt(mp->mnt_optnew, "sec",
 1162                 (void **) &secname, NULL) == 0)
 1163                 nfs_sec_name(secname, &args.flags);
 1164 
 1165         if (mp->mnt_flag & MNT_UPDATE) {
 1166                 struct nfsmount *nmp = VFSTONFS(mp);
 1167 
 1168                 if (nmp == NULL) {
 1169                         error = EIO;
 1170                         goto out;
 1171                 }
 1172 
 1173                 /*
 1174                  * If a change from TCP->UDP is done and there are thread(s)
 1175                  * that have I/O RPC(s) in progress with a transfer size
 1176                  * greater than NFS_MAXDGRAMDATA, those thread(s) will be
 1177                  * hung, retrying the RPC(s) forever. Usually these threads
 1178                  * will be seen doing an uninterruptible sleep on wait channel
 1179                  * "nfsreq".
 1180                  */
 1181                 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
 1182                         tprintf(td->td_proc, LOG_WARNING,
 1183         "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
 1184 
 1185                 /*
 1186                  * When doing an update, we can't change version,
 1187                  * security, switch lockd strategies, change cookie
 1188                  * translation or switch oneopenown.
 1189                  */
 1190                 args.flags = (args.flags &
 1191                     ~(NFSMNT_NFSV3 |
 1192                       NFSMNT_NFSV4 |
 1193                       NFSMNT_KERB |
 1194                       NFSMNT_INTEGRITY |
 1195                       NFSMNT_PRIVACY |
 1196                       NFSMNT_ONEOPENOWN |
 1197                       NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
 1198                     (nmp->nm_flag &
 1199                         (NFSMNT_NFSV3 |
 1200                          NFSMNT_NFSV4 |
 1201                          NFSMNT_KERB |
 1202                          NFSMNT_INTEGRITY |
 1203                          NFSMNT_PRIVACY |
 1204                          NFSMNT_ONEOPENOWN |
 1205                          NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
 1206                 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
 1207                 goto out;
 1208         }
 1209 
 1210         /*
 1211          * Make the nfs_ip_paranoia sysctl serve as the default connection
 1212          * or no-connection mode for those protocols that support 
 1213          * no-connection mode (the flag will be cleared later for protocols
 1214          * that do not support no-connection mode).  This will allow a client
 1215          * to receive replies from a different IP then the request was
 1216          * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
 1217          * not 0.
 1218          */
 1219         if (nfs_ip_paranoia == 0)
 1220                 args.flags |= NFSMNT_NOCONN;
 1221 
 1222         if (has_nfs_args_opt != 0) {
 1223                 /*
 1224                  * In the 'nfs_args' case, the pointers in the args
 1225                  * structure are in userland - we copy them in here.
 1226                  */
 1227                 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
 1228                         vfs_mount_error(mp, "Bad file handle");
 1229                         error = EINVAL;
 1230                         goto out;
 1231                 }
 1232                 error = copyin((caddr_t)args.fh, (caddr_t)nfh,
 1233                     args.fhsize);
 1234                 if (error != 0)
 1235                         goto out;
 1236                 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
 1237                 if (error != 0)
 1238                         goto out;
 1239                 bzero(&hst[hstlen], MNAMELEN - hstlen);
 1240                 args.hostname = hst;
 1241                 /* getsockaddr() call must be after above copyin() calls */
 1242                 error = getsockaddr(&nam, (caddr_t)args.addr,
 1243                     args.addrlen);
 1244                 if (error != 0)
 1245                         goto out;
 1246         } else if (nfs_mount_parse_from(mp->mnt_optnew,
 1247             &args.hostname, (struct sockaddr_in **)&nam, dirpath,
 1248             sizeof(dirpath), &dirlen) == 0) {
 1249                 has_nfs_from_opt = 1;
 1250                 bcopy(args.hostname, hst, MNAMELEN);
 1251                 hst[MNAMELEN - 1] = '\0';
 1252 
 1253                 /*
 1254                  * This only works with NFSv4 for now.
 1255                  */
 1256                 args.fhsize = 0;
 1257                 args.flags |= NFSMNT_NFSV4;
 1258                 args.sotype = SOCK_STREAM;
 1259         } else {
 1260                 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
 1261                     &args.fhsize) == 0) {
 1262                         if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
 1263                                 vfs_mount_error(mp, "Bad file handle");
 1264                                 error = EINVAL;
 1265                                 goto out;
 1266                         }
 1267                         bcopy(args.fh, nfh, args.fhsize);
 1268                 } else {
 1269                         args.fhsize = 0;
 1270                 }
 1271                 (void) vfs_getopt(mp->mnt_optnew, "hostname",
 1272                     (void **)&args.hostname, &len);
 1273                 if (args.hostname == NULL) {
 1274                         vfs_mount_error(mp, "Invalid hostname");
 1275                         error = EINVAL;
 1276                         goto out;
 1277                 }
 1278                 if (len >= MNAMELEN) {
 1279                         vfs_mount_error(mp, "Hostname too long");
 1280                         error = EINVAL;
 1281                         goto out;
 1282                 }
 1283                 bcopy(args.hostname, hst, len);
 1284                 hst[len] = '\0';
 1285         }
 1286 
 1287         if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
 1288                 strlcpy(srvkrbname, name, sizeof (srvkrbname));
 1289         else {
 1290                 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
 1291                 cp = strchr(srvkrbname, ':');
 1292                 if (cp != NULL)
 1293                         *cp = '\0';
 1294         }
 1295         srvkrbnamelen = strlen(srvkrbname);
 1296 
 1297         if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
 1298                 strlcpy(krbname, name, sizeof (krbname));
 1299         else
 1300                 krbname[0] = '\0';
 1301         krbnamelen = strlen(krbname);
 1302 
 1303         if (has_nfs_from_opt == 0) {
 1304                 if (vfs_getopt(mp->mnt_optnew,
 1305                     "dirpath", (void **)&name, NULL) == 0)
 1306                         strlcpy(dirpath, name, sizeof (dirpath));
 1307                 else
 1308                         dirpath[0] = '\0';
 1309                 dirlen = strlen(dirpath);
 1310         }
 1311 
 1312         if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
 1313                 if (vfs_getopt(mp->mnt_optnew, "addr",
 1314                     (void **)&args.addr, &args.addrlen) == 0) {
 1315                         if (args.addrlen > SOCK_MAXADDRLEN) {
 1316                                 error = ENAMETOOLONG;
 1317                                 goto out;
 1318                         }
 1319                         nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
 1320                         bcopy(args.addr, nam, args.addrlen);
 1321                         nam->sa_len = args.addrlen;
 1322                 } else {
 1323                         vfs_mount_error(mp, "No server address");
 1324                         error = EINVAL;
 1325                         goto out;
 1326                 }
 1327         }
 1328 
 1329         args.fh = nfh;
 1330         error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
 1331             dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
 1332             nametimeo, negnametimeo, minvers);
 1333 out:
 1334         if (!error) {
 1335                 MNT_ILOCK(mp);
 1336                 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
 1337                     MNTK_USES_BCACHE;
 1338                 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0)
 1339                         mp->mnt_kern_flag |= MNTK_NULL_NOCACHE;
 1340                 MNT_IUNLOCK(mp);
 1341         }
 1342         free(hst, M_TEMP);
 1343         return (error);
 1344 }
 1345 
 1346 
 1347 /*
 1348  * VFS Operations.
 1349  *
 1350  * mount system call
 1351  * It seems a bit dumb to copyinstr() the host and path here and then
 1352  * bcopy() them in mountnfs(), but I wanted to detect errors before
 1353  * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
 1354  * an error after that means that I have to release the mbuf.
 1355  */
 1356 /* ARGSUSED */
 1357 static int
 1358 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
 1359 {
 1360         int error;
 1361         struct nfs_args args;
 1362 
 1363         error = copyin(data, &args, sizeof (struct nfs_args));
 1364         if (error)
 1365                 return error;
 1366 
 1367         ma = mount_arg(ma, "nfs_args", &args, sizeof args);
 1368 
 1369         error = kernel_mount(ma, flags);
 1370         return (error);
 1371 }
 1372 
 1373 /*
 1374  * Common code for mount and mountroot
 1375  */
 1376 static int
 1377 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
 1378     char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
 1379     u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
 1380     struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
 1381     int minvers)
 1382 {
 1383         struct nfsmount *nmp;
 1384         struct nfsnode *np;
 1385         int error, trycnt, ret;
 1386         struct nfsvattr nfsva;
 1387         struct nfsclclient *clp;
 1388         struct nfsclds *dsp, *tdsp;
 1389         uint32_t lease;
 1390         static u_int64_t clval = 0;
 1391 
 1392         NFSCL_DEBUG(3, "in mnt\n");
 1393         clp = NULL;
 1394         if (mp->mnt_flag & MNT_UPDATE) {
 1395                 nmp = VFSTONFS(mp);
 1396                 printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
 1397                 free(nam, M_SONAME);
 1398                 return (0);
 1399         } else {
 1400                 nmp = malloc(sizeof (struct nfsmount) +
 1401                     krbnamelen + dirlen + srvkrbnamelen + 2,
 1402                     M_NEWNFSMNT, M_WAITOK | M_ZERO);
 1403                 TAILQ_INIT(&nmp->nm_bufq);
 1404                 TAILQ_INIT(&nmp->nm_sess);
 1405                 if (clval == 0)
 1406                         clval = (u_int64_t)nfsboottime.tv_sec;
 1407                 nmp->nm_clval = clval++;
 1408                 nmp->nm_krbnamelen = krbnamelen;
 1409                 nmp->nm_dirpathlen = dirlen;
 1410                 nmp->nm_srvkrbnamelen = srvkrbnamelen;
 1411                 if (td->td_ucred->cr_uid != (uid_t)0) {
 1412                         /*
 1413                          * nm_uid is used to get KerberosV credentials for
 1414                          * the nfsv4 state handling operations if there is
 1415                          * no host based principal set. Use the uid of
 1416                          * this user if not root, since they are doing the
 1417                          * mount. I don't think setting this for root will
 1418                          * work, since root normally does not have user
 1419                          * credentials in a credentials cache.
 1420                          */
 1421                         nmp->nm_uid = td->td_ucred->cr_uid;
 1422                 } else {
 1423                         /*
 1424                          * Just set to -1, so it won't be used.
 1425                          */
 1426                         nmp->nm_uid = (uid_t)-1;
 1427                 }
 1428 
 1429                 /* Copy and null terminate all the names */
 1430                 if (nmp->nm_krbnamelen > 0) {
 1431                         bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
 1432                         nmp->nm_name[nmp->nm_krbnamelen] = '\0';
 1433                 }
 1434                 if (nmp->nm_dirpathlen > 0) {
 1435                         bcopy(dirpath, NFSMNT_DIRPATH(nmp),
 1436                             nmp->nm_dirpathlen);
 1437                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
 1438                             + 1] = '\0';
 1439                 }
 1440                 if (nmp->nm_srvkrbnamelen > 0) {
 1441                         bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
 1442                             nmp->nm_srvkrbnamelen);
 1443                         nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
 1444                             + nmp->nm_srvkrbnamelen + 2] = '\0';
 1445                 }
 1446                 nmp->nm_sockreq.nr_cred = crhold(cred);
 1447                 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
 1448                 mp->mnt_data = nmp;
 1449                 nmp->nm_getinfo = nfs_getnlminfo;
 1450                 nmp->nm_vinvalbuf = ncl_vinvalbuf;
 1451         }
 1452         vfs_getnewfsid(mp);
 1453         nmp->nm_mountp = mp;
 1454         mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
 1455 
 1456         /*
 1457          * Since nfs_decode_args() might optionally set them, these
 1458          * need to be set to defaults before the call, so that the
 1459          * optional settings aren't overwritten.
 1460          */
 1461         nmp->nm_nametimeo = nametimeo;
 1462         nmp->nm_negnametimeo = negnametimeo;
 1463         nmp->nm_timeo = NFS_TIMEO;
 1464         nmp->nm_retry = NFS_RETRANS;
 1465         nmp->nm_readahead = NFS_DEFRAHEAD;
 1466 
 1467         /* This is empirical approximation of sqrt(hibufspace) * 256. */
 1468         nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
 1469         while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
 1470                 nmp->nm_wcommitsize *= 2;
 1471         nmp->nm_wcommitsize *= 256;
 1472 
 1473         if ((argp->flags & NFSMNT_NFSV4) != 0)
 1474                 nmp->nm_minorvers = minvers;
 1475         else
 1476                 nmp->nm_minorvers = 0;
 1477 
 1478         nfs_decode_args(mp, nmp, argp, hst, cred, td);
 1479 
 1480         /*
 1481          * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
 1482          * high, depending on whether we end up with negative offsets in
 1483          * the client or server somewhere.  2GB-1 may be safer.
 1484          *
 1485          * For V3, ncl_fsinfo will adjust this as necessary.  Assume maximum
 1486          * that we can handle until we find out otherwise.
 1487          */
 1488         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
 1489                 nmp->nm_maxfilesize = 0xffffffffLL;
 1490         else
 1491                 nmp->nm_maxfilesize = OFF_MAX;
 1492 
 1493         if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
 1494                 nmp->nm_wsize = NFS_WSIZE;
 1495                 nmp->nm_rsize = NFS_RSIZE;
 1496                 nmp->nm_readdirsize = NFS_READDIRSIZE;
 1497         }
 1498         nmp->nm_numgrps = NFS_MAXGRPS;
 1499         nmp->nm_tprintf_delay = nfs_tprintf_delay;
 1500         if (nmp->nm_tprintf_delay < 0)
 1501                 nmp->nm_tprintf_delay = 0;
 1502         nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
 1503         if (nmp->nm_tprintf_initial_delay < 0)
 1504                 nmp->nm_tprintf_initial_delay = 0;
 1505         nmp->nm_fhsize = argp->fhsize;
 1506         if (nmp->nm_fhsize > 0)
 1507                 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
 1508         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
 1509         nmp->nm_nam = nam;
 1510         /* Set up the sockets and per-host congestion */
 1511         nmp->nm_sotype = argp->sotype;
 1512         nmp->nm_soproto = argp->proto;
 1513         nmp->nm_sockreq.nr_prog = NFS_PROG;
 1514         if ((argp->flags & NFSMNT_NFSV4))
 1515                 nmp->nm_sockreq.nr_vers = NFS_VER4;
 1516         else if ((argp->flags & NFSMNT_NFSV3))
 1517                 nmp->nm_sockreq.nr_vers = NFS_VER3;
 1518         else
 1519                 nmp->nm_sockreq.nr_vers = NFS_VER2;
 1520 
 1521 
 1522         if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
 1523                 goto bad;
 1524         /* For NFSv4.1, get the clientid now. */
 1525         if (nmp->nm_minorvers > 0) {
 1526                 NFSCL_DEBUG(3, "at getcl\n");
 1527                 error = nfscl_getcl(mp, cred, td, 0, true, &clp);
 1528                 NFSCL_DEBUG(3, "aft getcl=%d\n", error);
 1529                 if (error != 0)
 1530                         goto bad;
 1531         }
 1532 
 1533         if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
 1534             nmp->nm_dirpathlen > 0) {
 1535                 NFSCL_DEBUG(3, "in dirp\n");
 1536                 /*
 1537                  * If the fhsize on the mount point == 0 for V4, the mount
 1538                  * path needs to be looked up.
 1539                  */
 1540                 trycnt = 3;
 1541                 do {
 1542                         error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
 1543                             cred, td);
 1544                         NFSCL_DEBUG(3, "aft dirp=%d\n", error);
 1545                         if (error)
 1546                                 (void) nfs_catnap(PZERO, error, "nfsgetdirp");
 1547                 } while (error && --trycnt > 0);
 1548                 if (error)
 1549                         goto bad;
 1550         }
 1551 
 1552         /*
 1553          * A reference count is needed on the nfsnode representing the
 1554          * remote root.  If this object is not persistent, then backward
 1555          * traversals of the mount point (i.e. "..") will not work if
 1556          * the nfsnode gets flushed out of the cache. Ufs does not have
 1557          * this problem, because one can identify root inodes by their
 1558          * number == UFS_ROOTINO (2).
 1559          */
 1560         if (nmp->nm_fhsize > 0) {
 1561                 /*
 1562                  * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
 1563                  * non-zero for the root vnode. f_iosize will be set correctly
 1564                  * by nfs_statfs() before any I/O occurs.
 1565                  */
 1566                 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
 1567                 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
 1568                     LK_EXCLUSIVE);
 1569                 if (error)
 1570                         goto bad;
 1571                 *vpp = NFSTOV(np);
 1572         
 1573                 /*
 1574                  * Get file attributes and transfer parameters for the
 1575                  * mountpoint.  This has the side effect of filling in
 1576                  * (*vpp)->v_type with the correct value.
 1577                  */
 1578                 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
 1579                     cred, td, &nfsva, NULL, &lease);
 1580                 if (ret) {
 1581                         /*
 1582                          * Just set default values to get things going.
 1583                          */
 1584                         NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
 1585                         nfsva.na_vattr.va_type = VDIR;
 1586                         nfsva.na_vattr.va_mode = 0777;
 1587                         nfsva.na_vattr.va_nlink = 100;
 1588                         nfsva.na_vattr.va_uid = (uid_t)0;
 1589                         nfsva.na_vattr.va_gid = (gid_t)0;
 1590                         nfsva.na_vattr.va_fileid = 2;
 1591                         nfsva.na_vattr.va_gen = 1;
 1592                         nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
 1593                         nfsva.na_vattr.va_size = 512 * 1024;
 1594                         lease = 60;
 1595                 }
 1596                 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
 1597                 if (nmp->nm_minorvers > 0) {
 1598                         NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
 1599                         NFSLOCKCLSTATE();
 1600                         clp->nfsc_renew = NFSCL_RENEW(lease);
 1601                         clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
 1602                         clp->nfsc_clientidrev++;
 1603                         if (clp->nfsc_clientidrev == 0)
 1604                                 clp->nfsc_clientidrev++;
 1605                         NFSUNLOCKCLSTATE();
 1606                         /*
 1607                          * Mount will succeed, so the renew thread can be
 1608                          * started now.
 1609                          */
 1610                         nfscl_start_renewthread(clp);
 1611                         nfscl_clientrelease(clp);
 1612                 }
 1613                 if (argp->flags & NFSMNT_NFSV3)
 1614                         ncl_fsinfo(nmp, *vpp, cred, td);
 1615         
 1616                 /* Mark if the mount point supports NFSv4 ACLs. */
 1617                 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
 1618                     ret == 0 &&
 1619                     NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
 1620                         MNT_ILOCK(mp);
 1621                         mp->mnt_flag |= MNT_NFS4ACLS;
 1622                         MNT_IUNLOCK(mp);
 1623                 }
 1624         
 1625                 /*
 1626                  * Lose the lock but keep the ref.
 1627                  */
 1628                 NFSVOPUNLOCK(*vpp, 0);
 1629                 return (0);
 1630         }
 1631         error = EIO;
 1632 
 1633 bad:
 1634         if (clp != NULL)
 1635                 nfscl_clientrelease(clp);
 1636         newnfs_disconnect(&nmp->nm_sockreq);
 1637         crfree(nmp->nm_sockreq.nr_cred);
 1638         if (nmp->nm_sockreq.nr_auth != NULL)
 1639                 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
 1640         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
 1641         mtx_destroy(&nmp->nm_mtx);
 1642         if (nmp->nm_clp != NULL) {
 1643                 NFSLOCKCLSTATE();
 1644                 LIST_REMOVE(nmp->nm_clp, nfsc_list);
 1645                 NFSUNLOCKCLSTATE();
 1646                 free(nmp->nm_clp, M_NFSCLCLIENT);
 1647         }
 1648         TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
 1649                 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
 1650                     dsp->nfsclds_sockp != NULL)
 1651                         newnfs_disconnect(dsp->nfsclds_sockp);
 1652                 nfscl_freenfsclds(dsp);
 1653         }
 1654         free(nmp, M_NEWNFSMNT);
 1655         free(nam, M_SONAME);
 1656         return (error);
 1657 }
 1658 
 1659 /*
 1660  * unmount system call
 1661  */
 1662 static int
 1663 nfs_unmount(struct mount *mp, int mntflags)
 1664 {
 1665         struct thread *td;
 1666         struct nfsmount *nmp;
 1667         int error, flags = 0, i, trycnt = 0;
 1668         struct nfsclds *dsp, *tdsp;
 1669         struct nfscldeleg *dp, *ndp;
 1670         struct nfscldeleghead dh;
 1671 
 1672         td = curthread;
 1673         TAILQ_INIT(&dh);
 1674 
 1675         if (mntflags & MNT_FORCE)
 1676                 flags |= FORCECLOSE;
 1677         nmp = VFSTONFS(mp);
 1678         error = 0;
 1679         /*
 1680          * Goes something like this..
 1681          * - Call vflush() to clear out vnodes for this filesystem
 1682          * - Close the socket
 1683          * - Free up the data structures
 1684          */
 1685         /* In the forced case, cancel any outstanding requests. */
 1686         if (mntflags & MNT_FORCE) {
 1687                 NFSDDSLOCK();
 1688                 if (nfsv4_findmirror(nmp) != NULL)
 1689                         error = ENXIO;
 1690                 NFSDDSUNLOCK();
 1691                 if (error)
 1692                         goto out;
 1693                 error = newnfs_nmcancelreqs(nmp);
 1694                 if (error)
 1695                         goto out;
 1696                 /* For a forced close, get rid of the renew thread now */
 1697                 nfscl_umount(nmp, td, &dh);
 1698         }
 1699         /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
 1700         do {
 1701                 error = vflush(mp, 1, flags, td);
 1702                 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
 1703                         (void) nfs_catnap(PSOCK, error, "newndm");
 1704         } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
 1705         if (error)
 1706                 goto out;
 1707 
 1708         /*
 1709          * We are now committed to the unmount.
 1710          */
 1711         if ((mntflags & MNT_FORCE) == 0)
 1712                 nfscl_umount(nmp, td, NULL);
 1713         else {
 1714                 mtx_lock(&nmp->nm_mtx);
 1715                 nmp->nm_privflag |= NFSMNTP_FORCEDISM;
 1716                 mtx_unlock(&nmp->nm_mtx);
 1717         }
 1718         /* Make sure no nfsiods are assigned to this mount. */
 1719         NFSLOCKIOD();
 1720         for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
 1721                 if (ncl_iodmount[i] == nmp) {
 1722                         ncl_iodwant[i] = NFSIOD_AVAILABLE;
 1723                         ncl_iodmount[i] = NULL;
 1724                 }
 1725         NFSUNLOCKIOD();
 1726 
 1727         /*
 1728          * We can now set mnt_data to NULL and wait for
 1729          * nfssvc(NFSSVC_FORCEDISM) to complete.
 1730          */
 1731         mtx_lock(&mountlist_mtx);
 1732         mtx_lock(&nmp->nm_mtx);
 1733         mp->mnt_data = NULL;
 1734         mtx_unlock(&mountlist_mtx);
 1735         while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0)
 1736                 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0);
 1737         mtx_unlock(&nmp->nm_mtx);
 1738 
 1739         newnfs_disconnect(&nmp->nm_sockreq);
 1740         crfree(nmp->nm_sockreq.nr_cred);
 1741         free(nmp->nm_nam, M_SONAME);
 1742         if (nmp->nm_sockreq.nr_auth != NULL)
 1743                 AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
 1744         mtx_destroy(&nmp->nm_sockreq.nr_mtx);
 1745         mtx_destroy(&nmp->nm_mtx);
 1746         TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) {
 1747                 if (dsp != TAILQ_FIRST(&nmp->nm_sess) &&
 1748                     dsp->nfsclds_sockp != NULL)
 1749                         newnfs_disconnect(dsp->nfsclds_sockp);
 1750                 nfscl_freenfsclds(dsp);
 1751         }
 1752         free(nmp, M_NEWNFSMNT);
 1753 
 1754         /* Free up the delegation structures for forced dismounts. */
 1755         TAILQ_FOREACH_SAFE(dp, &dh, nfsdl_list, ndp) {
 1756                 TAILQ_REMOVE(&dh, dp, nfsdl_list);
 1757                 free(dp, M_NFSCLDELEG);
 1758         }
 1759 out:
 1760         return (error);
 1761 }
 1762 
 1763 /*
 1764  * Return root of a filesystem
 1765  */
 1766 static int
 1767 nfs_root(struct mount *mp, int flags, struct vnode **vpp)
 1768 {
 1769         struct vnode *vp;
 1770         struct nfsmount *nmp;
 1771         struct nfsnode *np;
 1772         int error;
 1773 
 1774         nmp = VFSTONFS(mp);
 1775         error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
 1776         if (error)
 1777                 return error;
 1778         vp = NFSTOV(np);
 1779         /*
 1780          * Get transfer parameters and attributes for root vnode once.
 1781          */
 1782         mtx_lock(&nmp->nm_mtx);
 1783         if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
 1784                 mtx_unlock(&nmp->nm_mtx);
 1785                 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
 1786         } else 
 1787                 mtx_unlock(&nmp->nm_mtx);
 1788         if (vp->v_type == VNON)
 1789             vp->v_type = VDIR;
 1790         vp->v_vflag |= VV_ROOT;
 1791         *vpp = vp;
 1792         return (0);
 1793 }
 1794 
 1795 /*
 1796  * Flush out the buffer cache
 1797  */
 1798 /* ARGSUSED */
 1799 static int
 1800 nfs_sync(struct mount *mp, int waitfor)
 1801 {
 1802         struct vnode *vp, *mvp;
 1803         struct thread *td;
 1804         int error, allerror = 0;
 1805 
 1806         td = curthread;
 1807 
 1808         MNT_ILOCK(mp);
 1809         /*
 1810          * If a forced dismount is in progress, return from here so that
 1811          * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
 1812          * calling VFS_UNMOUNT().
 1813          */
 1814         if (NFSCL_FORCEDISM(mp)) {
 1815                 MNT_IUNLOCK(mp);
 1816                 return (EBADF);
 1817         }
 1818         MNT_IUNLOCK(mp);
 1819 
 1820         /*
 1821          * Force stale buffer cache information to be flushed.
 1822          */
 1823 loop:
 1824         MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
 1825                 /* XXX Racy bv_cnt check. */
 1826                 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
 1827                     waitfor == MNT_LAZY) {
 1828                         VI_UNLOCK(vp);
 1829                         continue;
 1830                 }
 1831                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
 1832                         MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
 1833                         goto loop;
 1834                 }
 1835                 error = VOP_FSYNC(vp, waitfor, td);
 1836                 if (error)
 1837                         allerror = error;
 1838                 NFSVOPUNLOCK(vp, 0);
 1839                 vrele(vp);
 1840         }
 1841         return (allerror);
 1842 }
 1843 
 1844 static int
 1845 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
 1846 {
 1847         struct nfsmount *nmp = VFSTONFS(mp);
 1848         struct vfsquery vq;
 1849         int error;
 1850 
 1851         bzero(&vq, sizeof(vq));
 1852         switch (op) {
 1853 #if 0
 1854         case VFS_CTL_NOLOCKS:
 1855                 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
 1856                 if (req->oldptr != NULL) {
 1857                         error = SYSCTL_OUT(req, &val, sizeof(val));
 1858                         if (error)
 1859                                 return (error);
 1860                 }
 1861                 if (req->newptr != NULL) {
 1862                         error = SYSCTL_IN(req, &val, sizeof(val));
 1863                         if (error)
 1864                                 return (error);
 1865                         if (val)
 1866                                 nmp->nm_flag |= NFSMNT_NOLOCKS;
 1867                         else
 1868                                 nmp->nm_flag &= ~NFSMNT_NOLOCKS;
 1869                 }
 1870                 break;
 1871 #endif
 1872         case VFS_CTL_QUERY:
 1873                 mtx_lock(&nmp->nm_mtx);
 1874                 if (nmp->nm_state & NFSSTA_TIMEO)
 1875                         vq.vq_flags |= VQ_NOTRESP;
 1876                 mtx_unlock(&nmp->nm_mtx);
 1877 #if 0
 1878                 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
 1879                     (nmp->nm_state & NFSSTA_LOCKTIMEO))
 1880                         vq.vq_flags |= VQ_NOTRESPLOCK;
 1881 #endif
 1882                 error = SYSCTL_OUT(req, &vq, sizeof(vq));
 1883                 break;
 1884         case VFS_CTL_TIMEO:
 1885                 if (req->oldptr != NULL) {
 1886                         error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
 1887                             sizeof(nmp->nm_tprintf_initial_delay));
 1888                         if (error)
 1889                                 return (error);
 1890                 }
 1891                 if (req->newptr != NULL) {
 1892                         error = vfs_suser(mp, req->td);
 1893                         if (error)
 1894                                 return (error);
 1895                         error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
 1896                             sizeof(nmp->nm_tprintf_initial_delay));
 1897                         if (error)
 1898                                 return (error);
 1899                         if (nmp->nm_tprintf_initial_delay < 0)
 1900                                 nmp->nm_tprintf_initial_delay = 0;
 1901                 }
 1902                 break;
 1903         default:
 1904                 return (ENOTSUP);
 1905         }
 1906         return (0);
 1907 }
 1908 
 1909 /*
 1910  * Purge any RPCs in progress, so that they will all return errors.
 1911  * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
 1912  * forced dismount.
 1913  */
 1914 static void
 1915 nfs_purge(struct mount *mp)
 1916 {
 1917         struct nfsmount *nmp = VFSTONFS(mp);
 1918 
 1919         newnfs_nmcancelreqs(nmp);
 1920 }
 1921 
 1922 /*
 1923  * Extract the information needed by the nlm from the nfs vnode.
 1924  */
 1925 static void
 1926 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
 1927     struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
 1928     struct timeval *timeop)
 1929 {
 1930         struct nfsmount *nmp;
 1931         struct nfsnode *np = VTONFS(vp);
 1932 
 1933         nmp = VFSTONFS(vp->v_mount);
 1934         if (fhlenp != NULL)
 1935                 *fhlenp = (size_t)np->n_fhp->nfh_len;
 1936         if (fhp != NULL)
 1937                 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
 1938         if (sp != NULL)
 1939                 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
 1940         if (is_v3p != NULL)
 1941                 *is_v3p = NFS_ISV3(vp);
 1942         if (sizep != NULL)
 1943                 *sizep = np->n_size;
 1944         if (timeop != NULL) {
 1945                 timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
 1946                 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
 1947         }
 1948 }
 1949 
 1950 /*
 1951  * This function prints out an option name, based on the conditional
 1952  * argument.
 1953  */
 1954 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
 1955     char *opt, char **buf, size_t *blen)
 1956 {
 1957         int len;
 1958 
 1959         if (testval != 0 && *blen > strlen(opt)) {
 1960                 len = snprintf(*buf, *blen, "%s", opt);
 1961                 if (len != strlen(opt))
 1962                         printf("EEK!!\n");
 1963                 *buf += len;
 1964                 *blen -= len;
 1965         }
 1966 }
 1967 
 1968 /*
 1969  * This function printf out an options integer value.
 1970  */
 1971 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
 1972     char *opt, char **buf, size_t *blen)
 1973 {
 1974         int len;
 1975 
 1976         if (*blen > strlen(opt) + 1) {
 1977                 /* Could result in truncated output string. */
 1978                 len = snprintf(*buf, *blen, "%s=%d", opt, optval);
 1979                 if (len < *blen) {
 1980                         *buf += len;
 1981                         *blen -= len;
 1982                 }
 1983         }
 1984 }
 1985 
 1986 /*
 1987  * Load the option flags and values into the buffer.
 1988  */
 1989 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
 1990 {
 1991         char *buf;
 1992         size_t blen;
 1993 
 1994         buf = buffer;
 1995         blen = buflen;
 1996         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
 1997             &blen);
 1998         if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
 1999                 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
 2000                     &blen);
 2001                 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
 2002                     &buf, &blen);
 2003                 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&
 2004                     nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen);
 2005         }
 2006         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
 2007             &blen);
 2008         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
 2009             "nfsv2", &buf, &blen);
 2010         nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
 2011         nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
 2012         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
 2013             &buf, &blen);
 2014         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
 2015             &buf, &blen);
 2016         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
 2017             &blen);
 2018         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
 2019             &blen);
 2020         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
 2021             &blen);
 2022         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
 2023             &blen);
 2024         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
 2025             &blen);
 2026         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
 2027             ",noncontigwr", &buf, &blen);
 2028         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
 2029             0, ",lockd", &buf, &blen);
 2030         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
 2031             NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
 2032         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
 2033             &buf, &blen);
 2034         nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
 2035             &buf, &blen);
 2036         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
 2037             NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
 2038         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
 2039             NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
 2040             &buf, &blen);
 2041         nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
 2042             NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
 2043             &buf, &blen);
 2044         nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
 2045         nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
 2046         nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
 2047         nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
 2048         nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
 2049         nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
 2050             &blen);
 2051         nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
 2052         nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
 2053         nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
 2054             &blen);
 2055         nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
 2056         nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
 2057             &blen);
 2058         nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
 2059         nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
 2060 }
 2061 

Cache object: f1e679fef67d33fe5b4efd6628724ffa


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