2004-05-23 02:52:13 +04:00
|
|
|
/* $NetBSD: nfs_vfsops.c,v 1.138 2004/05/22 22:52:16 jonathan Exp $ */
|
1994-06-29 10:39:25 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1996-02-18 14:53:36 +03:00
|
|
|
* Copyright (c) 1989, 1993, 1995
|
1994-06-08 15:33:09 +04:00
|
|
|
* The Regents of the University of California. All rights reserved.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Rick Macklem at The University of Guelph.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-08-07 20:26:28 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1993-03-21 12:45:37 +03:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
1996-02-18 14:53:36 +03:00
|
|
|
* @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
|
2001-11-10 13:59:08 +03:00
|
|
|
#include <sys/cdefs.h>
|
2004-05-23 02:52:13 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.138 2004/05/22 22:52:16 jonathan Exp $");
|
2001-11-10 13:59:08 +03:00
|
|
|
|
2001-05-30 15:40:35 +04:00
|
|
|
#if defined(_KERNEL_OPT)
|
1998-07-05 12:49:30 +04:00
|
|
|
#include "opt_compat_netbsd.h"
|
2000-09-19 21:04:50 +04:00
|
|
|
#include "opt_nfs.h"
|
1998-07-05 12:49:30 +04:00
|
|
|
#endif
|
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/signal.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/namei.h>
|
1997-01-31 06:00:31 +03:00
|
|
|
#include <sys/device.h>
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/vnode.h>
|
1994-06-08 15:33:09 +04:00
|
|
|
#include <sys/kernel.h>
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/buf.h>
|
|
|
|
#include <sys/mbuf.h>
|
2004-04-21 05:05:31 +04:00
|
|
|
#include <sys/dirent.h>
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/socket.h>
|
1996-02-10 00:48:19 +03:00
|
|
|
#include <sys/socketvar.h>
|
2000-04-16 01:14:48 +04:00
|
|
|
#include <sys/sysctl.h>
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/systm.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/route.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
#include <nfs/rpcv2.h>
|
1996-02-18 14:53:36 +03:00
|
|
|
#include <nfs/nfsproto.h>
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <nfs/nfsnode.h>
|
|
|
|
#include <nfs/nfs.h>
|
1996-02-18 14:53:36 +03:00
|
|
|
#include <nfs/nfsmount.h>
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <nfs/xdr_subs.h>
|
|
|
|
#include <nfs/nfsm_subs.h>
|
|
|
|
#include <nfs/nfsdiskless.h>
|
1994-06-08 15:33:09 +04:00
|
|
|
#include <nfs/nqnfs.h>
|
1996-02-10 00:48:19 +03:00
|
|
|
#include <nfs/nfs_var.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1996-12-03 03:22:43 +03:00
|
|
|
extern struct nfsstats nfsstats;
|
1996-02-18 14:53:36 +03:00
|
|
|
extern int nfs_ticks;
|
|
|
|
|
2003-02-01 09:23:35 +03:00
|
|
|
MALLOC_DEFINE(M_NFSMNT, "NFS mount", "NFS mount structure");
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* nfs vfs operations.
|
|
|
|
*/
|
1998-02-18 10:05:47 +03:00
|
|
|
|
2001-01-22 15:17:35 +03:00
|
|
|
extern const struct vnodeopv_desc nfsv2_vnodeop_opv_desc;
|
|
|
|
extern const struct vnodeopv_desc spec_nfsv2nodeop_opv_desc;
|
|
|
|
extern const struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc;
|
1998-02-18 10:05:47 +03:00
|
|
|
|
2001-01-22 15:17:35 +03:00
|
|
|
const struct vnodeopv_desc * const nfs_vnodeopv_descs[] = {
|
1998-02-18 10:05:47 +03:00
|
|
|
&nfsv2_vnodeop_opv_desc,
|
|
|
|
&spec_nfsv2nodeop_opv_desc,
|
|
|
|
&fifo_nfsv2nodeop_opv_desc,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
struct vfsops nfs_vfsops = {
|
1994-04-14 08:05:45 +04:00
|
|
|
MOUNT_NFS,
|
1993-03-21 12:45:37 +03:00
|
|
|
nfs_mount,
|
|
|
|
nfs_start,
|
|
|
|
nfs_unmount,
|
|
|
|
nfs_root,
|
|
|
|
nfs_quotactl,
|
2004-04-21 05:05:31 +04:00
|
|
|
nfs_statvfs,
|
1993-03-21 12:45:37 +03:00
|
|
|
nfs_sync,
|
1994-06-08 15:33:09 +04:00
|
|
|
nfs_vget,
|
1993-03-21 12:45:37 +03:00
|
|
|
nfs_fhtovp,
|
|
|
|
nfs_vptofh,
|
1996-12-03 03:22:43 +03:00
|
|
|
nfs_vfs_init,
|
2001-09-15 20:12:54 +04:00
|
|
|
nfs_vfs_reinit,
|
2000-03-16 21:08:17 +03:00
|
|
|
nfs_vfs_done,
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
NULL,
|
1997-01-31 06:00:31 +03:00
|
|
|
nfs_mountroot,
|
1999-02-27 02:44:43 +03:00
|
|
|
nfs_checkexp,
|
1998-02-18 10:05:47 +03:00
|
|
|
nfs_vnodeopv_descs,
|
1993-03-21 12:45:37 +03:00
|
|
|
};
|
|
|
|
|
1996-02-18 14:53:36 +03:00
|
|
|
extern u_int32_t nfs_procids[NFS_NPROCS];
|
|
|
|
extern u_int32_t nfs_prog, nfs_vers;
|
1994-06-13 19:28:55 +04:00
|
|
|
|
1997-10-10 05:53:17 +04:00
|
|
|
static int nfs_mount_diskless __P((struct nfs_dlmount *, const char *,
|
2003-06-30 02:28:00 +04:00
|
|
|
struct mount **, struct vnode **, struct proc *));
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
2004-04-21 05:05:31 +04:00
|
|
|
* nfs statvfs call
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
2004-04-21 05:05:31 +04:00
|
|
|
nfs_statvfs(mp, sbp, p)
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mount *mp;
|
2004-04-21 05:05:31 +04:00
|
|
|
struct statvfs *sbp;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2000-03-30 16:51:13 +04:00
|
|
|
struct vnode *vp;
|
|
|
|
struct nfs_statfs *sfp;
|
|
|
|
caddr_t cp;
|
|
|
|
u_int32_t *tl;
|
|
|
|
int32_t t1, t2;
|
1993-03-21 12:45:37 +03:00
|
|
|
caddr_t bpos, dpos, cp2;
|
1996-02-18 14:53:36 +03:00
|
|
|
struct nfsmount *nmp = VFSTONFS(mp);
|
2000-09-19 21:04:50 +04:00
|
|
|
int error = 0, retattr;
|
|
|
|
#ifdef NFS_V2_ONLY
|
|
|
|
const int v3 = 0;
|
|
|
|
#else
|
|
|
|
int v3 = (nmp->nm_flag & NFSMNT_NFSV3);
|
|
|
|
#endif
|
2003-02-26 09:31:08 +03:00
|
|
|
struct mbuf *mreq, *mrep = NULL, *md, *mb;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct ucred *cred;
|
1996-02-18 14:53:36 +03:00
|
|
|
u_quad_t tquad;
|
2003-04-25 01:21:04 +04:00
|
|
|
struct nfsnode *np;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1996-02-18 14:53:36 +03:00
|
|
|
#ifndef nolint
|
|
|
|
sfp = (struct nfs_statfs *)0;
|
|
|
|
#endif
|
2001-02-12 23:02:30 +03:00
|
|
|
vp = nmp->nm_vnode;
|
2003-04-25 01:21:04 +04:00
|
|
|
np = VTONFS(vp);
|
1993-03-21 12:45:37 +03:00
|
|
|
cred = crget();
|
1995-06-02 23:50:11 +04:00
|
|
|
cred->cr_ngroups = 0;
|
2001-12-04 21:38:08 +03:00
|
|
|
#ifndef NFS_V2_ONLY
|
1997-10-10 05:53:17 +04:00
|
|
|
if (v3 && (nmp->nm_iflag & NFSMNT_GOTFSINFO) == 0)
|
2003-06-30 02:28:00 +04:00
|
|
|
(void)nfs_fsinfo(nmp, vp, cred, p);
|
2001-12-04 21:38:08 +03:00
|
|
|
#endif
|
1996-02-18 14:53:36 +03:00
|
|
|
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
|
2003-04-25 01:21:04 +04:00
|
|
|
nfsm_reqhead(np, NFSPROC_FSSTAT, NFSX_FH(v3));
|
|
|
|
nfsm_fhtom(np, v3);
|
2003-06-30 02:28:00 +04:00
|
|
|
nfsm_request(np, NFSPROC_FSSTAT, p, cred);
|
1996-02-18 14:53:36 +03:00
|
|
|
if (v3)
|
2002-10-21 16:52:32 +04:00
|
|
|
nfsm_postop_attr(vp, retattr, 0);
|
1996-03-25 02:58:10 +03:00
|
|
|
if (error) {
|
2003-10-02 10:01:51 +04:00
|
|
|
if (mrep != NULL) {
|
|
|
|
if (mrep->m_next != NULL)
|
2004-04-21 05:05:31 +04:00
|
|
|
printf("nfs_vfsops: nfs_statvfs would lose buffers\n");
|
2003-10-02 10:01:51 +04:00
|
|
|
m_freem(mrep);
|
|
|
|
}
|
1996-03-25 02:58:10 +03:00
|
|
|
goto nfsmout;
|
|
|
|
}
|
|
|
|
nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_flag = nmp->nm_flag;
|
1996-02-18 14:53:36 +03:00
|
|
|
sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
|
|
|
|
if (v3) {
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_frsize = sbp->f_bsize = NFS_FABLKSIZE;
|
1999-03-06 08:34:40 +03:00
|
|
|
tquad = fxdr_hyper(&sfp->sf_tbytes);
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_blocks = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE);
|
1999-03-06 08:34:40 +03:00
|
|
|
tquad = fxdr_hyper(&sfp->sf_fbytes);
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_bfree = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE);
|
1999-03-06 08:34:40 +03:00
|
|
|
tquad = fxdr_hyper(&sfp->sf_abytes);
|
2004-04-21 05:05:31 +04:00
|
|
|
tquad = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE);
|
|
|
|
sbp->f_bresvd = sbp->f_bfree - tquad;
|
|
|
|
sbp->f_bavail = tquad;
|
|
|
|
#ifdef COMPAT_20
|
|
|
|
/* Handle older NFS servers returning negative values */
|
|
|
|
if ((quad_t)sbp->f_bavail < 0)
|
|
|
|
sbp->f_bavail = 0;
|
|
|
|
#endif
|
1999-03-06 08:34:40 +03:00
|
|
|
tquad = fxdr_hyper(&sfp->sf_tfiles);
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_files = tquad;
|
1999-03-06 08:34:40 +03:00
|
|
|
tquad = fxdr_hyper(&sfp->sf_ffiles);
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_ffree = tquad;
|
|
|
|
sbp->f_favail = tquad;
|
|
|
|
sbp->f_fresvd = 0;
|
|
|
|
sbp->f_namemax = MAXNAMLEN;
|
1994-06-08 15:33:09 +04:00
|
|
|
} else {
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_bsize = NFS_FABLKSIZE;
|
|
|
|
sbp->f_frsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
|
1996-02-18 14:53:36 +03:00
|
|
|
sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
|
|
|
|
sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
|
|
|
|
sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_fresvd = 0;
|
1994-06-08 15:33:09 +04:00
|
|
|
sbp->f_files = 0;
|
|
|
|
sbp->f_ffree = 0;
|
2004-04-21 05:05:31 +04:00
|
|
|
sbp->f_favail = 0;
|
|
|
|
sbp->f_fresvd = 0;
|
|
|
|
sbp->f_namemax = MAXNAMLEN;
|
1994-06-08 15:33:09 +04:00
|
|
|
}
|
2004-04-21 05:05:31 +04:00
|
|
|
copy_statvfs_info(sbp, mp);
|
1993-03-21 12:45:37 +03:00
|
|
|
nfsm_reqdone;
|
|
|
|
crfree(cred);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2000-09-19 21:04:50 +04:00
|
|
|
#ifndef NFS_V2_ONLY
|
1996-02-18 14:53:36 +03:00
|
|
|
/*
|
|
|
|
* nfs version 3 fsinfo rpc call
|
|
|
|
*/
|
|
|
|
int
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_fsinfo(nmp, vp, cred, p)
|
2000-03-30 16:51:13 +04:00
|
|
|
struct nfsmount *nmp;
|
|
|
|
struct vnode *vp;
|
1996-02-18 14:53:36 +03:00
|
|
|
struct ucred *cred;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1996-02-18 14:53:36 +03:00
|
|
|
{
|
2000-03-30 16:51:13 +04:00
|
|
|
struct nfsv3_fsinfo *fsp;
|
|
|
|
caddr_t cp;
|
|
|
|
int32_t t1, t2;
|
|
|
|
u_int32_t *tl, pref, max;
|
1996-02-18 14:53:36 +03:00
|
|
|
caddr_t bpos, dpos, cp2;
|
|
|
|
int error = 0, retattr;
|
2003-02-26 09:31:08 +03:00
|
|
|
struct mbuf *mreq, *mrep, *md, *mb;
|
1997-07-18 03:54:27 +04:00
|
|
|
u_int64_t maxfsize;
|
2003-04-25 01:21:04 +04:00
|
|
|
struct nfsnode *np = VTONFS(vp);
|
1996-02-18 14:53:36 +03:00
|
|
|
|
|
|
|
nfsstats.rpccnt[NFSPROC_FSINFO]++;
|
2003-04-25 01:21:04 +04:00
|
|
|
nfsm_reqhead(np, NFSPROC_FSINFO, NFSX_FH(1));
|
|
|
|
nfsm_fhtom(np, 1);
|
2003-06-30 02:28:00 +04:00
|
|
|
nfsm_request(np, NFSPROC_FSINFO, p, cred);
|
2002-10-21 16:52:32 +04:00
|
|
|
nfsm_postop_attr(vp, retattr, 0);
|
1996-02-18 14:53:36 +03:00
|
|
|
if (!error) {
|
|
|
|
nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
|
|
|
|
pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
|
2003-03-28 15:33:17 +03:00
|
|
|
if ((nmp->nm_flag & NFSMNT_WSIZE) == 0 &&
|
|
|
|
pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
|
|
|
|
~(NFS_FABLKSIZE - 1);
|
|
|
|
max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
|
1997-07-18 03:54:27 +04:00
|
|
|
if (max < nmp->nm_wsize && max > 0) {
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
|
|
|
|
if (nmp->nm_wsize == 0)
|
|
|
|
nmp->nm_wsize = max;
|
|
|
|
}
|
|
|
|
pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
|
2003-03-28 15:33:17 +03:00
|
|
|
if ((nmp->nm_flag & NFSMNT_RSIZE) == 0 &&
|
|
|
|
pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
|
|
|
|
~(NFS_FABLKSIZE - 1);
|
|
|
|
max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
|
1997-07-18 03:54:27 +04:00
|
|
|
if (max < nmp->nm_rsize && max > 0) {
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
|
|
|
|
if (nmp->nm_rsize == 0)
|
|
|
|
nmp->nm_rsize = max;
|
|
|
|
}
|
|
|
|
pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
|
1997-10-10 05:53:17 +04:00
|
|
|
if (pref < nmp->nm_readdirsize && pref >= NFS_DIRFRAGSIZ)
|
|
|
|
nmp->nm_readdirsize = (pref + NFS_DIRFRAGSIZ - 1) &
|
|
|
|
~(NFS_DIRFRAGSIZ - 1);
|
1997-07-18 03:54:27 +04:00
|
|
|
if (max < nmp->nm_readdirsize && max > 0) {
|
1997-10-10 05:53:17 +04:00
|
|
|
nmp->nm_readdirsize = max & ~(NFS_DIRFRAGSIZ - 1);
|
1996-02-18 14:53:36 +03:00
|
|
|
if (nmp->nm_readdirsize == 0)
|
|
|
|
nmp->nm_readdirsize = max;
|
|
|
|
}
|
1997-07-18 03:54:27 +04:00
|
|
|
/* XXX */
|
|
|
|
nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
|
1999-03-06 08:34:40 +03:00
|
|
|
maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
|
1997-07-18 03:54:27 +04:00
|
|
|
if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
|
|
|
|
nmp->nm_maxfilesize = maxfsize;
|
1997-10-10 05:53:17 +04:00
|
|
|
nmp->nm_iflag |= NFSMNT_GOTFSINFO;
|
1996-02-18 14:53:36 +03:00
|
|
|
}
|
|
|
|
nfsm_reqdone;
|
|
|
|
return (error);
|
|
|
|
}
|
2000-09-19 21:04:50 +04:00
|
|
|
#endif
|
1996-02-18 14:53:36 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1994-06-13 19:28:55 +04:00
|
|
|
* Mount a remote root fs via. NFS. It goes like this:
|
|
|
|
* - Call nfs_boot_init() to fill in the nfs_diskless struct
|
1994-06-08 15:33:09 +04:00
|
|
|
* - build the rootfs mount point and call mountnfs() to do the rest.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
1993-03-21 12:45:37 +03:00
|
|
|
nfs_mountroot()
|
|
|
|
{
|
1997-08-29 20:12:49 +04:00
|
|
|
struct nfs_diskless *nd;
|
1994-06-13 19:28:55 +04:00
|
|
|
struct vattr attr;
|
|
|
|
struct mount *mp;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct vnode *vp;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *procp;
|
1994-06-13 19:28:55 +04:00
|
|
|
long n;
|
|
|
|
int error;
|
|
|
|
|
2003-06-30 02:28:00 +04:00
|
|
|
procp = curproc; /* XXX */
|
1994-06-13 19:28:55 +04:00
|
|
|
|
1997-01-31 06:00:31 +03:00
|
|
|
if (root_device->dv_class != DV_IFNET)
|
|
|
|
return (ENODEV);
|
|
|
|
|
1994-06-14 07:29:12 +04:00
|
|
|
/*
|
|
|
|
* XXX time must be non-zero when we init the interface or else
|
|
|
|
* the arp code will wedge. [Fixed now in if_ether.c]
|
|
|
|
* However, the NFS attribute cache gives false "hits" when
|
|
|
|
* time.tv_sec < NFS_ATTRTIMEO(np) so keep this in for now.
|
|
|
|
*/
|
|
|
|
if (time.tv_sec < NFS_MAXATTRTIMO)
|
|
|
|
time.tv_sec = NFS_MAXATTRTIMO;
|
|
|
|
|
1994-06-13 19:28:55 +04:00
|
|
|
/*
|
|
|
|
* Call nfs_boot_init() to fill in the nfs_diskless struct.
|
|
|
|
* Side effect: Finds and configures a network interface.
|
|
|
|
*/
|
1997-08-29 20:12:49 +04:00
|
|
|
nd = malloc(sizeof(*nd), M_NFSMNT, M_WAITOK);
|
1998-08-10 00:51:08 +04:00
|
|
|
memset((caddr_t)nd, 0, sizeof(*nd));
|
2003-06-30 02:28:00 +04:00
|
|
|
error = nfs_boot_init(nd, procp);
|
1999-02-21 18:11:09 +03:00
|
|
|
if (error) {
|
|
|
|
free(nd, M_NFSMNT);
|
|
|
|
return (error);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
1994-06-13 19:28:55 +04:00
|
|
|
* Create the root mount point.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2003-06-30 02:28:00 +04:00
|
|
|
error = nfs_mount_diskless(&nd->nd_root, "/", &mp, &vp, procp);
|
1997-05-28 03:37:39 +04:00
|
|
|
if (error)
|
1997-08-29 20:12:49 +04:00
|
|
|
goto out;
|
|
|
|
printf("root on %s\n", nd->nd_root.ndm_host);
|
1994-06-13 19:28:55 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Link it into the mount list.
|
|
|
|
*/
|
1996-02-18 14:53:36 +03:00
|
|
|
simple_lock(&mountlist_slock);
|
|
|
|
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
|
|
|
|
simple_unlock(&mountlist_slock);
|
|
|
|
rootvp = vp;
|
1994-06-13 19:28:55 +04:00
|
|
|
mp->mnt_vnodecovered = NULLVP;
|
1998-03-01 05:20:01 +03:00
|
|
|
vfs_unbusy(mp);
|
1994-06-13 19:28:55 +04:00
|
|
|
|
|
|
|
/* Get root attributes (for the time). */
|
2003-06-30 02:28:00 +04:00
|
|
|
error = VOP_GETATTR(vp, &attr, procp->p_ucred, procp);
|
1997-05-28 03:37:39 +04:00
|
|
|
if (error)
|
|
|
|
panic("nfs_mountroot: getattr for root");
|
1998-09-29 01:20:52 +04:00
|
|
|
n = attr.va_atime.tv_sec;
|
1994-06-14 07:29:12 +04:00
|
|
|
#ifdef DEBUG
|
1996-10-13 05:39:03 +04:00
|
|
|
printf("root time: 0x%lx\n", n);
|
1994-06-14 07:29:12 +04:00
|
|
|
#endif
|
1994-06-13 19:28:55 +04:00
|
|
|
inittodr(n);
|
1994-06-08 15:33:09 +04:00
|
|
|
|
1997-08-29 20:12:49 +04:00
|
|
|
out:
|
1999-02-21 18:11:09 +03:00
|
|
|
if (error)
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_boot_cleanup(nd, procp);
|
1997-08-29 20:12:49 +04:00
|
|
|
free(nd, M_NFSMNT);
|
|
|
|
return (error);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
/*
|
|
|
|
* Internal version of mount system call for diskless setup.
|
1997-08-29 20:12:49 +04:00
|
|
|
* Separate function because we used to call it twice.
|
|
|
|
* (once for root and once for swap)
|
1994-06-08 15:33:09 +04:00
|
|
|
*/
|
1997-05-28 03:37:39 +04:00
|
|
|
static int
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_mount_diskless(ndmntp, mntname, mpp, vpp, p)
|
1994-06-13 19:28:55 +04:00
|
|
|
struct nfs_dlmount *ndmntp;
|
1997-05-28 03:37:39 +04:00
|
|
|
const char *mntname; /* mount point name */
|
|
|
|
struct mount **mpp;
|
1994-06-13 19:28:55 +04:00
|
|
|
struct vnode **vpp;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1994-06-08 15:33:09 +04:00
|
|
|
{
|
1994-06-13 19:28:55 +04:00
|
|
|
struct mount *mp;
|
|
|
|
struct mbuf *m;
|
|
|
|
int error;
|
1994-06-08 15:33:09 +04:00
|
|
|
|
1998-03-01 05:20:01 +03:00
|
|
|
vfs_rootmountalloc(MOUNT_NFS, (char *)mntname, &mp);
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
mp->mnt_op = &nfs_vfsops;
|
1998-03-03 22:07:20 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Historical practice expects NFS root file systems to
|
|
|
|
* be initially mounted r/w.
|
|
|
|
*/
|
|
|
|
mp->mnt_flag &= ~MNT_RDONLY;
|
1994-06-13 19:28:55 +04:00
|
|
|
|
|
|
|
/* Get mbuf for server sockaddr. */
|
1994-08-14 07:35:27 +04:00
|
|
|
m = m_get(M_WAIT, MT_SONAME);
|
1996-10-20 17:13:22 +04:00
|
|
|
if (m == NULL)
|
|
|
|
panic("nfs_mountroot: mget soname for %s", mntname);
|
2003-02-26 09:31:08 +03:00
|
|
|
MCLAIM(m, &nfs_mowner);
|
1998-08-10 00:51:08 +04:00
|
|
|
memcpy(mtod(m, caddr_t), (caddr_t)ndmntp->ndm_args.addr,
|
1996-10-20 17:13:22 +04:00
|
|
|
(m->m_len = ndmntp->ndm_args.addr->sa_len));
|
1994-06-08 15:33:09 +04:00
|
|
|
|
1996-10-20 17:13:22 +04:00
|
|
|
error = mountnfs(&ndmntp->ndm_args, mp, m, mntname,
|
2003-06-30 02:28:00 +04:00
|
|
|
ndmntp->ndm_args.hostname, vpp, p);
|
1997-05-28 03:37:39 +04:00
|
|
|
if (error) {
|
1998-03-01 05:20:01 +03:00
|
|
|
mp->mnt_op->vfs_refcount--;
|
|
|
|
vfs_unbusy(mp);
|
1997-05-28 03:37:39 +04:00
|
|
|
printf("nfs_mountroot: mount %s failed: %d\n",
|
|
|
|
mntname, error);
|
|
|
|
free(mp, M_MOUNT);
|
|
|
|
} else
|
|
|
|
*mpp = mp;
|
1994-06-08 15:33:09 +04:00
|
|
|
|
1997-05-28 03:37:39 +04:00
|
|
|
return (error);
|
1994-06-08 15:33:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-05-23 02:52:13 +04:00
|
|
|
nfs_decode_args(nmp, argp, p)
|
1994-06-08 15:33:09 +04:00
|
|
|
struct nfsmount *nmp;
|
|
|
|
struct nfs_args *argp;
|
2004-05-23 02:52:13 +04:00
|
|
|
struct proc *p;
|
1993-12-07 02:38:14 +03:00
|
|
|
{
|
1994-06-08 15:33:09 +04:00
|
|
|
int s;
|
1994-08-23 13:31:00 +04:00
|
|
|
int adjsock;
|
1996-02-18 14:53:36 +03:00
|
|
|
int maxio;
|
1993-12-08 02:37:43 +03:00
|
|
|
|
1995-08-13 03:59:09 +04:00
|
|
|
s = splsoftnet();
|
1994-08-23 13:31:00 +04:00
|
|
|
|
1997-02-22 05:48:26 +03:00
|
|
|
/*
|
|
|
|
* Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
|
|
|
|
* no sense in that context.
|
|
|
|
*/
|
|
|
|
if (argp->sotype == SOCK_STREAM)
|
|
|
|
argp->flags &= ~NFSMNT_NOCONN;
|
|
|
|
|
1997-10-19 05:46:15 +04:00
|
|
|
/*
|
|
|
|
* Cookie translation is not needed for v2, silently ignore it.
|
|
|
|
*/
|
|
|
|
if ((argp->flags & (NFSMNT_XLATECOOKIE|NFSMNT_NFSV3)) ==
|
|
|
|
NFSMNT_XLATECOOKIE)
|
|
|
|
argp->flags &= ~NFSMNT_XLATECOOKIE;
|
|
|
|
|
1994-08-23 13:31:00 +04:00
|
|
|
/* Re-bind if rsrvd port requested and wasn't on one */
|
|
|
|
adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
|
|
|
|
&& (argp->flags & NFSMNT_RESVPORT);
|
1997-02-05 00:33:19 +03:00
|
|
|
/* Also re-bind if we're switching to/from a connected UDP socket */
|
|
|
|
adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
|
|
|
|
(argp->flags & NFSMNT_NOCONN));
|
1994-08-23 13:31:00 +04:00
|
|
|
|
2000-08-23 13:59:22 +04:00
|
|
|
/* Update flags. */
|
|
|
|
nmp->nm_flag = argp->flags;
|
1993-12-08 02:37:43 +03:00
|
|
|
splx(s);
|
1993-12-07 02:38:14 +03:00
|
|
|
|
|
|
|
if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
|
1994-06-08 15:33:09 +04:00
|
|
|
nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
|
|
|
|
if (nmp->nm_timeo < NFS_MINTIMEO)
|
|
|
|
nmp->nm_timeo = NFS_MINTIMEO;
|
|
|
|
else if (nmp->nm_timeo > NFS_MAXTIMEO)
|
|
|
|
nmp->nm_timeo = NFS_MAXTIMEO;
|
1993-12-07 02:38:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
|
|
|
|
nmp->nm_retry = argp->retrans;
|
|
|
|
if (nmp->nm_retry > NFS_MAXREXMIT)
|
|
|
|
nmp->nm_retry = NFS_MAXREXMIT;
|
|
|
|
}
|
|
|
|
|
2000-09-19 21:04:50 +04:00
|
|
|
#ifndef NFS_V2_ONLY
|
1996-02-18 14:53:36 +03:00
|
|
|
if (argp->flags & NFSMNT_NFSV3) {
|
|
|
|
if (argp->sotype == SOCK_DGRAM)
|
|
|
|
maxio = NFS_MAXDGRAMDATA;
|
|
|
|
else
|
|
|
|
maxio = NFS_MAXDATA;
|
|
|
|
} else
|
2000-09-19 21:04:50 +04:00
|
|
|
#endif
|
1996-02-18 14:53:36 +03:00
|
|
|
maxio = NFS_V2MAXDATA;
|
|
|
|
|
1993-12-07 02:38:14 +03:00
|
|
|
if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
|
1994-08-23 13:31:00 +04:00
|
|
|
int osize = nmp->nm_wsize;
|
1993-12-07 02:38:14 +03:00
|
|
|
nmp->nm_wsize = argp->wsize;
|
|
|
|
/* Round down to multiple of blocksize */
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
|
1993-12-07 02:38:14 +03:00
|
|
|
if (nmp->nm_wsize <= 0)
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_wsize = NFS_FABLKSIZE;
|
1994-08-23 13:31:00 +04:00
|
|
|
adjsock |= (nmp->nm_wsize != osize);
|
1993-12-07 02:38:14 +03:00
|
|
|
}
|
1996-02-18 14:53:36 +03:00
|
|
|
if (nmp->nm_wsize > maxio)
|
|
|
|
nmp->nm_wsize = maxio;
|
1993-12-07 02:38:14 +03:00
|
|
|
if (nmp->nm_wsize > MAXBSIZE)
|
|
|
|
nmp->nm_wsize = MAXBSIZE;
|
|
|
|
|
|
|
|
if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
|
1994-08-23 13:31:00 +04:00
|
|
|
int osize = nmp->nm_rsize;
|
1993-12-07 02:38:14 +03:00
|
|
|
nmp->nm_rsize = argp->rsize;
|
|
|
|
/* Round down to multiple of blocksize */
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
|
1993-12-07 02:38:14 +03:00
|
|
|
if (nmp->nm_rsize <= 0)
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_rsize = NFS_FABLKSIZE;
|
1994-08-23 13:31:00 +04:00
|
|
|
adjsock |= (nmp->nm_rsize != osize);
|
1993-12-07 02:38:14 +03:00
|
|
|
}
|
1996-02-18 14:53:36 +03:00
|
|
|
if (nmp->nm_rsize > maxio)
|
|
|
|
nmp->nm_rsize = maxio;
|
1993-12-07 02:38:14 +03:00
|
|
|
if (nmp->nm_rsize > MAXBSIZE)
|
|
|
|
nmp->nm_rsize = MAXBSIZE;
|
1994-06-08 15:33:09 +04:00
|
|
|
|
1996-02-18 14:53:36 +03:00
|
|
|
if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
|
|
|
|
nmp->nm_readdirsize = argp->readdirsize;
|
1997-10-10 05:53:17 +04:00
|
|
|
/* Round down to multiple of minimum blocksize */
|
|
|
|
nmp->nm_readdirsize &= ~(NFS_DIRFRAGSIZ - 1);
|
|
|
|
if (nmp->nm_readdirsize < NFS_DIRFRAGSIZ)
|
|
|
|
nmp->nm_readdirsize = NFS_DIRFRAGSIZ;
|
|
|
|
/* Bigger than buffer size makes no sense */
|
|
|
|
if (nmp->nm_readdirsize > NFS_DIRBLKSIZ)
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_readdirsize = NFS_DIRBLKSIZ;
|
1996-03-13 03:38:55 +03:00
|
|
|
} else if (argp->flags & NFSMNT_RSIZE)
|
|
|
|
nmp->nm_readdirsize = nmp->nm_rsize;
|
|
|
|
|
1996-02-18 14:53:36 +03:00
|
|
|
if (nmp->nm_readdirsize > maxio)
|
|
|
|
nmp->nm_readdirsize = maxio;
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
|
|
|
|
argp->maxgrouplist <= NFS_MAXGRPS)
|
|
|
|
nmp->nm_numgrps = argp->maxgrouplist;
|
|
|
|
if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 &&
|
|
|
|
argp->readahead <= NFS_MAXRAHEAD)
|
|
|
|
nmp->nm_readahead = argp->readahead;
|
|
|
|
if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 &&
|
|
|
|
argp->leaseterm <= NQ_MAXLEASE)
|
|
|
|
nmp->nm_leaseterm = argp->leaseterm;
|
|
|
|
if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 &&
|
|
|
|
argp->deadthresh <= NQ_NEVERDEAD)
|
|
|
|
nmp->nm_deadthresh = argp->deadthresh;
|
1994-08-23 13:31:00 +04:00
|
|
|
|
1996-10-20 17:13:22 +04:00
|
|
|
adjsock |= ((nmp->nm_sotype != argp->sotype) ||
|
|
|
|
(nmp->nm_soproto != argp->proto));
|
|
|
|
nmp->nm_sotype = argp->sotype;
|
|
|
|
nmp->nm_soproto = argp->proto;
|
|
|
|
|
1994-08-23 13:31:00 +04:00
|
|
|
if (nmp->nm_so && adjsock) {
|
1998-03-24 16:49:21 +03:00
|
|
|
nfs_safedisconnect(nmp);
|
1994-08-23 13:31:00 +04:00
|
|
|
if (nmp->nm_sotype == SOCK_DGRAM)
|
2004-05-23 02:52:13 +04:00
|
|
|
while (nfs_connect(nmp, (struct nfsreq *)0, p)) {
|
1996-10-13 05:39:03 +04:00
|
|
|
printf("nfs_args: retrying connect\n");
|
1994-08-23 13:31:00 +04:00
|
|
|
(void) tsleep((caddr_t)&lbolt,
|
1998-11-13 01:31:02 +03:00
|
|
|
PSOCK, "nfscn3", 0);
|
1994-08-23 13:31:00 +04:00
|
|
|
}
|
|
|
|
}
|
1993-12-07 02:38:14 +03:00
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* VFS Operations.
|
|
|
|
*
|
|
|
|
* mount system call
|
|
|
|
* It seems a bit dumb to copyinstr() the host and path here and then
|
1998-08-10 00:51:08 +04:00
|
|
|
* memcpy() them in mountnfs(), but I wanted to detect errors before
|
1993-03-21 12:45:37 +03:00
|
|
|
* doing the sockargs() call because sockargs() allocates an mbuf and
|
|
|
|
* an error after that means that I have to release the mbuf.
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_mount(mp, path, data, ndp, p)
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mount *mp;
|
1996-12-22 13:10:12 +03:00
|
|
|
const char *path;
|
|
|
|
void *data;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct nameidata *ndp;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct nfs_args args;
|
|
|
|
struct mbuf *nam;
|
2002-10-21 07:58:07 +04:00
|
|
|
struct nfsmount *nmp = VFSTONFS(mp);
|
|
|
|
struct sockaddr *sa;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct vnode *vp;
|
2002-07-26 05:36:30 +04:00
|
|
|
char *pth, *hst;
|
1995-03-09 15:05:21 +03:00
|
|
|
size_t len;
|
2002-07-26 05:36:30 +04:00
|
|
|
u_char *nfh;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2002-10-21 07:58:07 +04:00
|
|
|
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
2002-09-21 22:08:27 +04:00
|
|
|
if (mp->mnt_flag & MNT_GETARGS) {
|
2002-10-21 07:58:07 +04:00
|
|
|
|
2002-09-21 22:08:27 +04:00
|
|
|
if (nmp == NULL)
|
2002-10-21 07:58:07 +04:00
|
|
|
return (EIO);
|
|
|
|
if (args.addr != NULL) {
|
|
|
|
sa = mtod(nmp->nm_nam, struct sockaddr *);
|
|
|
|
error = copyout(sa, args.addr, sa->sa_len);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2002-11-24 14:02:57 +03:00
|
|
|
args.addrlen = sa->sa_len;
|
|
|
|
} else
|
|
|
|
args.addrlen = 0;
|
|
|
|
|
2002-09-21 22:08:27 +04:00
|
|
|
args.version = NFS_ARGSVERSION;
|
|
|
|
args.sotype = nmp->nm_sotype;
|
|
|
|
args.proto = nmp->nm_soproto;
|
|
|
|
args.fh = NULL;
|
|
|
|
args.fhsize = 0;
|
|
|
|
args.flags = nmp->nm_flag;
|
|
|
|
args.wsize = nmp->nm_wsize;
|
|
|
|
args.rsize = nmp->nm_rsize;
|
|
|
|
args.readdirsize = nmp->nm_readdirsize;
|
|
|
|
args.timeo = nmp->nm_timeo;
|
|
|
|
args.retrans = nmp->nm_retry;
|
|
|
|
args.maxgrouplist = nmp->nm_numgrps;
|
|
|
|
args.readahead = nmp->nm_readahead;
|
|
|
|
args.leaseterm = nmp->nm_leaseterm;
|
2002-10-01 19:00:04 +04:00
|
|
|
args.deadthresh = nmp->nm_deadthresh;
|
2002-09-21 22:08:27 +04:00
|
|
|
args.hostname = NULL;
|
2002-10-21 07:58:07 +04:00
|
|
|
return (copyout(&args, data, sizeof(args)));
|
2002-09-21 22:08:27 +04:00
|
|
|
}
|
|
|
|
|
1996-02-18 14:53:36 +03:00
|
|
|
if (args.version != NFS_ARGSVERSION)
|
|
|
|
return (EPROGMISMATCH);
|
2000-09-19 21:04:50 +04:00
|
|
|
#ifdef NFS_V2_ONLY
|
2001-04-28 20:11:47 +04:00
|
|
|
if (args.flags & NFSMNT_NQNFS)
|
|
|
|
return (EPROGUNAVAIL);
|
|
|
|
if (args.flags & NFSMNT_NFSV3)
|
|
|
|
return (EPROGMISMATCH);
|
2000-09-19 21:04:50 +04:00
|
|
|
#endif
|
1993-12-07 02:38:14 +03:00
|
|
|
if (mp->mnt_flag & MNT_UPDATE) {
|
|
|
|
if (nmp == NULL)
|
1994-06-08 15:33:09 +04:00
|
|
|
return (EIO);
|
1996-05-24 02:47:27 +04:00
|
|
|
/*
|
|
|
|
* When doing an update, we can't change from or to
|
1997-10-19 05:46:15 +04:00
|
|
|
* v3 and/or nqnfs, or change cookie translation
|
1996-05-24 02:47:27 +04:00
|
|
|
*/
|
1997-10-19 05:46:15 +04:00
|
|
|
args.flags = (args.flags &
|
|
|
|
~(NFSMNT_NFSV3|NFSMNT_NQNFS|NFSMNT_XLATECOOKIE)) |
|
|
|
|
(nmp->nm_flag &
|
|
|
|
(NFSMNT_NFSV3|NFSMNT_NQNFS|NFSMNT_XLATECOOKIE));
|
2004-05-23 02:52:13 +04:00
|
|
|
nfs_decode_args(nmp, &args, p);
|
1993-12-07 02:38:14 +03:00
|
|
|
return (0);
|
|
|
|
}
|
2001-07-31 02:23:42 +04:00
|
|
|
if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
|
|
|
|
return (EINVAL);
|
2002-07-25 23:03:27 +04:00
|
|
|
MALLOC(nfh, u_char *, NFSX_V3FHMAX, M_TEMP, M_WAITOK);
|
2001-07-31 02:51:06 +04:00
|
|
|
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
|
1996-02-10 00:48:19 +03:00
|
|
|
if (error)
|
2002-07-26 05:36:30 +04:00
|
|
|
return (error);
|
2002-07-25 23:03:27 +04:00
|
|
|
MALLOC(pth, char *, MNAMELEN, M_TEMP, M_WAITOK);
|
2002-07-26 05:36:30 +04:00
|
|
|
error = copyinstr(path, pth, MNAMELEN - 1, &len);
|
1996-02-18 14:53:36 +03:00
|
|
|
if (error)
|
2002-07-26 05:36:30 +04:00
|
|
|
goto free_nfh;
|
1998-08-10 00:51:08 +04:00
|
|
|
memset(&pth[len], 0, MNAMELEN - len);
|
2002-07-25 23:03:27 +04:00
|
|
|
MALLOC(hst, char *, MNAMELEN, M_TEMP, M_WAITOK);
|
2002-07-26 05:36:30 +04:00
|
|
|
error = copyinstr(args.hostname, hst, MNAMELEN - 1, &len);
|
1996-02-18 14:53:36 +03:00
|
|
|
if (error)
|
2002-07-26 05:36:30 +04:00
|
|
|
goto free_pth;
|
1998-08-10 00:51:08 +04:00
|
|
|
memset(&hst[len], 0, MNAMELEN - len);
|
2002-07-26 05:36:30 +04:00
|
|
|
/* sockargs() call must be after above copyin() calls */
|
|
|
|
error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME);
|
|
|
|
if (error)
|
|
|
|
goto free_hst;
|
2003-02-26 09:31:08 +03:00
|
|
|
MCLAIM(nam, &nfs_mowner);
|
1996-02-18 14:53:36 +03:00
|
|
|
args.fh = nfh;
|
2003-06-30 02:28:00 +04:00
|
|
|
error = mountnfs(&args, mp, nam, pth, hst, &vp, p);
|
2002-07-25 23:03:27 +04:00
|
|
|
|
2002-07-26 05:36:30 +04:00
|
|
|
free_hst:
|
|
|
|
FREE(hst, M_TEMP);
|
|
|
|
free_pth:
|
|
|
|
FREE(pth, M_TEMP);
|
|
|
|
free_nfh:
|
2002-07-25 23:03:27 +04:00
|
|
|
FREE(nfh, M_TEMP);
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Common code for mount and mountroot
|
|
|
|
*/
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
2003-06-30 02:28:00 +04:00
|
|
|
mountnfs(argp, mp, nam, pth, hst, vpp, p)
|
2000-03-30 16:51:13 +04:00
|
|
|
struct nfs_args *argp;
|
|
|
|
struct mount *mp;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mbuf *nam;
|
1996-12-22 13:10:12 +03:00
|
|
|
const char *pth, *hst;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct vnode **vpp;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2000-03-30 16:51:13 +04:00
|
|
|
struct nfsmount *nmp;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct nfsnode *np;
|
|
|
|
int error;
|
2002-07-25 23:03:27 +04:00
|
|
|
struct vattr *attrs;
|
1997-10-10 05:53:17 +04:00
|
|
|
struct ucred *cr;
|
1993-11-19 05:31:23 +03:00
|
|
|
|
2000-05-07 05:38:36 +04:00
|
|
|
/*
|
|
|
|
* If the number of nfs iothreads to use has never
|
|
|
|
* been set, create a reasonable number of them.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (nfs_niothreads < 0) {
|
2001-07-01 06:13:35 +04:00
|
|
|
nfs_niothreads = NFS_DEFAULT_NIOTHREADS;
|
2000-05-07 05:38:36 +04:00
|
|
|
nfs_getset_niothreads(TRUE);
|
|
|
|
}
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
if (mp->mnt_flag & MNT_UPDATE) {
|
|
|
|
nmp = VFSTONFS(mp);
|
|
|
|
/* update paths, file handles, etc, here XXX */
|
|
|
|
m_freem(nam);
|
|
|
|
return (0);
|
|
|
|
} else {
|
|
|
|
MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
|
|
|
|
M_NFSMNT, M_WAITOK);
|
1998-08-10 00:51:08 +04:00
|
|
|
memset((caddr_t)nmp, 0, sizeof (struct nfsmount));
|
2002-07-30 11:40:07 +04:00
|
|
|
mp->mnt_data = nmp;
|
1996-02-18 14:53:36 +03:00
|
|
|
TAILQ_INIT(&nmp->nm_uidlruhead);
|
1996-12-03 01:55:39 +03:00
|
|
|
TAILQ_INIT(&nmp->nm_bufq);
|
2003-05-03 20:28:57 +04:00
|
|
|
lockinit(&nmp->nm_writeverflock, PRIBIO, "nfswverf", 0, 0);
|
|
|
|
simple_lock_init(&nmp->nm_slock);
|
1994-06-08 15:33:09 +04:00
|
|
|
}
|
2000-06-10 22:27:01 +04:00
|
|
|
vfs_getnewfsid(mp);
|
1993-03-21 12:45:37 +03:00
|
|
|
nmp->nm_mountp = mp;
|
1997-07-18 03:54:27 +04:00
|
|
|
|
2000-09-19 21:04:50 +04:00
|
|
|
#ifndef NFS_V2_ONLY
|
1994-06-08 15:33:09 +04:00
|
|
|
if (argp->flags & NFSMNT_NQNFS)
|
|
|
|
/*
|
|
|
|
* We have to set mnt_maxsymlink to a non-zero value so
|
|
|
|
* that COMPAT_43 routines will know that we are setting
|
|
|
|
* the d_type field in directories (and can zero it for
|
|
|
|
* unsuspecting binaries).
|
|
|
|
*/
|
|
|
|
mp->mnt_maxsymlinklen = 1;
|
2000-09-19 21:04:50 +04:00
|
|
|
#endif
|
1997-07-18 03:54:27 +04:00
|
|
|
|
2000-09-19 21:04:50 +04:00
|
|
|
#ifndef NFS_V2_ONLY
|
1997-07-18 21:31:46 +04:00
|
|
|
if ((argp->flags & NFSMNT_NFSV3) == 0)
|
2000-09-19 21:04:50 +04:00
|
|
|
#endif
|
1997-07-18 03:54:27 +04:00
|
|
|
/*
|
|
|
|
* V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo
|
|
|
|
* will fill this in.
|
|
|
|
*/
|
|
|
|
nmp->nm_maxfilesize = 0xffffffffLL;
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
nmp->nm_timeo = NFS_TIMEO;
|
1993-03-21 12:45:37 +03:00
|
|
|
nmp->nm_retry = NFS_RETRANS;
|
|
|
|
nmp->nm_wsize = NFS_WSIZE;
|
|
|
|
nmp->nm_rsize = NFS_RSIZE;
|
1996-02-18 14:53:36 +03:00
|
|
|
nmp->nm_readdirsize = NFS_READDIRSIZE;
|
1994-06-08 15:33:09 +04:00
|
|
|
nmp->nm_numgrps = NFS_MAXGRPS;
|
|
|
|
nmp->nm_readahead = NFS_DEFRAHEAD;
|
|
|
|
nmp->nm_leaseterm = NQ_DEFLEASE;
|
|
|
|
nmp->nm_deadthresh = NQ_DEADTHRESH;
|
1994-08-19 02:47:43 +04:00
|
|
|
CIRCLEQ_INIT(&nmp->nm_timerhead);
|
1994-06-08 15:33:09 +04:00
|
|
|
nmp->nm_inprog = NULLVP;
|
2004-04-21 05:05:31 +04:00
|
|
|
error = set_statvfs_info(pth, UIO_SYSSPACE, hst, UIO_SYSSPACE, mp, p);
|
2003-04-17 01:44:18 +04:00
|
|
|
if (error)
|
|
|
|
goto bad;
|
1993-03-21 12:45:37 +03:00
|
|
|
nmp->nm_nam = nam;
|
|
|
|
|
|
|
|
/* Set up the sockets and per-host congestion */
|
|
|
|
nmp->nm_sotype = argp->sotype;
|
|
|
|
nmp->nm_soproto = argp->proto;
|
|
|
|
|
2004-05-23 02:52:13 +04:00
|
|
|
nfs_decode_args(nmp, argp, p);
|
1996-10-20 17:13:22 +04:00
|
|
|
|
2001-09-20 12:22:04 +04:00
|
|
|
mp->mnt_fs_bshift = ffs(MIN(nmp->nm_rsize, nmp->nm_wsize)) - 1;
|
|
|
|
mp->mnt_dev_bshift = DEV_BSHIFT;
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
/*
|
|
|
|
* For Connection based sockets (TCP,...) defer the connect until
|
|
|
|
* the first request, in case the server is not responding.
|
|
|
|
*/
|
|
|
|
if (nmp->nm_sotype == SOCK_DGRAM &&
|
2004-05-23 02:52:13 +04:00
|
|
|
(error = nfs_connect(nmp, (struct nfsreq *)0, p)))
|
1993-03-21 12:45:37 +03:00
|
|
|
goto bad;
|
1994-06-08 15:33:09 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This is silly, but it has to be set so that vinifod() works.
|
2004-04-21 05:05:31 +04:00
|
|
|
* We do not want to do an nfs_statvfs() here since we can get
|
1994-06-08 15:33:09 +04:00
|
|
|
* stuck on a dead server and we are holding a lock on the mount
|
|
|
|
* point.
|
|
|
|
*/
|
|
|
|
mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
|
2003-06-30 02:28:00 +04:00
|
|
|
error = nfs_nget(mp, (nfsfh_t *)argp->fh, argp->fhsize, &np);
|
1996-02-18 14:53:36 +03:00
|
|
|
if (error)
|
1993-03-21 12:45:37 +03:00
|
|
|
goto bad;
|
|
|
|
*vpp = NFSTOV(np);
|
2002-07-25 23:03:27 +04:00
|
|
|
MALLOC(attrs, struct vattr *, sizeof(struct vattr), M_TEMP, M_WAITOK);
|
2003-06-30 02:28:00 +04:00
|
|
|
VOP_GETATTR(*vpp, attrs, p->p_ucred, p);
|
1998-03-03 16:32:28 +03:00
|
|
|
if ((nmp->nm_flag & NFSMNT_NFSV3) && ((*vpp)->v_type == VDIR)) {
|
1997-10-10 05:53:17 +04:00
|
|
|
cr = crget();
|
2002-07-25 23:03:27 +04:00
|
|
|
cr->cr_uid = attrs->va_uid;
|
|
|
|
cr->cr_gid = attrs->va_gid;
|
1997-10-10 05:53:17 +04:00
|
|
|
cr->cr_ngroups = 0;
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_cookieheuristic(*vpp, &nmp->nm_iflag, p, cr);
|
1997-10-10 05:53:17 +04:00
|
|
|
crfree(cr);
|
|
|
|
}
|
2002-07-25 23:03:27 +04:00
|
|
|
FREE(attrs, M_TEMP);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2001-02-06 14:40:02 +03:00
|
|
|
/*
|
|
|
|
* A reference count is needed on the nfsnode representing the
|
|
|
|
* remote root. If this object is not persistent, then backward
|
|
|
|
* traversals of the mount point (i.e. "..") will not work if
|
|
|
|
* the nfsnode gets flushed out of the cache. Ufs does not have
|
|
|
|
* this problem, because one can identify root inodes by their
|
|
|
|
* number == ROOTINO (2). So, just unlock, but no rele.
|
|
|
|
*/
|
|
|
|
|
2001-02-12 23:02:30 +03:00
|
|
|
nmp->nm_vnode = *vpp;
|
2001-02-06 14:40:02 +03:00
|
|
|
VOP_UNLOCK(*vpp, 0);
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
return (0);
|
|
|
|
bad:
|
|
|
|
nfs_disconnect(nmp);
|
1994-06-08 15:33:09 +04:00
|
|
|
free((caddr_t)nmp, M_NFSMNT);
|
1993-03-21 12:45:37 +03:00
|
|
|
m_freem(nam);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* unmount system call
|
|
|
|
*/
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_unmount(mp, mntflags, p)
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mount *mp;
|
|
|
|
int mntflags;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2000-03-30 16:51:13 +04:00
|
|
|
struct nfsmount *nmp;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct vnode *vp;
|
|
|
|
int error, flags = 0;
|
|
|
|
|
1995-01-18 09:15:17 +03:00
|
|
|
if (mntflags & MNT_FORCE)
|
1993-03-21 12:45:37 +03:00
|
|
|
flags |= FORCECLOSE;
|
|
|
|
nmp = VFSTONFS(mp);
|
|
|
|
/*
|
|
|
|
* Goes something like this..
|
|
|
|
* - Check for activity on the root vnode (other than ourselves).
|
|
|
|
* - Call vflush() to clear out vnodes for this file system,
|
|
|
|
* except for the root vnode.
|
|
|
|
* - Decrement reference on the vnode representing remote root.
|
|
|
|
* - Close the socket
|
|
|
|
* - Free up the data structures
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* We need to decrement the ref. count on the nfsnode representing
|
|
|
|
* the remote root. See comment in mountnfs(). The VFS unmount()
|
|
|
|
* has done vput on this vnode, otherwise we would get deadlock!
|
|
|
|
*/
|
2001-02-12 23:02:30 +03:00
|
|
|
vp = nmp->nm_vnode;
|
2003-06-29 22:43:21 +04:00
|
|
|
error = vget(vp, LK_EXCLUSIVE | LK_RETRY);
|
2001-02-12 23:02:30 +03:00
|
|
|
if (error != 0)
|
|
|
|
return error;
|
|
|
|
|
1996-06-24 14:26:40 +04:00
|
|
|
if ((mntflags & MNT_FORCE) == 0 && vp->v_usecount > 2) {
|
1993-03-21 12:45:37 +03:00
|
|
|
vput(vp);
|
|
|
|
return (EBUSY);
|
|
|
|
}
|
1994-06-08 15:33:09 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Must handshake with nqnfs_clientd() if it is active.
|
|
|
|
*/
|
1997-10-10 05:53:17 +04:00
|
|
|
nmp->nm_iflag |= NFSMNT_DISMINPROG;
|
1994-06-08 15:33:09 +04:00
|
|
|
while (nmp->nm_inprog != NULLVP)
|
|
|
|
(void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0);
|
1996-02-18 14:53:36 +03:00
|
|
|
error = vflush(mp, vp, flags);
|
|
|
|
if (error) {
|
1993-03-21 12:45:37 +03:00
|
|
|
vput(vp);
|
1997-10-10 05:53:17 +04:00
|
|
|
nmp->nm_iflag &= ~NFSMNT_DISMINPROG;
|
1993-03-21 12:45:37 +03:00
|
|
|
return (error);
|
|
|
|
}
|
1994-06-08 15:33:09 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1999-08-29 22:32:15 +04:00
|
|
|
* We are now committed to the unmount; mark the mount structure
|
|
|
|
* as doomed so that any sleepers kicked awake by nfs_disconnect
|
|
|
|
* will go away cleanly.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
1999-08-29 22:32:15 +04:00
|
|
|
nmp->nm_iflag |= NFSMNT_DISMNT;
|
1994-06-08 15:33:09 +04:00
|
|
|
|
|
|
|
/*
|
2001-02-06 14:40:02 +03:00
|
|
|
* There are two reference counts to get rid of here
|
|
|
|
* (see comment in mountnfs()).
|
1994-06-08 15:33:09 +04:00
|
|
|
*/
|
|
|
|
vrele(vp);
|
2001-02-06 14:40:02 +03:00
|
|
|
vput(vp);
|
1994-04-10 05:22:23 +04:00
|
|
|
vgone(vp);
|
1993-03-21 12:45:37 +03:00
|
|
|
nfs_disconnect(nmp);
|
|
|
|
m_freem(nmp->nm_nam);
|
1994-06-08 15:33:09 +04:00
|
|
|
|
1999-08-29 22:32:15 +04:00
|
|
|
/*
|
|
|
|
* For NQNFS, let the server daemon free the nfsmount structure.
|
|
|
|
*/
|
1994-06-08 15:33:09 +04:00
|
|
|
if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
|
|
|
|
free((caddr_t)nmp, M_NFSMNT);
|
1993-03-21 12:45:37 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return root of a filesystem
|
|
|
|
*/
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
2003-06-29 22:43:21 +04:00
|
|
|
nfs_root(mp, vpp)
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mount *mp;
|
|
|
|
struct vnode **vpp;
|
|
|
|
{
|
2000-03-30 16:51:13 +04:00
|
|
|
struct vnode *vp;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct nfsmount *nmp;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
nmp = VFSTONFS(mp);
|
2001-02-12 23:02:30 +03:00
|
|
|
vp = nmp->nm_vnode;
|
2003-06-29 22:43:21 +04:00
|
|
|
error = vget(vp, LK_EXCLUSIVE | LK_RETRY);
|
2001-02-12 23:02:30 +03:00
|
|
|
if (error != 0)
|
|
|
|
return error;
|
1996-05-24 02:47:27 +04:00
|
|
|
if (vp->v_type == VNON)
|
|
|
|
vp->v_type = VDIR;
|
1993-03-21 12:45:37 +03:00
|
|
|
vp->v_flag = VROOT;
|
|
|
|
*vpp = vp;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
extern int syncprt;
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Flush out the buffer cache
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_sync(mp, waitfor, cred, p)
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mount *mp;
|
|
|
|
int waitfor;
|
1994-06-08 15:33:09 +04:00
|
|
|
struct ucred *cred;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2000-03-30 16:51:13 +04:00
|
|
|
struct vnode *vp;
|
1994-06-08 15:33:09 +04:00
|
|
|
int error, allerror = 0;
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* Force stale buffer cache information to be flushed.
|
|
|
|
*/
|
1994-06-08 15:33:09 +04:00
|
|
|
loop:
|
2003-04-02 19:14:19 +04:00
|
|
|
LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
|
1994-06-08 15:33:09 +04:00
|
|
|
/*
|
|
|
|
* If the vnode that we are about to sync is no longer
|
|
|
|
* associated with this mount point, start over.
|
|
|
|
*/
|
|
|
|
if (vp->v_mount != mp)
|
|
|
|
goto loop;
|
2001-10-08 04:22:13 +04:00
|
|
|
if (waitfor == MNT_LAZY || VOP_ISLOCKED(vp) ||
|
2000-12-10 22:36:31 +03:00
|
|
|
(LIST_EMPTY(&vp->v_dirtyblkhd) &&
|
a whole bunch of changes to improve performance and robustness under load:
- remove special treatment of pager_map mappings in pmaps. this is
required now, since I've removed the globals that expose the address range.
pager_map now uses pmap_kenter_pa() instead of pmap_enter(), so there's
no longer any need to special-case it.
- eliminate struct uvm_vnode by moving its fields into struct vnode.
- rewrite the pageout path. the pager is now responsible for handling the
high-level requests instead of only getting control after a bunch of work
has already been done on its behalf. this will allow us to UBCify LFS,
which needs tighter control over its pages than other filesystems do.
writing a page to disk no longer requires making it read-only, which
allows us to write wired pages without causing all kinds of havoc.
- use a new PG_PAGEOUT flag to indicate that a page should be freed
on behalf of the pagedaemon when it's unlocked. this flag is very similar
to PG_RELEASED, but unlike PG_RELEASED, PG_PAGEOUT can be cleared if the
pageout fails due to eg. an indirect-block buffer being locked.
this allows us to remove the "version" field from struct vm_page,
and together with shrinking "loan_count" from 32 bits to 16,
struct vm_page is now 4 bytes smaller.
- no longer use PG_RELEASED for swap-backed pages. if the page is busy
because it's being paged out, we can't release the swap slot to be
reallocated until that write is complete, but unlike with vnodes we
don't keep a count of in-progress writes so there's no good way to
know when the write is done. instead, when we need to free a busy
swap-backed page, just sleep until we can get it busy ourselves.
- implement a fast-path for extending writes which allows us to avoid
zeroing new pages. this substantially reduces cpu usage.
- encapsulate the data used by the genfs code in a struct genfs_node,
which must be the first element of the filesystem-specific vnode data
for filesystems which use genfs_{get,put}pages().
- eliminate many of the UVM pagerops, since they aren't needed anymore
now that the pager "put" operation is a higher-level operation.
- enhance the genfs code to allow NFS to use the genfs_{get,put}pages
instead of a modified copy.
- clean up struct vnode by removing all the fields that used to be used by
the vfs_cluster.c code (which we don't use anymore with UBC).
- remove kmem_object and mb_object since they were useless.
instead of allocating pages to these objects, we now just allocate
pages with no object. such pages are mapped in the kernel until they
are freed, so we can use the mapping to find the page to free it.
this allows us to remove splvm() protection in several places.
The sum of all these changes improves write throughput on my
decstation 5000/200 to within 1% of the rate of NetBSD 1.5
and reduces the elapsed time for "make release" of a NetBSD 1.5
source tree on my 128MB pc to 10% less than a 1.5 kernel took.
2001-09-16 00:36:31 +04:00
|
|
|
vp->v_uobj.uo_npages == 0))
|
1994-06-08 15:33:09 +04:00
|
|
|
continue;
|
2003-06-29 22:43:21 +04:00
|
|
|
if (vget(vp, LK_EXCLUSIVE))
|
1994-06-08 15:33:09 +04:00
|
|
|
goto loop;
|
1998-06-05 23:53:00 +04:00
|
|
|
error = VOP_FSYNC(vp, cred,
|
2003-06-30 02:28:00 +04:00
|
|
|
waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p);
|
1996-02-18 14:53:36 +03:00
|
|
|
if (error)
|
1994-06-08 15:33:09 +04:00
|
|
|
allerror = error;
|
|
|
|
vput(vp);
|
|
|
|
}
|
|
|
|
return (allerror);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1994-06-08 15:33:09 +04:00
|
|
|
* NFS flat namespace lookup.
|
|
|
|
* Currently unsupported.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
2003-06-29 22:43:21 +04:00
|
|
|
nfs_vget(mp, ino, vpp)
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mount *mp;
|
1994-06-08 15:33:09 +04:00
|
|
|
ino_t ino;
|
|
|
|
struct vnode **vpp;
|
|
|
|
{
|
|
|
|
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
1996-02-18 14:53:36 +03:00
|
|
|
/*
|
|
|
|
* Do that sysctl thang...
|
|
|
|
*/
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
static int
|
|
|
|
sysctl_vfs_nfs_iothreads(SYSCTLFN_ARGS)
|
1996-02-18 14:53:36 +03:00
|
|
|
{
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
int error;
|
1996-02-18 14:53:36 +03:00
|
|
|
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
nfs_getset_niothreads(0);
|
|
|
|
error = sysctl_lookup(SYSCTLFN_CALL(rnode));
|
|
|
|
if (error || newp == NULL)
|
|
|
|
return (error);
|
|
|
|
nfs_getset_niothreads(1);
|
1996-02-18 14:53:36 +03:00
|
|
|
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
return (0);
|
|
|
|
}
|
2000-04-16 01:14:48 +04:00
|
|
|
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
SYSCTL_SETUP(sysctl_vfs_nfs_setup, "sysctl vfs.nfs subtree setup")
|
|
|
|
{
|
2000-04-16 01:14:48 +04:00
|
|
|
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT,
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
CTLTYPE_NODE, "vfs", NULL,
|
|
|
|
NULL, 0, NULL, 0,
|
|
|
|
CTL_VFS, CTL_EOL);
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT,
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
CTLTYPE_NODE, "nfs", NULL,
|
|
|
|
NULL, 0, NULL, 0,
|
|
|
|
CTL_VFS, 2, CTL_EOL);
|
|
|
|
/*
|
|
|
|
* XXX the "2" above could be dynamic, thereby eliminating one
|
|
|
|
* more instance of the "number to vfs" mapping problem, but
|
|
|
|
* "2" is the order as taken from sys/mount.h
|
|
|
|
*/
|
2000-04-16 01:14:48 +04:00
|
|
|
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
CTLTYPE_STRUCT, "nfsstats", NULL,
|
|
|
|
NULL, 0, &nfsstats, sizeof(nfsstats),
|
|
|
|
CTL_VFS, 2, NFS_NFSSTATS, CTL_EOL);
|
2004-03-24 18:34:46 +03:00
|
|
|
sysctl_createv(clog, 0, NULL, NULL,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
|
Dynamic sysctl.
Gone are the old kern_sysctl(), cpu_sysctl(), hw_sysctl(),
vfs_sysctl(), etc, routines, along with sysctl_int() et al. Now all
nodes are registered with the tree, and nodes can be added (or
removed) easily, and I/O to and from the tree is handled generically.
Since the nodes are registered with the tree, the mapping from name to
number (and back again) can now be discovered, instead of having to be
hard coded. Adding new nodes to the tree is likewise much simpler --
the new infrastructure handles almost all the work for simple types,
and just about anything else can be done with a small helper function.
All existing nodes are where they were before (numerically speaking),
so all existing consumers of sysctl information should notice no
difference.
PS - I'm sorry, but there's a distinct lack of documentation at the
moment. I'm working on sysctl(3/8/9) right now, and I promise to
watch out for buses.
2003-12-04 22:38:21 +03:00
|
|
|
CTLTYPE_INT, "iothreads", NULL,
|
|
|
|
sysctl_vfs_nfs_iothreads, 0, &nfs_niothreads, 0,
|
|
|
|
CTL_VFS, 2, NFS_IOTHREADS, CTL_EOL);
|
1996-02-18 14:53:36 +03:00
|
|
|
}
|
|
|
|
|
1994-06-08 15:33:09 +04:00
|
|
|
/*
|
|
|
|
* At this point, this should never happen
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2003-06-29 22:43:21 +04:00
|
|
|
nfs_fhtovp(mp, fhp, vpp)
|
2000-03-30 16:51:13 +04:00
|
|
|
struct mount *mp;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct fid *fhp;
|
|
|
|
struct vnode **vpp;
|
1999-02-27 02:44:43 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
|
|
|
nfs_checkexp(mp, nam, exflagsp, credanonp)
|
2000-03-30 16:51:13 +04:00
|
|
|
struct mount *mp;
|
1999-02-27 02:44:43 +03:00
|
|
|
struct mbuf *nam;
|
1994-06-08 15:33:09 +04:00
|
|
|
int *exflagsp;
|
|
|
|
struct ucred **credanonp;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Vnode pointer to File handle, should never happen either
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
1993-03-21 12:45:37 +03:00
|
|
|
nfs_vptofh(vp, fhp)
|
|
|
|
struct vnode *vp;
|
|
|
|
struct fid *fhp;
|
|
|
|
{
|
|
|
|
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Vfs start routine, a no-op.
|
|
|
|
*/
|
|
|
|
/* ARGSUSED */
|
1994-06-08 15:33:09 +04:00
|
|
|
int
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_start(mp, flags, p)
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mount *mp;
|
|
|
|
int flags;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do operations associated with quotas, not supported
|
|
|
|
*/
|
1994-06-08 15:33:09 +04:00
|
|
|
/* ARGSUSED */
|
|
|
|
int
|
2003-06-30 02:28:00 +04:00
|
|
|
nfs_quotactl(mp, cmd, uid, arg, p)
|
1993-03-21 12:45:37 +03:00
|
|
|
struct mount *mp;
|
|
|
|
int cmd;
|
|
|
|
uid_t uid;
|
2004-04-27 21:37:30 +04:00
|
|
|
void *arg;
|
2003-06-30 02:28:00 +04:00
|
|
|
struct proc *p;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-06-08 15:33:09 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|