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