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