diff options
author | dfr <dfr@FreeBSD.org> | 1997-05-19 14:36:56 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1997-05-19 14:36:56 +0000 |
commit | d7e320b30e346cf2c6e56f2137bd257b8f8278e7 (patch) | |
tree | afc51a58d727816c7b373ca2288b232ae4d5dd97 /sys/nfsclient | |
parent | 9d3c1b4d788c8e5f07a10319b51b2125f3731f85 (diff) | |
download | FreeBSD-src-d7e320b30e346cf2c6e56f2137bd257b8f8278e7.zip FreeBSD-src-d7e320b30e346cf2c6e56f2137bd257b8f8278e7.tar.gz |
Fix a few bugs with NFS and mmap caused by NFS' use of b_validoff
and b_validend. The changes to vfs_bio.c are a bit ugly but hopefully
can be tidied up later by a slight redesign.
PR: kern/2573, kern/2754, kern/3046 (possibly)
Reviewed by: dyson
Diffstat (limited to 'sys/nfsclient')
-rw-r--r-- | sys/nfsclient/nfs.h | 4 | ||||
-rw-r--r-- | sys/nfsclient/nfs_bio.c | 85 | ||||
-rw-r--r-- | sys/nfsclient/nfs_vnops.c | 9 | ||||
-rw-r--r-- | sys/nfsclient/nfsargs.h | 4 | ||||
-rw-r--r-- | sys/nfsclient/nfsnode.h | 3 | ||||
-rw-r--r-- | sys/nfsclient/nfsstats.h | 4 |
6 files changed, 96 insertions, 13 deletions
diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h index 406024e..2dc19c1 100644 --- a/sys/nfsclient/nfs.h +++ b/sys/nfsclient/nfs.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs.h 8.4 (Berkeley) 5/1/95 - * $Id: nfs.h,v 1.25 1997/05/10 16:12:02 dfr Exp $ + * $Id: nfs.h,v 1.26 1997/05/13 17:25:44 dfr Exp $ */ #ifndef _NFS_NFS_H_ @@ -583,7 +583,7 @@ int nfs_connect __P((struct nfsmount *,struct nfsreq *)); void nfs_disconnect __P((struct nfsmount *)); int nfs_getattrcache __P((struct vnode *,struct vattr *)); int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long)); -int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *)); +int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *, int getpages)); int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *)); void nfsrv_init __P((int)); void nfs_clearcommit __P((struct mount *)); diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index bc550fc..2a02371 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_bio.c 8.9 (Berkeley) 3/30/95 - * $Id: nfs_bio.c,v 1.36 1997/04/19 14:28:36 dfr Exp $ + * $Id: nfs_bio.c,v 1.37 1997/05/13 19:41:32 dfr Exp $ */ @@ -52,6 +52,11 @@ #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/vm_extern.h> +#include <vm/vm_prot.h> +#include <vm/vm_page.h> +#include <vm/vm_object.h> +#include <vm/vm_pager.h> +#include <vm/vnode_pager.h> #include <nfs/rpcv2.h> #include <nfs/nfsproto.h> @@ -67,15 +72,70 @@ extern int nfs_numasync; extern struct nfsstats nfsstats; /* + * Vnode op for VM getpages. + */ +int +nfs_getpages(ap) + struct vop_getpages_args *ap; +{ + int i, bsize; + vm_object_t obj; + int pcount; + struct uio auio; + struct iovec aiov; + int error; + vm_page_t m; + + if (!(ap->a_vp->v_flag & VVMIO)) { + printf("nfs_getpages: called with non-VMIO vnode??\n"); + return EOPNOTSUPP; + } + + pcount = round_page(ap->a_count) / PAGE_SIZE; + + obj = ap->a_m[ap->a_reqpage]->object; + bsize = ap->a_vp->v_mount->mnt_stat.f_iosize; + + for (i = 0; i < pcount; i++) { + if (i != ap->a_reqpage) { + vnode_pager_freepage(ap->a_m[i]); + } + } + m = ap->a_m[ap->a_reqpage]; + + m->busy++; + m->flags &= ~PG_BUSY; + + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = 0; + aiov.iov_len = MAXBSIZE; + auio.uio_resid = MAXBSIZE; + auio.uio_offset = IDX_TO_OFF(m->pindex); + auio.uio_segflg = UIO_NOCOPY; + auio.uio_rw = UIO_READ; + auio.uio_procp = curproc; + error = nfs_bioread(ap->a_vp, &auio, IO_NODELOCKED, curproc->p_ucred, 1); + + m->flags |= PG_BUSY; + m->busy--; + + if (error && (auio.uio_resid == MAXBSIZE)) + return VM_PAGER_ERROR; + return 0; +} + +/* * Vnode op for read using bio * Any similarity to readip() is purely coincidental */ int -nfs_bioread(vp, uio, ioflag, cred) +nfs_bioread(vp, uio, ioflag, cred, getpages) register struct vnode *vp; register struct uio *uio; int ioflag; struct ucred *cred; + int getpages; { register struct nfsnode *np = VTONFS(vp); register int biosize, diff, i; @@ -235,6 +295,27 @@ again: bp = nfs_getcacheblk(vp, lbn, bufsize, p); if (!bp) return (EINTR); + /* + * If we are being called from nfs_getpages, we must + * make sure the buffer is a vmio buffer. The vp will + * already be setup for vmio but there may be some old + * non-vmio buffers attached to it. + */ + if (getpages && !(bp->b_flags & B_VMIO)) { +#ifdef DIAGNOSTIC + printf("nfs_bioread: non vmio buf found, discarding\n"); +#endif + bp->b_flags |= B_NOCACHE; + bp->b_flags |= B_INVAFTERWRITE; + if (bp->b_dirtyend > 0) { + if ((bp->b_flags & B_DELWRI) == 0) + panic("nfsbioread"); + if (VOP_BWRITE(bp) == EINTR) + return (EINTR); + } else + brelse(bp); + goto again; + } if ((bp->b_flags & B_CACHE) == 0) { bp->b_flags |= B_READ; bp->b_flags &= ~(B_DONE | B_ERROR | B_INVAL); diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c index d3ec002..ff5ad94 100644 --- a/sys/nfsclient/nfs_vnops.c +++ b/sys/nfsclient/nfs_vnops.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 - * $Id: nfs_vnops.c,v 1.48 1997/05/09 13:18:42 dfr Exp $ + * $Id: nfs_vnops.c,v 1.49 1997/05/17 18:32:52 phk Exp $ */ @@ -184,6 +184,7 @@ static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { { &vop_truncate_desc, (vop_t *)nfs_truncate }, /* truncate */ { &vop_update_desc, (vop_t *)nfs_update }, /* update */ { &vop_bwrite_desc, (vop_t *)nfs_bwrite }, /* bwrite */ + { &vop_getpages_desc, (vop_t *)nfs_getpages }, /* getpages */ { NULL, NULL } }; static struct vnodeopv_desc nfsv2_vnodeop_opv_desc = @@ -1035,7 +1036,7 @@ nfs_read(ap) if (vp->v_type != VREG) return (EPERM); - return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); + return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0)); } /* @@ -1053,7 +1054,7 @@ nfs_readlink(ap) if (vp->v_type != VLNK) return (EPERM); - return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred)); + return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0)); } /* @@ -2055,7 +2056,7 @@ nfs_readdir(ap) * Call nfs_bioread() to do the real work. */ tresid = uio->uio_resid; - error = nfs_bioread(vp, uio, 0, ap->a_cred); + error = nfs_bioread(vp, uio, 0, ap->a_cred, 0); if (!error && uio->uio_resid == tresid) nfsstats.direofcache_misses++; diff --git a/sys/nfsclient/nfsargs.h b/sys/nfsclient/nfsargs.h index 406024e..2dc19c1 100644 --- a/sys/nfsclient/nfsargs.h +++ b/sys/nfsclient/nfsargs.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs.h 8.4 (Berkeley) 5/1/95 - * $Id: nfs.h,v 1.25 1997/05/10 16:12:02 dfr Exp $ + * $Id: nfs.h,v 1.26 1997/05/13 17:25:44 dfr Exp $ */ #ifndef _NFS_NFS_H_ @@ -583,7 +583,7 @@ int nfs_connect __P((struct nfsmount *,struct nfsreq *)); void nfs_disconnect __P((struct nfsmount *)); int nfs_getattrcache __P((struct vnode *,struct vattr *)); int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long)); -int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *)); +int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *, int getpages)); int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *)); void nfsrv_init __P((int)); void nfs_clearcommit __P((struct mount *)); diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h index 540d803..12553ef 100644 --- a/sys/nfsclient/nfsnode.h +++ b/sys/nfsclient/nfsnode.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfsnode.h 8.9 (Berkeley) 5/14/95 - * $Id: nfsnode.h,v 1.19 1997/02/22 09:42:49 peter Exp $ + * $Id: nfsnode.h,v 1.20 1997/04/04 17:49:35 dfr Exp $ */ @@ -161,6 +161,7 @@ extern vop_t **spec_nfsv2nodeop_p; /* * Prototypes for NFS vnode operations */ +int nfs_getpages __P((struct vop_getpages_args *)); int nfs_write __P((struct vop_write_args *)); #define nfs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop) int nqnfs_vop_lease_check __P((struct vop_lease_args *)); diff --git a/sys/nfsclient/nfsstats.h b/sys/nfsclient/nfsstats.h index 406024e..2dc19c1 100644 --- a/sys/nfsclient/nfsstats.h +++ b/sys/nfsclient/nfsstats.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs.h 8.4 (Berkeley) 5/1/95 - * $Id: nfs.h,v 1.25 1997/05/10 16:12:02 dfr Exp $ + * $Id: nfs.h,v 1.26 1997/05/13 17:25:44 dfr Exp $ */ #ifndef _NFS_NFS_H_ @@ -583,7 +583,7 @@ int nfs_connect __P((struct nfsmount *,struct nfsreq *)); void nfs_disconnect __P((struct nfsmount *)); int nfs_getattrcache __P((struct vnode *,struct vattr *)); int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long)); -int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *)); +int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *, int getpages)); int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *)); void nfsrv_init __P((int)); void nfs_clearcommit __P((struct mount *)); |