diff options
Diffstat (limited to 'sys/nfs/nfs_vfsops.c')
-rw-r--r-- | sys/nfs/nfs_vfsops.c | 487 |
1 files changed, 339 insertions, 148 deletions
diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c index 1f18676..54e2a71 100644 --- a/sys/nfs/nfs_vfsops.c +++ b/sys/nfs/nfs_vfsops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1989, 1993 + * Copyright (c) 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by @@ -33,7 +33,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)nfs_vfsops.c 8.3 (Berkeley) 1/4/94 + * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 */ #include <sys/param.h> @@ -48,6 +48,7 @@ #include <sys/buf.h> #include <sys/mbuf.h> #include <sys/socket.h> +#include <sys/socketvar.h> #include <sys/systm.h> #include <net/if.h> @@ -55,15 +56,20 @@ #include <netinet/in.h> #include <nfs/rpcv2.h> -#include <nfs/nfsv2.h> +#include <nfs/nfsproto.h> #include <nfs/nfsnode.h> -#include <nfs/nfsmount.h> #include <nfs/nfs.h> +#include <nfs/nfsmount.h> #include <nfs/xdr_subs.h> #include <nfs/nfsm_subs.h> #include <nfs/nfsdiskless.h> #include <nfs/nqnfs.h> +struct nfsstats nfsstats; +static int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); +extern int nfs_ticks; + /* * nfs vfs operations. */ @@ -79,6 +85,7 @@ struct vfsops nfs_vfsops = { nfs_fhtovp, nfs_vptofh, nfs_init, + nfs_sysctl }; /* @@ -87,16 +94,14 @@ struct vfsops nfs_vfsops = { * to ensure that it is allocated to initialized data (.data not .bss). */ struct nfs_diskless nfs_diskless = { 0 }; +int nfs_diskless_valid = 0; -extern u_long nfs_procids[NFS_NPROCS]; -extern u_long nfs_prog, nfs_vers; void nfs_disconnect __P((struct nfsmount *)); void nfsargs_ntoh __P((struct nfs_args *)); -static struct mount *nfs_mountdiskless __P((char *, char *, int, - struct sockaddr_in *, struct nfs_args *, register struct vnode **)); - -#define TRUE 1 -#define FALSE 0 +int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *, + struct proc *)); +static int nfs_mountdiskless __P((char *, char *, int, struct sockaddr_in *, + struct nfs_args *, struct proc *, struct vnode **, struct mount **)); /* * nfs statfs call @@ -108,39 +113,55 @@ nfs_statfs(mp, sbp, p) struct proc *p; { register struct vnode *vp; - register struct nfsv2_statfs *sfp; + register struct nfs_statfs *sfp; register caddr_t cp; - register long t1; + register u_long *tl; + register long t1, t2; caddr_t bpos, dpos, cp2; - int error = 0, isnq; + struct nfsmount *nmp = VFSTONFS(mp); + int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr; struct mbuf *mreq, *mrep, *md, *mb, *mb2; - struct nfsmount *nmp; struct ucred *cred; struct nfsnode *np; + u_quad_t tquad; - nmp = VFSTONFS(mp); - isnq = (nmp->nm_flag & NFSMNT_NQNFS); - if (error = nfs_nget(mp, &nmp->nm_fh, &np)) +#ifndef nolint + sfp = (struct nfs_statfs *)0; +#endif + error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); + if (error) return (error); vp = NFSTOV(np); - nfsstats.rpccnt[NFSPROC_STATFS]++; cred = crget(); cred->cr_ngroups = 1; - nfsm_reqhead(vp, NFSPROC_STATFS, NFSX_FH); - nfsm_fhtom(vp); - nfsm_request(vp, NFSPROC_STATFS, p, cred); - nfsm_dissect(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq)); - sbp->f_type = MOUNT_NFS; - sbp->f_flags = nmp->nm_flag; - sbp->f_iosize = NFS_MAXDGRAMDATA; - sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); - sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); - sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); - sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); - if (isnq) { - sbp->f_files = fxdr_unsigned(long, sfp->sf_files); - sbp->f_ffree = fxdr_unsigned(long, sfp->sf_ffree); + if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) + (void)nfs_fsinfo(nmp, vp, cred, p); + nfsstats.rpccnt[NFSPROC_FSSTAT]++; + nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); + nfsm_fhtom(vp, v3); + nfsm_request(vp, NFSPROC_FSSTAT, p, cred); + if (v3) + nfsm_postop_attr(vp, retattr); + if (!error) + nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); + sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize); + if (v3) { + sbp->f_bsize = NFS_FABLKSIZE; + fxdr_hyper(&sfp->sf_tbytes, &tquad); + sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); + fxdr_hyper(&sfp->sf_fbytes, &tquad); + sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); + fxdr_hyper(&sfp->sf_abytes, &tquad); + sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); + sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1]) + & 0x7fffffff); + sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1]) + & 0x7fffffff); } else { + sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); + sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); + sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); + sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; } @@ -155,6 +176,66 @@ nfs_statfs(mp, sbp, p) } /* + * nfs version 3 fsinfo rpc call + */ +int +nfs_fsinfo(nmp, vp, cred, p) + register struct nfsmount *nmp; + register struct vnode *vp; + struct ucred *cred; + struct proc *p; +{ + register struct nfsv3_fsinfo *fsp; + register caddr_t cp; + register long t1, t2; + register u_long *tl, pref, max; + caddr_t bpos, dpos, cp2; + int error = 0, retattr; + struct mbuf *mreq, *mrep, *md, *mb, *mb2; + + nfsstats.rpccnt[NFSPROC_FSINFO]++; + nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); + nfsm_fhtom(vp, 1); + nfsm_request(vp, NFSPROC_FSINFO, p, cred); + nfsm_postop_attr(vp, retattr); + if (!error) { + nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); + pref = fxdr_unsigned(u_long, fsp->fs_wtpref); + if (pref < nmp->nm_wsize) + nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & + ~(NFS_FABLKSIZE - 1); + max = fxdr_unsigned(u_long, fsp->fs_wtmax); + if (max < nmp->nm_wsize) { + nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); + if (nmp->nm_wsize == 0) + nmp->nm_wsize = max; + } + pref = fxdr_unsigned(u_long, fsp->fs_rtpref); + if (pref < nmp->nm_rsize) + nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & + ~(NFS_FABLKSIZE - 1); + max = fxdr_unsigned(u_long, fsp->fs_rtmax); + if (max < nmp->nm_rsize) { + nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); + if (nmp->nm_rsize == 0) + nmp->nm_rsize = max; + } + pref = fxdr_unsigned(u_long, fsp->fs_dtpref); + if (pref < nmp->nm_readdirsize) + nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & + ~(NFS_DIRBLKSIZ - 1); + if (max < nmp->nm_readdirsize) { + nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); + if (nmp->nm_readdirsize == 0) + nmp->nm_readdirsize = max; + } + nmp->nm_flag |= NFSMNT_GOTFSINFO; + } + nfsm_reqdone; + return (error); +} + +/* * Mount a remote root fs via. nfs. This depends on the info in the * nfs_diskless structure that has been filled in properly by some primary * bootstrap. @@ -170,12 +251,14 @@ nfs_statfs(mp, sbp, p) int nfs_mountroot() { - register struct mount *mp; - register struct nfs_diskless *nd = &nfs_diskless; + struct mount *mp, *swap_mp; + struct nfs_diskless *nd = &nfs_diskless; struct socket *so; struct vnode *vp; struct proc *p = curproc; /* XXX */ int error, i; + u_long l; + char buf[128]; /* * XXX time must be non-zero when we init the interface or else @@ -184,6 +267,11 @@ nfs_mountroot() if (time.tv_sec == 0) time.tv_sec = 1; + /* + * XXX splnet, so networks will receive... + */ + splnet(); + #ifdef notyet /* Set up swap credentials. */ proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid); @@ -199,10 +287,31 @@ nfs_mountroot() * Do enough of ifconfig(8) so that the critical net interface can * talk to the server. */ - if (error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0)) - panic("nfs_mountroot: socreate: %d", error); - if (error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p)) - panic("nfs_mountroot: SIOCAIFADDR: %d", error); + error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0); + if (error) { + printf("nfs_mountroot: socreate(%04x): %d", + nd->myif.ifra_addr.sa_family, error); + return (error); + } + + /* + * We might not have been told the right interface, so we pass + * over the first ten interfaces of the same kind, until we get + * one of them configured. + */ + + for (i = strlen(nd->myif.ifra_name) - 1; + nd->myif.ifra_name[i] >= '0' && + nd->myif.ifra_name[i] <= '9'; + nd->myif.ifra_name[i] ++) { + error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p); + if(!error) + break; + } + if (error) { + printf("nfs_mountroot: SIOCAIFADDR: %d", error); + return (error); + } soclose(so); /* @@ -215,23 +324,40 @@ nfs_mountroot() sin = mask; sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); - if (error = rtrequest(RTM_ADD, (struct sockaddr *)&sin, + error = rtrequest(RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&nd->mygateway, (struct sockaddr *)&mask, - RTF_UP | RTF_GATEWAY, (struct rtentry **)0)) - panic("nfs_mountroot: RTM_ADD: %d", error); + RTF_UP | RTF_GATEWAY, (struct rtentry **)0); + if (error) { + printf("nfs_mountroot: RTM_ADD: %d", error); + return (error); + } } - /* - * If swapping to an nfs node (indicated by swdevt[0].sw_dev == NODEV): - * Create a fake mount point just for the swap vnode so that the - * swap file can be on a different server from the rootfs. - */ - if (swdevt[0].sw_dev == NODEV) { - nd->swap_args.fh = (nfsv2fh_t *)nd->swap_fh; - (void) nfs_mountdiskless(nd->swap_hostnam, "/swap", 0, - &nd->swap_saddr, &nd->swap_args, &vp); - + swap_mp = NULL; + if (nd->swap_nblks) { + /* + * Create a fake mount point just for the swap vnode so that the + * swap file can be on a different server from the rootfs. + */ + nd->swap_args.fh = nd->swap_fh; + /* + * If using nfsv3_diskless, replace NFSX_V2FH with + * nd->swap_fhsize. + */ + nd->swap_args.fhsize = NFSX_V2FH; + l = ntohl(nd->swap_saddr.sin_addr.s_addr); + sprintf(buf,"%ld.%ld.%ld.%ld:%s", + (l >> 24) & 0xff, (l >> 16) & 0xff, + (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam); + printf("NFS SWAP: %s\n",buf); + if (error = nfs_mountdiskless(buf, "/swap", 0, + &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp)) + return (error); + vfs_unbusy(swap_mp, p); + + for (i=0;swdevt[i].sw_dev != NODEV;i++) ; + /* * Since the swap file is not the root dir of a file system, * hack it to a regular file. @@ -240,25 +366,44 @@ nfs_mountroot() vp->v_flag = 0; swapdev_vp = vp; VREF(vp); - swdevt[0].sw_vp = vp; - swdevt[0].sw_nblks = ntohl(nd->swap_nblks); - } else if (bdevvp(swapdev, &swapdev_vp)) - panic("nfs_mountroot: can't setup swapdev_vp"); + swdevt[i].sw_vp = vp; + swdevt[i].sw_nblks = nd->swap_nblks*2; + + if (!swdevt[i].sw_nblks) { + swdevt[i].sw_nblks = 2048; + printf("defaulting to %d kbyte.\n", + swdevt[i].sw_nblks/2); + } else + printf("using %d kbyte.\n",swdevt[i].sw_nblks/2); + } /* * Create the rootfs mount point. */ - nd->root_args.fh = (nfsv2fh_t *)nd->root_fh; - mp = nfs_mountdiskless(nd->root_hostnam, "/", MNT_RDONLY, - &nd->root_saddr, &nd->root_args, &vp); - - if (vfs_lock(mp)) - panic("nfs_mountroot: vfs_lock"); - TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); - mp->mnt_flag |= MNT_ROOTFS; - mp->mnt_vnodecovered = NULLVP; - vfs_unlock(mp); + nd->root_args.fh = nd->root_fh; + /* + * If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize. + */ + nd->root_args.fhsize = NFSX_V2FH; + l = ntohl(nd->swap_saddr.sin_addr.s_addr); + sprintf(buf,"%ld.%ld.%ld.%ld:%s", + (l >> 24) & 0xff, (l >> 16) & 0xff, + (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam); + printf("NFS ROOT: %s\n",buf); + if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY, + &nd->root_saddr, &nd->root_args, p, &vp, &mp)) { + if (swap_mp) { + mp->mnt_vfc->vfc_refcount--; + free(swap_mp, M_MOUNT); + } + return (error); + } + + simple_lock(&mountlist_slock); + CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); + simple_unlock(&mountlist_slock); rootvp = vp; + vfs_unbusy(mp, p); /* * This is not really an nfs issue, but it is much easier to @@ -278,59 +423,39 @@ nfs_mountroot() /* * Internal version of mount system call for diskless setup. */ -static struct mount * -nfs_mountdiskless(path, which, mountflag, sin, args, vpp) +static int +nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp) char *path; char *which; int mountflag; struct sockaddr_in *sin; struct nfs_args *args; - register struct vnode **vpp; + struct proc *p; + struct vnode **vpp; + struct mount **mpp; { - register struct mount *mp; - register struct mbuf *m; - register int error; - - mp = (struct mount *)malloc((u_long)sizeof(struct mount), - M_MOUNT, M_NOWAIT); - if (mp == NULL) - panic("nfs_mountroot: %s mount malloc", which); - bzero((char *)mp, (u_long)sizeof(struct mount)); - mp->mnt_op = &nfs_vfsops; - mp->mnt_flag = mountflag; + struct mount *mp; + struct mbuf *m; + int error; - MGET(m, MT_SONAME, M_DONTWAIT); - if (m == NULL) - panic("nfs_mountroot: %s mount mbuf", which); + if (error = vfs_rootmountalloc("nfs", path, &mp)) { + printf("nfs_mountroot: NFS not configured"); + return (error); + } + mp->mnt_flag = mountflag; + MGET(m, MT_SONAME, M_WAITOK); bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len); m->m_len = sin->sin_len; - nfsargs_ntoh(args); - if (error = mountnfs(args, mp, m, which, path, vpp)) - panic("nfs_mountroot: mount %s on %s: %d", path, which, error); - - return (mp); -} - -/* - * Convert the integer fields of the nfs_args structure from net byte order - * to host byte order. Called by nfs_mountroot() above. - */ -void -nfsargs_ntoh(nfsp) - register struct nfs_args *nfsp; -{ - - NTOHL(nfsp->sotype); - NTOHL(nfsp->proto); - NTOHL(nfsp->flags); - NTOHL(nfsp->wsize); - NTOHL(nfsp->rsize); - NTOHL(nfsp->timeo); - NTOHL(nfsp->retrans); - NTOHL(nfsp->maxgrouplist); - NTOHL(nfsp->readahead); - NTOHL(nfsp->leaseterm); - NTOHL(nfsp->deadthresh); + if (error = mountnfs(args, mp, m, which, path, vpp)) { + printf("nfs_mountroot: mount %s on %s: %d", path, which, error); + mp->mnt_vfc->vfc_refcount--; + vfs_unbusy(mp, p); + free(mp, M_MOUNT); + return (error); + } + (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); + *mpp = mp; + return (0); } /* @@ -357,23 +482,29 @@ nfs_mount(mp, path, data, ndp, p) struct vnode *vp; char pth[MNAMELEN], hst[MNAMELEN]; u_int len; - nfsv2fh_t nfh; + u_char nfh[NFSX_V3FHMAX]; - if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args))) + error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); + if (error) return (error); - if (error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t))) + if (args.version != NFS_ARGSVERSION) + return (EPROGMISMATCH); + error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); + if (error) return (error); - if (error = copyinstr(path, pth, MNAMELEN-1, &len)) + error = copyinstr(path, pth, MNAMELEN-1, &len); + if (error) return (error); bzero(&pth[len], MNAMELEN - len); - if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len)) + error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); + if (error) return (error); bzero(&hst[len], MNAMELEN - len); /* sockargs() call must be after above copyin() calls */ - if (error = sockargs(&nam, (caddr_t)args.addr, - args.addrlen, MT_SONAME)) + error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME); + if (error) return (error); - args.fh = &nfh; + args.fh = nfh; error = mountnfs(&args, mp, nam, pth, hst, &vp); return (error); } @@ -391,7 +522,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp) { register struct nfsmount *nmp; struct nfsnode *np; - int error; + int error, maxio; if (mp->mnt_flag & MNT_UPDATE) { nmp = VFSTONFS(mp); @@ -402,16 +533,12 @@ mountnfs(argp, mp, nam, pth, hst, vpp) MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount), M_NFSMNT, M_WAITOK); bzero((caddr_t)nmp, sizeof (struct nfsmount)); + TAILQ_INIT(&nmp->nm_uidlruhead); mp->mnt_data = (qaddr_t)nmp; } - getnewfsid(mp, MOUNT_NFS); + vfs_getnewfsid(mp); nmp->nm_mountp = mp; nmp->nm_flag = argp->flags; - if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_MYWRITE)) == - (NFSMNT_NQNFS | NFSMNT_MYWRITE)) { - error = EPERM; - goto bad; - } if (nmp->nm_flag & NFSMNT_NQNFS) /* * We have to set mnt_maxsymlink to a non-zero value so @@ -424,15 +551,15 @@ mountnfs(argp, mp, nam, pth, hst, vpp) nmp->nm_retry = NFS_RETRANS; nmp->nm_wsize = NFS_WSIZE; nmp->nm_rsize = NFS_RSIZE; + nmp->nm_readdirsize = NFS_READDIRSIZE; nmp->nm_numgrps = NFS_MAXGRPS; nmp->nm_readahead = NFS_DEFRAHEAD; nmp->nm_leaseterm = NQ_DEFLEASE; nmp->nm_deadthresh = NQ_DEADTHRESH; - nmp->nm_tnext = (struct nfsnode *)nmp; - nmp->nm_tprev = (struct nfsnode *)nmp; + CIRCLEQ_INIT(&nmp->nm_timerhead); nmp->nm_inprog = NULLVP; - bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t)); - mp->mnt_stat.f_type = MOUNT_NFS; + nmp->nm_fhsize = argp->fhsize; + bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); nmp->nm_nam = nam; @@ -451,29 +578,48 @@ mountnfs(argp, mp, nam, pth, hst, vpp) nmp->nm_retry = NFS_MAXREXMIT; } + if (argp->flags & NFSMNT_NFSV3) { + if (argp->sotype == SOCK_DGRAM) + maxio = NFS_MAXDGRAMDATA; + else + maxio = NFS_MAXDATA; + } else + maxio = NFS_V2MAXDATA; + if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { nmp->nm_wsize = argp->wsize; /* Round down to multiple of blocksize */ - nmp->nm_wsize &= ~0x1ff; + nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize <= 0) - nmp->nm_wsize = 512; - else if (nmp->nm_wsize > NFS_MAXDATA) - nmp->nm_wsize = NFS_MAXDATA; + nmp->nm_wsize = NFS_FABLKSIZE; } + if (nmp->nm_wsize > maxio) + nmp->nm_wsize = maxio; if (nmp->nm_wsize > MAXBSIZE) nmp->nm_wsize = MAXBSIZE; if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { nmp->nm_rsize = argp->rsize; /* Round down to multiple of blocksize */ - nmp->nm_rsize &= ~0x1ff; + nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize <= 0) - nmp->nm_rsize = 512; - else if (nmp->nm_rsize > NFS_MAXDATA) - nmp->nm_rsize = NFS_MAXDATA; + nmp->nm_rsize = NFS_FABLKSIZE; } + if (nmp->nm_rsize > maxio) + nmp->nm_rsize = maxio; if (nmp->nm_rsize > MAXBSIZE) nmp->nm_rsize = MAXBSIZE; + + if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { + nmp->nm_readdirsize = argp->readdirsize; + /* Round down to multiple of blocksize */ + nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1); + if (nmp->nm_readdirsize < NFS_DIRBLKSIZ) + nmp->nm_readdirsize = NFS_DIRBLKSIZ; + } + if (nmp->nm_readdirsize > maxio) + nmp->nm_readdirsize = maxio; + if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && argp->maxgrouplist <= NFS_MAXGRPS) nmp->nm_numgrps = argp->maxgrouplist; @@ -513,7 +659,8 @@ mountnfs(argp, mp, nam, pth, hst, vpp) * this problem, because one can identify root inodes by their * number == ROOTINO (2). */ - if (error = nfs_nget(mp, &nmp->nm_fh, &np)) + error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); + if (error) goto bad; *vpp = NFSTOV(np); @@ -538,13 +685,9 @@ nfs_unmount(mp, mntflags, p) struct nfsnode *np; struct vnode *vp; int error, flags = 0; - extern int doforce; - if (mntflags & MNT_FORCE) { - if (!doforce || (mp->mnt_flag & MNT_ROOTFS)) - return (EINVAL); + if (mntflags & MNT_FORCE) flags |= FORCECLOSE; - } nmp = VFSTONFS(mp); /* * Goes something like this.. @@ -560,7 +703,8 @@ nfs_unmount(mp, mntflags, p) * the remote root. See comment in mountnfs(). The VFS unmount() * has done vput on this vnode, otherwise we would get deadlock! */ - if (error = nfs_nget(mp, &nmp->nm_fh, &np)) + error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); + if (error) return(error); vp = NFSTOV(np); if (vp->v_usecount > 2) { @@ -574,7 +718,8 @@ nfs_unmount(mp, mntflags, p) nmp->nm_flag |= NFSMNT_DISMINPROG; while (nmp->nm_inprog != NULLVP) (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); - if (error = vflush(mp, vp, flags)) { + error = vflush(mp, vp, flags); + if (error) { vput(vp); nmp->nm_flag &= ~NFSMNT_DISMINPROG; return (error); @@ -615,7 +760,8 @@ nfs_root(mp, vpp) int error; nmp = VFSTONFS(mp); - if (error = nfs_nget(mp, &nmp->nm_fh, &np)) + error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); + if (error) return (error); vp = NFSTOV(np); vp->v_type = VDIR; @@ -655,9 +801,10 @@ loop: goto loop; if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL) continue; - if (vget(vp, 1)) + if (vget(vp, LK_EXCLUSIVE, p)) goto loop; - if (error = VOP_FSYNC(vp, cred, waitfor, p)) + error = VOP_FSYNC(vp, cred, waitfor, p); + if (error) allerror = error; vput(vp); } @@ -738,3 +885,47 @@ nfs_quotactl(mp, cmd, uid, arg, p) return (EOPNOTSUPP); } + +/* + * Do that sysctl thang... + */ +static int +nfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen, struct proc *p) +{ + int rv; + + /* + * All names at this level are terminal. + */ + if(namelen > 1) + return ENOTDIR; /* overloaded */ + + switch(name[0]) { + case NFS_NFSSTATS: + if(!oldp) { + *oldlenp = sizeof nfsstats; + return 0; + } + + if(*oldlenp < sizeof nfsstats) { + *oldlenp = sizeof nfsstats; + return ENOMEM; + } + + rv = copyout(&nfsstats, oldp, sizeof nfsstats); + if(rv) return rv; + + if(newp && newlen != sizeof nfsstats) + return EINVAL; + + if(newp) { + return copyin(newp, &nfsstats, sizeof nfsstats); + } + return 0; + + default: + return EOPNOTSUPP; + } +} + |