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