File:  [DragonFly] / src / sys / vfs / nfs / nfs_vfsops.c
Revision 1.18: download - view: text, annotated - select for diffs
Wed May 19 22:53:05 2004 UTC (10 years, 2 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Device layer rollup commit.

* cdevsw_add() is now required.  cdevsw_add() and cdevsw_remove() may specify
  a mask/match indicating the range of supported minor numbers.  Multiple
  cdevsw_add()'s using the same major number, but distinctly different
  ranges, may be issued.  All devices that failed to call cdevsw_add() before
  now do.

* cdevsw_remove() now automatically marks all devices within its supported
  range as being destroyed.

* vnode->v_rdev is no longer resolved when the vnode is created.  Instead,
  only v_udev (a newly added field) is resolved.  v_rdev is resolved when
  the vnode is opened and cleared on the last close.

* A great deal of code was making rather dubious assumptions with regards
  to the validity of devices associated with vnodes, primarily due to
  the persistence of a device structure due to being indexed by (major, minor)
  instead of by (cdevsw, major, minor).  In particular, if you run a program
  which connects to a USB device and then you pull the USB device and plug
  it back in, the vnode subsystem will continue to believe that the device
  is open when, in fact, it isn't (because it was destroyed and recreated).

  In particular, note that all the VFS mount procedures now check devices
  via v_udev instead of v_rdev prior to calling VOP_OPEN(), since v_rdev
  is NULL prior to the first open.

* The disk layer's device interaction has been rewritten.  The disk layer
  (i.e. the slice and disklabel management layer) no longer overloads
  its data onto the device structure representing the underlying physical
  disk.  Instead, the disk layer uses the new cdevsw_add() functionality
  to register its own cdevsw using the underlying device's major number,
  and simply does NOT register the underlying device's cdevsw.  No
  confusion is created because the device hash is now based on
  (cdevsw,major,minor) rather then (major,minor).

  NOTE: This also means that underlying raw disk devices may use the entire
  device minor number instead of having to reserve the bits used by the disk
  layer, and also means that can we (theoretically) stack a fully
  disklabel-supported 'disk' on top of any block device.

* The new reference counting scheme prevents this by associating a device
  with a cdevsw and disconnecting the device from its cdevsw when the cdevsw
  is removed.  Additionally, all udev2dev() lookups run through the cdevsw
  mask/match and only successfully find devices still associated with an
  active cdevsw.

* Major work on MFS:  MFS no longer shortcuts vnode and device creation.  It
  now creates a real vnode and a real device and implements real open and
  close VOPs.  Additionally, due to the disk layer changes, MFS is no longer
  limited to 255 mounts.  The new limit is 16 million.  Since MFS creates a
  real device node, mount_mfs will now create a real /dev/mfs<PID> device
  that can be read from userland (e.g. so you can dump an MFS filesystem).

* BUF AND DEVICE STRATEGY changes.  The struct buf contains a b_dev field.
  In order to properly handle stacked devices we now require that the b_dev
  field be initialized before the device strategy routine is called.  This
  required some additional work in various VFS implementations.  To enforce
  this requirement, biodone() now sets b_dev to NODEV.  The new disk layer
  will adjust b_dev before forwarding a request to the actual physical
  device.

* A bug in the ISO CD boot sequence which resulted in a panic has been fixed.

Testing by: lots of people, but David Rhodus found the most aggregious bugs.

    1: /*
    2:  * Copyright (c) 1989, 1993, 1995
    3:  *	The Regents of the University of California.  All rights reserved.
    4:  *
    5:  * This code is derived from software contributed to Berkeley by
    6:  * Rick Macklem at The University of Guelph.
    7:  *
    8:  * Redistribution and use in source and binary forms, with or without
    9:  * modification, are permitted provided that the following conditions
   10:  * are met:
   11:  * 1. Redistributions of source code must retain the above copyright
   12:  *    notice, this list of conditions and the following disclaimer.
   13:  * 2. Redistributions in binary form must reproduce the above copyright
   14:  *    notice, this list of conditions and the following disclaimer in the
   15:  *    documentation and/or other materials provided with the distribution.
   16:  * 3. All advertising materials mentioning features or use of this software
   17:  *    must display the following acknowledgement:
   18:  *	This product includes software developed by the University of
   19:  *	California, Berkeley and its contributors.
   20:  * 4. Neither the name of the University nor the names of its contributors
   21:  *    may be used to endorse or promote products derived from this software
   22:  *    without specific prior written permission.
   23:  *
   24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34:  * SUCH DAMAGE.
   35:  *
   36:  *	@(#)nfs_vfsops.c	8.12 (Berkeley) 5/20/95
   37:  * $FreeBSD: src/sys/nfs/nfs_vfsops.c,v 1.91.2.7 2003/01/27 20:04:08 dillon Exp $
   38:  * $DragonFly: src/sys/vfs/nfs/nfs_vfsops.c,v 1.18 2004/05/19 22:53:05 dillon Exp $
   39:  */
   40: 
   41: #include "opt_bootp.h"
   42: 
   43: #include <sys/param.h>
   44: #include <sys/sockio.h>
   45: #include <sys/proc.h>
   46: #include <sys/vnode.h>
   47: #include <sys/kernel.h>
   48: #include <sys/sysctl.h>
   49: #include <sys/malloc.h>
   50: #include <sys/mount.h>
   51: #include <sys/mbuf.h>
   52: #include <sys/socket.h>
   53: #include <sys/socketvar.h>
   54: #include <sys/systm.h>
   55: 
   56: #include <vm/vm.h>
   57: #include <vm/vm_extern.h>
   58: #include <vm/vm_zone.h>
   59: 
   60: #include <net/if.h>
   61: #include <net/route.h>
   62: #include <netinet/in.h>
   63: 
   64: #include "rpcv2.h"
   65: #include "nfsproto.h"
   66: #include "nfs.h"
   67: #include "nfsmount.h"
   68: #include "nfsnode.h"
   69: #include "xdr_subs.h"
   70: #include "nfsm_subs.h"
   71: #include "nfsdiskless.h"
   72: #include "nqnfs.h"
   73: 
   74: extern int	nfs_mountroot(struct mount *mp);
   75: extern void	bootpc_init(void);
   76: 
   77: extern int	nfs_ticks;
   78: 
   79: MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header");
   80: MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle");
   81: MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure");
   82: MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data");
   83: MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor");
   84: MALLOC_DEFINE(M_NFSUID, "NFS uid", "Nfs uid mapping structure");
   85: MALLOC_DEFINE(M_NQLEASE, "NQNFS Lease", "Nqnfs lease");
   86: MALLOC_DEFINE(M_NFSHASH, "NFS hash", "NFS hash tables");
   87: 
   88: vm_zone_t nfsmount_zone;
   89: 
   90: struct nfsstats	nfsstats;
   91: SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
   92: SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
   93: 	&nfsstats, nfsstats, "");
   94: static int nfs_ip_paranoia = 1;
   95: SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
   96: 	&nfs_ip_paranoia, 0, "");
   97: #ifdef NFS_DEBUG
   98: int nfs_debug;
   99: SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
  100: #endif
  101: 
  102: /*
  103:  * Tunable to determine the Read/Write unit size.  Maximum value
  104:  * is NFS_MAXDATA.  We also default to NFS_MAXDATA.
  105:  */
  106: static int nfs_io_size = NFS_MAXDATA;
  107: SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_io_size, CTLFLAG_RW,
  108: 	&nfs_io_size, 0, "NFS optimal I/O unit size");
  109: 
  110: static void	nfs_decode_args (struct nfsmount *nmp,
  111: 			struct nfs_args *argp);
  112: static int	mountnfs (struct nfs_args *,struct mount *,
  113: 			struct sockaddr *,char *,char *,struct vnode **);
  114: static int	nfs_mount ( struct mount *mp, char *path, caddr_t data,
  115: 			struct nameidata *ndp, struct thread *td);
  116: static int	nfs_unmount ( struct mount *mp, int mntflags,
  117: 			struct thread *td);
  118: static int	nfs_root ( struct mount *mp, struct vnode **vpp);
  119: static int	nfs_statfs ( struct mount *mp, struct statfs *sbp,
  120: 			struct thread *td);
  121: static int	nfs_sync ( struct mount *mp, int waitfor,
  122: 			struct thread *td);
  123: 
  124: /*
  125:  * nfs vfs operations.
  126:  */
  127: static struct vfsops nfs_vfsops = {
  128: 	nfs_mount,
  129: 	vfs_stdstart,
  130: 	nfs_unmount,
  131: 	nfs_root,
  132: 	vfs_stdquotactl,
  133: 	nfs_statfs,
  134: 	nfs_sync,
  135: 	vfs_stdvget,
  136: 	vfs_stdfhtovp,		/* shouldn't happen */
  137: 	vfs_stdcheckexp,
  138: 	vfs_stdvptofh,		/* shouldn't happen */
  139: 	nfs_init,
  140: 	nfs_uninit,
  141: 	vfs_stdextattrctl,
  142: };
  143: VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
  144: 
  145: /*
  146:  * This structure must be filled in by a primary bootstrap or bootstrap
  147:  * server for a diskless/dataless machine. It is initialized below just
  148:  * to ensure that it is allocated to initialized data (.data not .bss).
  149:  */
  150: struct nfs_diskless nfs_diskless = { { { 0 } } };
  151: struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
  152: int nfs_diskless_valid = 0;
  153: 
  154: SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, 
  155: 	&nfs_diskless_valid, 0, "");
  156: 
  157: SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
  158: 	nfsv3_diskless.root_hostnam, 0, "");
  159: 
  160: SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
  161: 	&nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
  162: 	"%Ssockaddr_in", "");
  163: 
  164: SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD,
  165: 	nfsv3_diskless.swap_hostnam, 0, "");
  166: 
  167: SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
  168: 	&nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr, 
  169: 	"%Ssockaddr_in","");
  170: 
  171: 
  172: void nfsargs_ntoh (struct nfs_args *);
  173: static int nfs_mountdiskless (char *, char *, int,
  174: 				  struct sockaddr_in *, struct nfs_args *,
  175: 				  struct thread *, struct vnode **,
  176: 				  struct mount **);
  177: static void nfs_convert_diskless (void);
  178: static void nfs_convert_oargs (struct nfs_args *args,
  179: 				   struct onfs_args *oargs);
  180: 
  181: /*
  182:  * Calculate the buffer I/O block size to use.  The maximum V2 block size
  183:  * is typically 8K, the maximum datagram size is typically 16K, and the
  184:  * maximum V3 block size is typically 32K.  The buffer cache tends to work
  185:  * best with 16K blocks but we allow 32K for TCP connections.
  186:  *
  187:  * We force the block size to be at least a page for buffer cache efficiency.
  188:  */
  189: static
  190: int
  191: nfs_iosize(int v3, int sotype)
  192: {
  193: 	int iosize;
  194: 	int iomax;
  195: 
  196: 	if (v3) {
  197: 		if (sotype == SOCK_STREAM)
  198: 			iomax = NFS_MAXDATA;
  199: 		else
  200: 			iomax = NFS_MAXDGRAMDATA;
  201: 	} else {
  202: 		iomax = NFS_V2MAXDATA;
  203: 	}
  204: 	if ((iosize = nfs_io_size) > iomax)
  205: 		iosize = iomax;
  206: 	if (iosize < PAGE_SIZE)
  207: 		iosize = PAGE_SIZE;
  208: 
  209: 	/*
  210: 	 * This is an aweful hack but until the buffer cache is rewritten
  211: 	 * we need it.  The problem is that when you combine write() with
  212: 	 * mmap() the vm_page->valid bits can become weird looking
  213: 	 * (e.g. 0xfc).  This occurs because NFS uses piecemeal buffers
  214: 	 * at the file EOF.  To solve the problem the BIO system needs to
  215: 	 * be guarenteed that the NFS iosize for regular files will be a
  216: 	 * multiple of PAGE_SIZE so it can invalidate the whole page
  217: 	 * rather then just the piece of it owned by the buffer when
  218: 	 * NFS does vinvalbuf() calls.
  219: 	 */
  220: 	if (iosize & PAGE_MASK)
  221: 		iosize = (iosize & ~PAGE_MASK) + PAGE_SIZE;
  222: 	return iosize;
  223: }
  224: 
  225: static void
  226: nfs_convert_oargs(args, oargs)
  227: 	struct nfs_args *args;
  228: 	struct onfs_args *oargs;
  229: {
  230: 	args->version = NFS_ARGSVERSION;
  231: 	args->addr = oargs->addr;
  232: 	args->addrlen = oargs->addrlen;
  233: 	args->sotype = oargs->sotype;
  234: 	args->proto = oargs->proto;
  235: 	args->fh = oargs->fh;
  236: 	args->fhsize = oargs->fhsize;
  237: 	args->flags = oargs->flags;
  238: 	args->wsize = oargs->wsize;
  239: 	args->rsize = oargs->rsize;
  240: 	args->readdirsize = oargs->readdirsize;
  241: 	args->timeo = oargs->timeo;
  242: 	args->retrans = oargs->retrans;
  243: 	args->maxgrouplist = oargs->maxgrouplist;
  244: 	args->readahead = oargs->readahead;
  245: 	args->leaseterm = oargs->leaseterm;
  246: 	args->deadthresh = oargs->deadthresh;
  247: 	args->hostname = oargs->hostname;
  248: }
  249: 
  250: static void
  251: nfs_convert_diskless()
  252: {
  253: 	bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
  254: 		sizeof(struct ifaliasreq));
  255: 	bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
  256: 		sizeof(struct sockaddr_in));
  257: 	nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args);
  258: 	nfsv3_diskless.swap_fhsize = NFSX_V2FH;
  259: 	bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH);
  260: 	bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr,
  261: 		sizeof(struct sockaddr_in));
  262: 	bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, MNAMELEN);
  263: 	nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks;
  264: 	bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred,
  265: 		sizeof(struct ucred));
  266: 	nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
  267: 	nfsv3_diskless.root_fhsize = NFSX_V2FH;
  268: 	bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH);
  269: 	bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
  270: 		sizeof(struct sockaddr_in));
  271: 	bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, MNAMELEN);
  272: 	nfsv3_diskless.root_time = nfs_diskless.root_time;
  273: 	bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam,
  274: 		MAXHOSTNAMELEN);
  275: 	nfs_diskless_valid = 3;
  276: }
  277: 
  278: /*
  279:  * nfs statfs call
  280:  */
  281: int
  282: nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
  283: {
  284: 	struct vnode *vp;
  285: 	struct nfs_statfs *sfp;
  286: 	caddr_t cp;
  287: 	u_int32_t *tl;
  288: 	int32_t t1, t2;
  289: 	caddr_t bpos, dpos, cp2;
  290: 	struct nfsmount *nmp = VFSTONFS(mp);
  291: 	int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
  292: 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
  293: 	struct ucred *cred;
  294: 	struct nfsnode *np;
  295: 	u_quad_t tquad;
  296: 
  297: #ifndef nolint
  298: 	sfp = (struct nfs_statfs *)0;
  299: #endif
  300: 	error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  301: 	if (error)
  302: 		return (error);
  303: 	vp = NFSTOV(np);
  304: 	cred = crget();
  305: 	cred->cr_ngroups = 1;
  306: 	if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
  307: 		(void)nfs_fsinfo(nmp, vp, td);
  308: 	nfsstats.rpccnt[NFSPROC_FSSTAT]++;
  309: 	nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
  310: 	nfsm_fhtom(vp, v3);
  311: 	nfsm_request(vp, NFSPROC_FSSTAT, td, cred);
  312: 	if (v3)
  313: 		nfsm_postop_attr(vp, retattr);
  314: 	if (error) {
  315: 		if (mrep != NULL)
  316: 			m_freem(mrep);
  317: 		goto nfsmout;
  318: 	}
  319: 	nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
  320: 	sbp->f_flags = nmp->nm_flag;
  321: 	sbp->f_iosize = nfs_iosize(v3, nmp->nm_sotype);
  322: 
  323: 	if (v3) {
  324: 		sbp->f_bsize = NFS_FABLKSIZE;
  325: 		tquad = fxdr_hyper(&sfp->sf_tbytes);
  326: 		sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
  327: 		tquad = fxdr_hyper(&sfp->sf_fbytes);
  328: 		sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
  329: 		tquad = fxdr_hyper(&sfp->sf_abytes);
  330: 		sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
  331: 		sbp->f_files = (fxdr_unsigned(int32_t,
  332: 		    sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
  333: 		sbp->f_ffree = (fxdr_unsigned(int32_t,
  334: 		    sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
  335: 	} else {
  336: 		sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
  337: 		sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
  338: 		sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
  339: 		sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
  340: 		sbp->f_files = 0;
  341: 		sbp->f_ffree = 0;
  342: 	}
  343: 	if (sbp != &mp->mnt_stat) {
  344: 		sbp->f_type = mp->mnt_vfc->vfc_typenum;
  345: 		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  346: 		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
  347: 	}
  348: 	m_freem(mrep);
  349: nfsmout:
  350: 	vput(vp);
  351: 	crfree(cred);
  352: 	return (error);
  353: }
  354: 
  355: /*
  356:  * nfs version 3 fsinfo rpc call
  357:  */
  358: int
  359: nfs_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct thread *td)
  360: {
  361: 	struct nfsv3_fsinfo *fsp;
  362: 	caddr_t cp;
  363: 	int32_t t1, t2;
  364: 	u_int32_t *tl, pref, max;
  365: 	caddr_t bpos, dpos, cp2;
  366: 	int error = 0, retattr;
  367: 	struct mbuf *mreq, *mrep, *md, *mb, *mb2;
  368: 	u_int64_t maxfsize;
  369: 
  370: 	nfsstats.rpccnt[NFSPROC_FSINFO]++;
  371: 	nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
  372: 	nfsm_fhtom(vp, 1);
  373: 	nfsm_request(vp, NFSPROC_FSINFO, td, nfs_vpcred(vp, ND_READ));
  374: 	nfsm_postop_attr(vp, retattr);
  375: 	if (!error) {
  376: 		nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
  377: 		pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
  378: 		if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
  379: 			nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
  380: 				~(NFS_FABLKSIZE - 1);
  381: 		max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
  382: 		if (max < nmp->nm_wsize && max > 0) {
  383: 			nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
  384: 			if (nmp->nm_wsize == 0)
  385: 				nmp->nm_wsize = max;
  386: 		}
  387: 		pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
  388: 		if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
  389: 			nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
  390: 				~(NFS_FABLKSIZE - 1);
  391: 		max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
  392: 		if (max < nmp->nm_rsize && max > 0) {
  393: 			nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
  394: 			if (nmp->nm_rsize == 0)
  395: 				nmp->nm_rsize = max;
  396: 		}
  397: 		pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
  398: 		if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
  399: 			nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
  400: 				~(NFS_DIRBLKSIZ - 1);
  401: 		if (max < nmp->nm_readdirsize && max > 0) {
  402: 			nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
  403: 			if (nmp->nm_readdirsize == 0)
  404: 				nmp->nm_readdirsize = max;
  405: 		}
  406: 		maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
  407: 		if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
  408: 			nmp->nm_maxfilesize = maxfsize;
  409: 		nmp->nm_state |= NFSSTA_GOTFSINFO;
  410: 	}
  411: 	m_freem(mrep);
  412: nfsmout:
  413: 	return (error);
  414: }
  415: 
  416: /*
  417:  * Mount a remote root fs via. nfs. This depends on the info in the
  418:  * nfs_diskless structure that has been filled in properly by some primary
  419:  * bootstrap.
  420:  * It goes something like this:
  421:  * - do enough of "ifconfig" by calling ifioctl() so that the system
  422:  *   can talk to the server
  423:  * - If nfs_diskless.mygateway is filled in, use that address as
  424:  *   a default gateway.
  425:  * - build the rootfs mount point and call mountnfs() to do the rest.
  426:  */
  427: int
  428: nfs_mountroot(mp)
  429: 	struct mount *mp;
  430: {
  431: 	struct mount  *swap_mp;
  432: 	struct nfsv3_diskless *nd = &nfsv3_diskless;
  433: 	struct socket *so;
  434: 	struct vnode *vp;
  435: 	struct thread *td = curthread;		/* XXX */
  436: 	int error, i;
  437: 	u_long l;
  438: 	char buf[128];
  439: 
  440: #if defined(BOOTP_NFSROOT) && defined(BOOTP)
  441: 	bootpc_init();		/* use bootp to get nfs_diskless filled in */
  442: #endif
  443: 
  444: 	/*
  445: 	 * XXX time must be non-zero when we init the interface or else
  446: 	 * the arp code will wedge...
  447: 	 */
  448: 	while (mycpu->gd_time_seconds == 0)
  449: 		tsleep(mycpu, 0, "arpkludge", 10);
  450: 
  451: 	if (nfs_diskless_valid==1) 
  452: 	  nfs_convert_diskless();
  453: 
  454: 	/*
  455: 	 * XXX splnet, so networks will receive...
  456: 	 */
  457: 	splnet();
  458: 
  459: #ifdef notyet
  460: 	/* Set up swap credentials. */
  461: 	proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
  462: 	proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
  463: 	if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
  464: 		NGROUPS)
  465: 		proc0.p_ucred->cr_ngroups = NGROUPS;
  466: 	for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
  467: 	    proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
  468: #endif
  469: 
  470: 	/*
  471: 	 * Do enough of ifconfig(8) so that the critical net interface can
  472: 	 * talk to the server.
  473: 	 */
  474: 	error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, td);
  475: 	if (error)
  476: 		panic("nfs_mountroot: socreate(%04x): %d",
  477: 			nd->myif.ifra_addr.sa_family, error);
  478: 
  479: #if 0 /* XXX Bad idea */
  480: 	/*
  481: 	 * We might not have been told the right interface, so we pass
  482: 	 * over the first ten interfaces of the same kind, until we get
  483: 	 * one of them configured.
  484: 	 */
  485: 
  486: 	for (i = strlen(nd->myif.ifra_name) - 1;
  487: 		nd->myif.ifra_name[i] >= '0' &&
  488: 		nd->myif.ifra_name[i] <= '9';
  489: 		nd->myif.ifra_name[i] ++) {
  490: 		error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
  491: 		if(!error)
  492: 			break;
  493: 	}
  494: #endif
  495: 	error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
  496: 	if (error)
  497: 		panic("nfs_mountroot: SIOCAIFADDR: %d", error);
  498: 	soclose(so);
  499: 
  500: 	/*
  501: 	 * If the gateway field is filled in, set it as the default route.
  502: 	 */
  503: 	if (nd->mygateway.sin_len != 0) {
  504: 		struct sockaddr_in mask, sin;
  505: 
  506: 		bzero((caddr_t)&mask, sizeof(mask));
  507: 		sin = mask;
  508: 		sin.sin_family = AF_INET;
  509: 		sin.sin_len = sizeof(sin);
  510: 		error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
  511: 		    (struct sockaddr *)&nd->mygateway,
  512: 		    (struct sockaddr *)&mask,
  513: 		    RTF_UP | RTF_GATEWAY, (struct rtentry **)0);
  514: 		if (error)
  515: 			panic("nfs_mountroot: RTM_ADD: %d", error);
  516: 	}
  517: 
  518: 	/*
  519: 	 * Create the rootfs mount point.
  520: 	 */
  521: 	nd->root_args.fh = nd->root_fh;
  522: 	nd->root_args.fhsize = nd->root_fhsize;
  523: 	l = ntohl(nd->root_saddr.sin_addr.s_addr);
  524: 	snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
  525: 		(l >> 24) & 0xff, (l >> 16) & 0xff,
  526: 		(l >>  8) & 0xff, (l >>  0) & 0xff,nd->root_hostnam);
  527: 	printf("NFS ROOT: %s\n",buf);
  528: 	if ((error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
  529: 	    &nd->root_saddr, &nd->root_args, td, &vp, &mp)) != 0) {
  530: 		if (swap_mp) {
  531: 			mp->mnt_vfc->vfc_refcount--;
  532: 			free(swap_mp, M_MOUNT);
  533: 		}
  534: 		return (error);
  535: 	}
  536: 
  537: 	swap_mp = NULL;
  538: 	if (nd->swap_nblks) {
  539: 
  540: 		/* Convert to DEV_BSIZE instead of Kilobyte */
  541: 		nd->swap_nblks *= 2;
  542: 
  543: 		/*
  544: 		 * Create a fake mount point just for the swap vnode so that the
  545: 		 * swap file can be on a different server from the rootfs.
  546: 		 */
  547: 		nd->swap_args.fh = nd->swap_fh;
  548: 		nd->swap_args.fhsize = nd->swap_fhsize;
  549: 		l = ntohl(nd->swap_saddr.sin_addr.s_addr);
  550: 		snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
  551: 			(l >> 24) & 0xff, (l >> 16) & 0xff,
  552: 			(l >>  8) & 0xff, (l >>  0) & 0xff,nd->swap_hostnam);
  553: 		printf("NFS SWAP: %s\n",buf);
  554: 		if ((error = nfs_mountdiskless(buf, "/swap", 0,
  555: 		    &nd->swap_saddr, &nd->swap_args, td, &vp, &swap_mp)) != 0)
  556: 			return (error);
  557: 		vfs_unbusy(swap_mp, td);
  558: 
  559: 		VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size = 
  560: 				nd->swap_nblks * DEV_BSIZE ;
  561: 		
  562: 		/*
  563: 		 * Since the swap file is not the root dir of a file system,
  564: 		 * hack it to a regular file.
  565: 		 */
  566: 		vp->v_type = VREG;
  567: 		vp->v_flag = 0;
  568: 		vref(vp);
  569: 		swaponvp(td, vp, nd->swap_nblks);
  570: 	}
  571: 
  572: 	mp->mnt_flag |= MNT_ROOTFS;
  573: 	mp->mnt_vnodecovered = NULLVP;
  574: 	rootvp = vp;
  575: 	vfs_unbusy(mp, td);
  576: 
  577: 	/*
  578: 	 * This is not really an nfs issue, but it is much easier to
  579: 	 * set hostname here and then let the "/etc/rc.xxx" files
  580: 	 * mount the right /var based upon its preset value.
  581: 	 */
  582: 	bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
  583: 	hostname[MAXHOSTNAMELEN - 1] = '\0';
  584: 	for (i = 0; i < MAXHOSTNAMELEN; i++)
  585: 		if (hostname[i] == '\0')
  586: 			break;
  587: 	inittodr(ntohl(nd->root_time));
  588: 	return (0);
  589: }
  590: 
  591: /*
  592:  * Internal version of mount system call for diskless setup.
  593:  */
  594: static int
  595: nfs_mountdiskless(char *path, char *which, int mountflag,
  596: 	struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
  597: 	struct vnode **vpp, struct mount **mpp)
  598: {
  599: 	struct mount *mp;
  600: 	struct sockaddr *nam;
  601: 	int error;
  602: 	int didalloc = 0;
  603: 
  604: 	mp = *mpp;
  605: 
  606: 	if (mp == NULL) {
  607: 		if ((error = vfs_rootmountalloc("nfs", path, &mp)) != 0) {
  608: 			printf("nfs_mountroot: NFS not configured");
  609: 			return (error);
  610: 		}
  611: 		didalloc = 1;
  612: 	}
  613: 
  614: 	mp->mnt_kern_flag = 0;
  615: 	mp->mnt_flag = mountflag;
  616: 	nam = dup_sockaddr((struct sockaddr *)sin, 1);
  617: 	if ((error = mountnfs(args, mp, nam, which, path, vpp)) != 0) {
  618: 		printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
  619: 		mp->mnt_vfc->vfc_refcount--;
  620: 		vfs_unbusy(mp, td);
  621: 		if (didalloc)
  622: 			free(mp, M_MOUNT);
  623: 		FREE(nam, M_SONAME);
  624: 		return (error);
  625: 	}
  626: 	(void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
  627: 	*mpp = mp;
  628: 	return (0);
  629: }
  630: 
  631: static void
  632: nfs_decode_args(nmp, argp)
  633: 	struct nfsmount *nmp;
  634: 	struct nfs_args *argp;
  635: {
  636: 	int s;
  637: 	int adjsock;
  638: 	int maxio;
  639: 
  640: 	s = splnet();
  641: 	/*
  642: 	 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
  643: 	 * no sense in that context.
  644: 	 */
  645: 	if (argp->sotype == SOCK_STREAM)
  646: 		nmp->nm_flag &= ~NFSMNT_NOCONN;
  647: 
  648: 	/* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
  649: 	if ((argp->flags & NFSMNT_NFSV3) == 0)
  650: 		nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
  651: 
  652: 	/* Re-bind if rsrvd port requested and wasn't on one */
  653: 	adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
  654: 		  && (argp->flags & NFSMNT_RESVPORT);
  655: 	/* Also re-bind if we're switching to/from a connected UDP socket */
  656: 	adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
  657: 		    (argp->flags & NFSMNT_NOCONN));
  658: 
  659: 	/* Update flags atomically.  Don't change the lock bits. */
  660: 	nmp->nm_flag = argp->flags | nmp->nm_flag;
  661: 	splx(s);
  662: 
  663: 	if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
  664: 		nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
  665: 		if (nmp->nm_timeo < NFS_MINTIMEO)
  666: 			nmp->nm_timeo = NFS_MINTIMEO;
  667: 		else if (nmp->nm_timeo > NFS_MAXTIMEO)
  668: 			nmp->nm_timeo = NFS_MAXTIMEO;
  669: 	}
  670: 
  671: 	if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
  672: 		nmp->nm_retry = argp->retrans;
  673: 		if (nmp->nm_retry > NFS_MAXREXMIT)
  674: 			nmp->nm_retry = NFS_MAXREXMIT;
  675: 	}
  676: 
  677: 	maxio = nfs_iosize(argp->flags & NFSMNT_NFSV3, argp->sotype);
  678: 
  679: 	if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
  680: 		nmp->nm_wsize = argp->wsize;
  681: 		/* Round down to multiple of blocksize */
  682: 		nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
  683: 		if (nmp->nm_wsize <= 0)
  684: 			nmp->nm_wsize = NFS_FABLKSIZE;
  685: 	}
  686: 	if (nmp->nm_wsize > maxio)
  687: 		nmp->nm_wsize = maxio;
  688: 	if (nmp->nm_wsize > MAXBSIZE)
  689: 		nmp->nm_wsize = MAXBSIZE;
  690: 
  691: 	if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
  692: 		nmp->nm_rsize = argp->rsize;
  693: 		/* Round down to multiple of blocksize */
  694: 		nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
  695: 		if (nmp->nm_rsize <= 0)
  696: 			nmp->nm_rsize = NFS_FABLKSIZE;
  697: 	}
  698: 	if (nmp->nm_rsize > maxio)
  699: 		nmp->nm_rsize = maxio;
  700: 	if (nmp->nm_rsize > MAXBSIZE)
  701: 		nmp->nm_rsize = MAXBSIZE;
  702: 
  703: 	if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
  704: 		nmp->nm_readdirsize = argp->readdirsize;
  705: 	}
  706: 	if (nmp->nm_readdirsize > maxio)
  707: 		nmp->nm_readdirsize = maxio;
  708: 	if (nmp->nm_readdirsize > nmp->nm_rsize)
  709: 		nmp->nm_readdirsize = nmp->nm_rsize;
  710: 
  711: 	if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
  712: 		nmp->nm_acregmin = argp->acregmin;
  713: 	else
  714: 		nmp->nm_acregmin = NFS_MINATTRTIMO;
  715: 	if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
  716: 		nmp->nm_acregmax = argp->acregmax;
  717: 	else
  718: 		nmp->nm_acregmax = NFS_MAXATTRTIMO;
  719: 	if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
  720: 		nmp->nm_acdirmin = argp->acdirmin;
  721: 	else
  722: 		nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
  723: 	if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
  724: 		nmp->nm_acdirmax = argp->acdirmax;
  725: 	else
  726: 		nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
  727: 	if (nmp->nm_acdirmin > nmp->nm_acdirmax)
  728: 		nmp->nm_acdirmin = nmp->nm_acdirmax;
  729: 	if (nmp->nm_acregmin > nmp->nm_acregmax)
  730: 		nmp->nm_acregmin = nmp->nm_acregmax;
  731: 
  732: 	if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
  733: 		if (argp->maxgrouplist <= NFS_MAXGRPS)
  734: 			nmp->nm_numgrps = argp->maxgrouplist;
  735: 		else
  736: 			nmp->nm_numgrps = NFS_MAXGRPS;
  737: 	}
  738: 	if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
  739: 		if (argp->readahead <= NFS_MAXRAHEAD)
  740: 			nmp->nm_readahead = argp->readahead;
  741: 		else
  742: 			nmp->nm_readahead = NFS_MAXRAHEAD;
  743: 	}
  744: 	if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2) {
  745: 		if (argp->leaseterm <= NQ_MAXLEASE)
  746: 			nmp->nm_leaseterm = argp->leaseterm;
  747: 		else
  748: 			nmp->nm_leaseterm = NQ_MAXLEASE;
  749: 	}
  750: 	if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1) {
  751: 		if (argp->deadthresh <= NQ_NEVERDEAD)
  752: 			nmp->nm_deadthresh = argp->deadthresh;
  753: 		else
  754: 			nmp->nm_deadthresh = NQ_NEVERDEAD;
  755: 	}
  756: 
  757: 	adjsock |= ((nmp->nm_sotype != argp->sotype) ||
  758: 		    (nmp->nm_soproto != argp->proto));
  759: 	nmp->nm_sotype = argp->sotype;
  760: 	nmp->nm_soproto = argp->proto;
  761: 
  762: 	if (nmp->nm_so && adjsock) {
  763: 		nfs_safedisconnect(nmp);
  764: 		if (nmp->nm_sotype == SOCK_DGRAM)
  765: 			while (nfs_connect(nmp, (struct nfsreq *)0)) {
  766: 				printf("nfs_args: retrying connect\n");
  767: 				(void) tsleep((caddr_t)&lbolt, 0, "nfscon", 0);
  768: 			}
  769: 	}
  770: }
  771: 
  772: /*
  773:  * VFS Operations.
  774:  *
  775:  * mount system call
  776:  * It seems a bit dumb to copyinstr() the host and path here and then
  777:  * bcopy() them in mountnfs(), but I wanted to detect errors before
  778:  * doing the sockargs() call because sockargs() allocates an mbuf and
  779:  * an error after that means that I have to release the mbuf.
  780:  */
  781: /* ARGSUSED */
  782: static int
  783: nfs_mount(struct mount *mp, char *path, caddr_t data,
  784: 	struct nameidata *ndp, struct thread *td)
  785: {
  786: 	int error;
  787: 	struct nfs_args args;
  788: 	struct sockaddr *nam;
  789: 	struct vnode *vp;
  790: 	char pth[MNAMELEN], hst[MNAMELEN];
  791: 	size_t len;
  792: 	u_char nfh[NFSX_V3FHMAX];
  793: 
  794: 	if (path == NULL) {
  795: 		nfs_mountroot(mp);
  796: 		return (0);
  797: 	}
  798: 	error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
  799: 	if (error)
  800: 		return (error);
  801: 	if (args.version != NFS_ARGSVERSION) {
  802: #ifdef COMPAT_PRELITE2
  803: 		/*
  804: 		 * If the argument version is unknown, then assume the
  805: 		 * caller is a pre-lite2 4.4BSD client and convert its
  806: 		 * arguments.
  807: 		 */
  808: 		struct onfs_args oargs;
  809: 		error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
  810: 		if (error)
  811: 			return (error);
  812: 		nfs_convert_oargs(&args,&oargs);
  813: #else /* !COMPAT_PRELITE2 */
  814: 		return (EPROGMISMATCH);
  815: #endif /* COMPAT_PRELITE2 */
  816: 	}
  817: 	if (mp->mnt_flag & MNT_UPDATE) {
  818: 		struct nfsmount *nmp = VFSTONFS(mp);
  819: 
  820: 		if (nmp == NULL)
  821: 			return (EIO);
  822: 		/*
  823: 		 * When doing an update, we can't change from or to
  824: 		 * v3 and/or nqnfs, or change cookie translation
  825: 		 */
  826: 		args.flags = (args.flags &
  827: 		    ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) |
  828: 		    (nmp->nm_flag &
  829: 			(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/));
  830: 		nfs_decode_args(nmp, &args);
  831: 		return (0);
  832: 	}
  833: 
  834: 	/*
  835: 	 * Make the nfs_ip_paranoia sysctl serve as the default connection
  836: 	 * or no-connection mode for those protocols that support 
  837: 	 * no-connection mode (the flag will be cleared later for protocols
  838: 	 * that do not support no-connection mode).  This will allow a client
  839: 	 * to receive replies from a different IP then the request was
  840: 	 * sent to.  Note: default value for nfs_ip_paranoia is 1 (paranoid),
  841: 	 * not 0.
  842: 	 */
  843: 	if (nfs_ip_paranoia == 0)
  844: 		args.flags |= NFSMNT_NOCONN;
  845: 	if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
  846: 		return (EINVAL);
  847: 	error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
  848: 	if (error)
  849: 		return (error);
  850: 	error = copyinstr(path, pth, MNAMELEN-1, &len);
  851: 	if (error)
  852: 		return (error);
  853: 	bzero(&pth[len], MNAMELEN - len);
  854: 	error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
  855: 	if (error)
  856: 		return (error);
  857: 	bzero(&hst[len], MNAMELEN - len);
  858: 	/* sockargs() call must be after above copyin() calls */
  859: 	error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
  860: 	if (error)
  861: 		return (error);
  862: 	args.fh = nfh;
  863: 	error = mountnfs(&args, mp, nam, pth, hst, &vp);
  864: 	return (error);
  865: }
  866: 
  867: /*
  868:  * Common code for mount and mountroot
  869:  */
  870: static int
  871: mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
  872: 	char *pth, char *hst, struct vnode **vpp)
  873: {
  874: 	struct nfsmount *nmp;
  875: 	struct nfsnode *np;
  876: 	int error;
  877: 
  878: 	if (mp->mnt_flag & MNT_UPDATE) {
  879: 		nmp = VFSTONFS(mp);
  880: 		/* update paths, file handles, etc, here	XXX */
  881: 		FREE(nam, M_SONAME);
  882: 		return (0);
  883: 	} else {
  884: 		nmp = zalloc(nfsmount_zone);
  885: 		bzero((caddr_t)nmp, sizeof (struct nfsmount));
  886: 		TAILQ_INIT(&nmp->nm_uidlruhead);
  887: 		TAILQ_INIT(&nmp->nm_bufq);
  888: 		mp->mnt_data = (qaddr_t)nmp;
  889: 	}
  890: 	vfs_getnewfsid(mp);
  891: 	nmp->nm_mountp = mp;
  892: 	if (argp->flags & NFSMNT_NQNFS)
  893: 		/*
  894: 		 * We have to set mnt_maxsymlink to a non-zero value so
  895: 		 * that COMPAT_43 routines will know that we are setting
  896: 		 * the d_type field in directories (and can zero it for
  897: 		 * unsuspecting binaries).
  898: 		 */
  899: 		mp->mnt_maxsymlinklen = 1;
  900: 
  901: 	/*
  902: 	 * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
  903: 	 * high, depending on whether we end up with negative offsets in
  904: 	 * the client or server somewhere.  2GB-1 may be safer.
  905: 	 *
  906: 	 * For V3, nfs_fsinfo will adjust this as necessary.  Assume maximum
  907: 	 * that we can handle until we find out otherwise.
  908: 	 * XXX Our "safe" limit on the client is what we can store in our
  909: 	 * buffer cache using signed(!) block numbers.
  910: 	 */
  911: 	if ((argp->flags & NFSMNT_NFSV3) == 0)
  912: 		nmp->nm_maxfilesize = 0xffffffffLL;
  913: 	else
  914: 		nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
  915: 
  916: 	nmp->nm_timeo = NFS_TIMEO;
  917: 	nmp->nm_retry = NFS_RETRANS;
  918: 	nmp->nm_wsize = nfs_iosize(argp->flags & NFSMNT_NFSV3, argp->sotype);
  919: 	nmp->nm_rsize = nmp->nm_wsize;
  920: 	nmp->nm_readdirsize = NFS_READDIRSIZE;
  921: 	nmp->nm_numgrps = NFS_MAXGRPS;
  922: 	nmp->nm_readahead = NFS_DEFRAHEAD;
  923: 	nmp->nm_leaseterm = NQ_DEFLEASE;
  924: 	nmp->nm_deadthresh = NQ_DEADTHRESH;
  925: 	CIRCLEQ_INIT(&nmp->nm_timerhead);
  926: 	nmp->nm_inprog = NULLVP;
  927: 	nmp->nm_fhsize = argp->fhsize;
  928: 	bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
  929: 	bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
  930: 	bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
  931: 	nmp->nm_nam = nam;
  932: 	/* Set up the sockets and per-host congestion */
  933: 	nmp->nm_sotype = argp->sotype;
  934: 	nmp->nm_soproto = argp->proto;
  935: 	nmp->nm_cred = crhold(proc0.p_ucred);
  936: 
  937: 	nfs_decode_args(nmp, argp);
  938: 
  939: 	/*
  940: 	 * For Connection based sockets (TCP,...) defer the connect until
  941: 	 * the first request, in case the server is not responding.
  942: 	 */
  943: 	if (nmp->nm_sotype == SOCK_DGRAM &&
  944: 		(error = nfs_connect(nmp, (struct nfsreq *)0)))
  945: 		goto bad;
  946: 
  947: 	/*
  948: 	 * This is silly, but it has to be set so that vinifod() works.
  949: 	 * We do not want to do an nfs_statfs() here since we can get
  950: 	 * stuck on a dead server and we are holding a lock on the mount
  951: 	 * point.
  952: 	 */
  953: 	mp->mnt_stat.f_iosize = 
  954: 		nfs_iosize(nmp->nm_flag & NFSMNT_NFSV3, nmp->nm_sotype);
  955: 
  956: 	/*
  957: 	 * A reference count is needed on the nfsnode representing the
  958: 	 * remote root.  If this object is not persistent, then backward
  959: 	 * traversals of the mount point (i.e. "..") will not work if
  960: 	 * the nfsnode gets flushed out of the cache. Ufs does not have
  961: 	 * this problem, because one can identify root inodes by their
  962: 	 * number == ROOTINO (2).
  963: 	 */
  964: 	error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  965: 	if (error)
  966: 		goto bad;
  967: 	*vpp = NFSTOV(np);
  968: 
  969: 	/*
  970: 	 * Retrieval of mountpoint attributes is delayed until nfs_rot
  971: 	 * or nfs_statfs are first called.  This will happen either when
  972: 	 * we first traverse the mount point or if somebody does a df(1).
  973: 	 *
  974: 	 * NFSSTA_GOTFSINFO is used to flag if we have successfully
  975: 	 * retrieved mountpoint attributes.  In the case of NFSv3 we
  976: 	 * also flag static fsinfo.
  977: 	 */
  978: 	if (*vpp != NULL)
  979: 		(*vpp)->v_type = VNON;
  980: 
  981: 	/*
  982: 	 * Lose the lock but keep the ref.
  983: 	 */
  984: 	VOP_UNLOCK(*vpp, NULL, 0, curthread);
  985: 
  986: 	return (0);
  987: bad:
  988: 	nfs_disconnect(nmp);
  989: 	nfs_free_mount(nmp);
  990: 	FREE(nam, M_SONAME);
  991: 	return (error);
  992: }
  993: 
  994: /*
  995:  * unmount system call
  996:  */
  997: static int
  998: nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
  999: {
 1000: 	struct nfsmount *nmp;
 1001: 	int error, flags = 0;
 1002: 
 1003: 	if (mntflags & MNT_FORCE)
 1004: 		flags |= FORCECLOSE;
 1005: 	nmp = VFSTONFS(mp);
 1006: 	/*
 1007: 	 * Goes something like this..
 1008: 	 * - Call vflush() to clear out vnodes for this file system
 1009: 	 * - Close the socket
 1010: 	 * - Free up the data structures
 1011: 	 */
 1012: 	/* In the forced case, cancel any outstanding requests. */
 1013: 	if (flags & FORCECLOSE) {
 1014: 		error = nfs_nmcancelreqs(nmp);
 1015: 		if (error)
 1016: 			return (error);
 1017: 	}
 1018: 	/*
 1019: 	 * Must handshake with nqnfs_clientd() if it is active.
 1020: 	 */
 1021: 	nmp->nm_state |= NFSSTA_DISMINPROG;
 1022: 	while (nmp->nm_inprog != NULLVP)
 1023: 		(void) tsleep((caddr_t)&lbolt, 0, "nfsdism", 0);
 1024: 
 1025: 	/* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
 1026: 	error = vflush(mp, 1, flags);
 1027: 	if (error) {
 1028: 		nmp->nm_state &= ~NFSSTA_DISMINPROG;
 1029: 		return (error);
 1030: 	}
 1031: 
 1032: 	/*
 1033: 	 * We are now committed to the unmount.
 1034: 	 * For NQNFS, let the server daemon free the nfsmount structure.
 1035: 	 */
 1036: 	if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB))
 1037: 		nmp->nm_state |= NFSSTA_DISMNT;
 1038: 
 1039: 	nfs_disconnect(nmp);
 1040: 	FREE(nmp->nm_nam, M_SONAME);
 1041: 
 1042: 	if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
 1043: 		nfs_free_mount(nmp);
 1044: 	return (0);
 1045: }
 1046: 
 1047: void
 1048: nfs_free_mount(struct nfsmount *nmp)
 1049: {
 1050: 	if (nmp->nm_cred)  {
 1051: 		crfree(nmp->nm_cred);
 1052: 		nmp->nm_cred = NULL;
 1053: 	}
 1054: 	zfree(nfsmount_zone, nmp);
 1055: }
 1056: 
 1057: /*
 1058:  * Return root of a filesystem
 1059:  */
 1060: static int
 1061: nfs_root(mp, vpp)
 1062: 	struct mount *mp;
 1063: 	struct vnode **vpp;
 1064: {
 1065: 	struct vnode *vp;
 1066: 	struct nfsmount *nmp;
 1067: 	struct vattr attrs;
 1068: 	struct nfsnode *np;
 1069: 	int error;
 1070: 
 1071: 	nmp = VFSTONFS(mp);
 1072: 	error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
 1073: 	if (error)
 1074: 		return (error);
 1075: 	vp = NFSTOV(np);
 1076: 
 1077: 	/*
 1078: 	 * Get transfer parameters and root vnode attributes
 1079: 	 */
 1080: 	if ((nmp->nm_state & NFSSTA_GOTFSINFO) == 0) {
 1081: 	    if (nmp->nm_flag & NFSMNT_NFSV3) {
 1082: 		nfs_fsinfo(nmp, vp, curthread);
 1083: 		mp->mnt_stat.f_iosize = nfs_iosize(1, nmp->nm_sotype);
 1084: 	    } else {
 1085: 		if ((error = VOP_GETATTR(vp, &attrs, curthread)) == 0)
 1086: 			nmp->nm_state |= NFSSTA_GOTFSINFO;
 1087: 		
 1088: 	    }
 1089: 	}
 1090: 	if (vp->v_type == VNON)
 1091: 	    vp->v_type = VDIR;
 1092: 	vp->v_flag = VROOT;
 1093: 	*vpp = vp;
 1094: 	return (0);
 1095: }
 1096: 
 1097: extern int syncprt;
 1098: 
 1099: struct scaninfo {
 1100: 	int rescan;
 1101: 	thread_t td;
 1102: 	int waitfor;
 1103: 	int allerror;
 1104: };
 1105: 
 1106: static int nfs_sync_scan1(struct mount *mp, struct vnode *vp, void *data);
 1107: static int nfs_sync_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data);
 1108: 
 1109: /*
 1110:  * Flush out the buffer cache
 1111:  */
 1112: /* ARGSUSED */
 1113: static int
 1114: nfs_sync(struct mount *mp, int waitfor, struct thread *td)
 1115: {
 1116: 	struct scaninfo scaninfo;
 1117: 	int error;
 1118: 
 1119: 	scaninfo.rescan = 0;
 1120: 	scaninfo.td = td;
 1121: 	scaninfo.waitfor = waitfor;
 1122: 	scaninfo.allerror = 0;
 1123: 
 1124: 	/*
 1125: 	 * Force stale buffer cache information to be flushed.
 1126: 	 */
 1127: 	error = 0;
 1128: 	while (error == 0 && scaninfo.rescan) {
 1129: 		scaninfo.rescan = 0;
 1130: 		error = vmntvnodescan(mp, nfs_sync_scan1,
 1131: 					nfs_sync_scan2, &scaninfo);
 1132: 	}
 1133: 	return(error);
 1134: }
 1135: 
 1136: static
 1137: int
 1138: nfs_sync_scan1(struct mount *mp, struct vnode *vp, void *data)
 1139: {
 1140:     struct scaninfo *info = data;
 1141: 
 1142:     if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd))
 1143: 	return(-1);
 1144:     if (info->waitfor == MNT_LAZY)
 1145: 	return(-1);
 1146:     return(0);
 1147: }
 1148: 
 1149: static
 1150: int
 1151: nfs_sync_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data)
 1152: {
 1153:     struct scaninfo *info = data;
 1154:     int error;
 1155: 
 1156:     if (vget(vp, vlock, LK_EXCLUSIVE | LK_INTERLOCK, info->td)) {
 1157: 	info->rescan = 1;
 1158: 	return(0);
 1159:     }
 1160:     error = VOP_FSYNC(vp, info->waitfor, info->td);
 1161:     if (error)
 1162: 	info->allerror = error;
 1163:     vput(vp);
 1164:     return(0);
 1165: }
 1166: