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