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-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

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.