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