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

Cache object: 020026fb089bb705677f2df4779b5471


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