summaryrefslogtreecommitdiffstats
path: root/sys/nfs/nfs_bio.c
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/nfs/nfs_bio.c
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/nfs/nfs_bio.c')
-rw-r--r--sys/nfs/nfs_bio.c85
1 files changed, 83 insertions, 2 deletions
diff --git a/sys/nfs/nfs_bio.c b/sys/nfs/nfs_bio.c
index bc550fc..2a02371 100644
--- a/sys/nfs/nfs_bio.c
+++ b/sys/nfs/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);
OpenPOWER on IntegriCloud