summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>1997-05-19 14:36:56 +0000
committerdfr <dfr@FreeBSD.org>1997-05-19 14:36:56 +0000
commitd7e320b30e346cf2c6e56f2137bd257b8f8278e7 (patch)
treeafc51a58d727816c7b373ca2288b232ae4d5dd97 /sys/nfsclient
parent9d3c1b4d788c8e5f07a10319b51b2125f3731f85 (diff)
downloadFreeBSD-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.h4
-rw-r--r--sys/nfsclient/nfs_bio.c85
-rw-r--r--sys/nfsclient/nfs_vnops.c9
-rw-r--r--sys/nfsclient/nfsargs.h4
-rw-r--r--sys/nfsclient/nfsnode.h3
-rw-r--r--sys/nfsclient/nfsstats.h4
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 *));
OpenPOWER on IntegriCloud