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

Cache object: 5cb0f47586728c99f4dc2a71b53f9754


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