summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/vfs_bio.c152
-rw-r--r--sys/nfs/nfs.h4
-rw-r--r--sys/nfs/nfs_bio.c85
-rw-r--r--sys/nfs/nfs_vnops.c9
-rw-r--r--sys/nfs/nfsnode.h3
-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
-rw-r--r--sys/nfsserver/nfs.h4
-rw-r--r--sys/nfsserver/nfsrvstats.h4
-rw-r--r--sys/vm/vm_fault.c4
-rw-r--r--sys/vm/vnode_pager.c7
15 files changed, 302 insertions, 79 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index d5f6a9d..0023dca 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -18,7 +18,7 @@
* 5. Modifications may be freely made to this file if the above conditions
* are met.
*
- * $Id: vfs_bio.c,v 1.114 1997/04/13 03:33:25 dyson Exp $
+ * $Id: vfs_bio.c,v 1.115 1997/05/10 09:09:42 joerg Exp $
*/
/*
@@ -77,6 +77,10 @@ static void vm_hold_free_pages(struct buf * bp, vm_offset_t from,
vm_offset_t to);
static void vm_hold_load_pages(struct buf * bp, vm_offset_t from,
vm_offset_t to);
+static void vfs_buf_set_valid(struct buf *bp, vm_ooffset_t foff,
+ vm_offset_t off, vm_offset_t size,
+ vm_page_t m);
+static void vfs_page_set_valid(struct buf *bp, vm_offset_t off, vm_page_t m);
static void vfs_clean_pages(struct buf * bp);
static void vfs_setdirty(struct buf *bp);
static void vfs_vmio_release(struct buf *bp);
@@ -501,8 +505,19 @@ brelse(struct buf * bp)
* constituted, so the B_INVAL flag is used to *invalidate* the buffer,
* but the VM object is kept around. The B_NOCACHE flag is used to
* invalidate the pages in the VM object.
+ *
+ * If the buffer is a partially filled NFS buffer, keep it
+ * since invalidating it now will lose informatio. The valid
+ * flags in the vm_pages have only DEV_BSIZE resolution but
+ * the b_validoff, b_validend fields have byte resolution.
+ * This can avoid unnecessary re-reads of the buffer.
*/
- if (bp->b_flags & B_VMIO) {
+ if ((bp->b_flags & B_VMIO)
+ && (bp->b_vp->v_tag != VT_NFS
+ || (bp->b_flags & (B_NOCACHE | B_INVAL | B_ERROR))
+ || bp->b_validend == 0
+ || (bp->b_validoff == 0
+ && bp->b_validend == bp->b_bufsize))) {
vm_ooffset_t foff;
vm_object_t obj;
int i, resid;
@@ -1418,6 +1433,7 @@ allocbuf(struct buf * bp, int size)
curbpnpages = bp->b_npages;
doretry:
bp->b_flags |= B_CACHE;
+ bp->b_validoff = bp->b_validend = 0;
for (toff = 0; toff < newbsize; toff += tinc) {
int bytesinpage;
@@ -1433,12 +1449,8 @@ allocbuf(struct buf * bp, int size)
bytesinpage = tinc;
if (tinc > (newbsize - toff))
bytesinpage = newbsize - toff;
- if ((bp->b_flags & B_CACHE) &&
- !vm_page_is_valid(m,
- (vm_offset_t) ((toff + off) & PAGE_MASK),
- bytesinpage)) {
- bp->b_flags &= ~B_CACHE;
- }
+ if (bp->b_flags & B_CACHE)
+ vfs_buf_set_valid(bp, off, toff, bytesinpage, m);
continue;
}
m = vm_page_lookup(obj, objoff);
@@ -1474,17 +1486,15 @@ allocbuf(struct buf * bp, int size)
bytesinpage = tinc;
if (tinc > (newbsize - toff))
bytesinpage = newbsize - toff;
- if ((bp->b_flags & B_CACHE) &&
- !vm_page_is_valid(m,
- (vm_offset_t) ((toff + off) & PAGE_MASK),
- bytesinpage)) {
- bp->b_flags &= ~B_CACHE;
- }
+ if (bp->b_flags & B_CACHE)
+ vfs_buf_set_valid(bp, off, toff, bytesinpage, m);
vm_page_wire(m);
}
bp->b_pages[pageindex] = m;
curbpnpages = pageindex + 1;
}
+ if (vp->v_tag == VT_NFS && bp->b_validend == 0)
+ bp->b_flags &= ~B_CACHE;
bp->b_data = (caddr_t) trunc_page(bp->b_data);
bp->b_npages = curbpnpages;
pmap_qenter((vm_offset_t) bp->b_data,
@@ -1562,7 +1572,7 @@ biodone(register struct buf * bp)
}
if (bp->b_flags & B_VMIO) {
int i, resid;
- vm_ooffset_t foff;
+ vm_ooffset_t foff, bfoff;
vm_page_t m;
vm_object_t obj;
int iosize;
@@ -1572,6 +1582,7 @@ biodone(register struct buf * bp)
foff = (vm_ooffset_t) DEV_BSIZE * bp->b_lblkno;
else
foff = (vm_ooffset_t) vp->v_mount->mnt_stat.f_iosize * bp->b_lblkno;
+ bfoff = foff;
obj = vp->v_object;
if (!obj) {
panic("biodone: no object");
@@ -1613,8 +1624,7 @@ biodone(register struct buf * bp)
* here in the read case.
*/
if ((bp->b_flags & B_READ) && !bogusflag && resid > 0) {
- vm_page_set_validclean(m,
- (vm_offset_t) (foff & PAGE_MASK), resid);
+ vfs_page_set_valid(bp, foff - bfoff, m);
}
/*
@@ -1761,6 +1771,73 @@ vfs_unbusy_pages(struct buf * bp)
}
/*
+ * Set NFS' b_validoff and b_validend fields from the valid bits
+ * of a page. If the consumer is not NFS, and the page is not
+ * valid for the entire range, clear the B_CACHE flag to force
+ * the consumer to re-read the page.
+ */
+static void
+vfs_buf_set_valid(struct buf *bp,
+ vm_ooffset_t foff, vm_offset_t off, vm_offset_t size,
+ vm_page_t m)
+{
+ if (bp->b_vp->v_tag == VT_NFS) {
+ vm_offset_t svalid, evalid;
+ int validbits = m->valid;
+
+ /*
+ * This only bothers with the first valid range in the
+ * page.
+ */
+ svalid = off;
+ while (validbits && !(validbits & 1)) {
+ svalid += DEV_BSIZE;
+ validbits >>= 1;
+ }
+ evalid = svalid;
+ while (validbits & 1) {
+ evalid += DEV_BSIZE;
+ validbits >>= 1;
+ }
+ /*
+ * Make sure this range is contiguous with the range
+ * built up from previous pages. If not, then we will
+ * just use the range from the previous pages.
+ */
+ if (svalid == bp->b_validend) {
+ bp->b_validoff = min(bp->b_validoff, svalid);
+ bp->b_validend = max(bp->b_validend, evalid);
+ }
+ } else if (!vm_page_is_valid(m,
+ (vm_offset_t) ((foff + off) & PAGE_MASK),
+ size)) {
+ bp->b_flags &= ~B_CACHE;
+ }
+}
+
+/*
+ * Set the valid bits in a page, taking care of the b_validoff,
+ * b_validend fields which NFS uses to optimise small reads. Off is
+ * the offset of the page within the buf.
+ */
+static void
+vfs_page_set_valid(struct buf *bp, vm_offset_t off, vm_page_t m)
+{
+ struct vnode *vp = bp->b_vp;
+ vm_offset_t soff, eoff;
+
+ soff = off;
+ eoff = min(off + PAGE_SIZE, bp->b_bufsize);
+ if (vp->v_tag == VT_NFS) {
+ soff = max((bp->b_validoff + DEV_BSIZE - 1) & -DEV_BSIZE, soff);
+ eoff = min(bp->b_validend & -DEV_BSIZE, eoff);
+ }
+ vm_page_set_invalid(m, 0, PAGE_SIZE);
+ if (eoff > soff)
+ vm_page_set_validclean(m, soff, eoff - soff);
+}
+
+/*
* This routine is called before a device strategy routine.
* It is used to tell the VM system that paging I/O is in
* progress, and treat the pages associated with the buffer
@@ -1775,36 +1852,25 @@ vfs_busy_pages(struct buf * bp, int clear_modify)
if (bp->b_flags & B_VMIO) {
vm_object_t obj = bp->b_vp->v_object;
- vm_ooffset_t foff;
- int iocount = bp->b_bufsize;
+ vm_offset_t off;
- if (bp->b_vp->v_type == VBLK)
- foff = (vm_ooffset_t) DEV_BSIZE * bp->b_lblkno;
- else
- foff = (vm_ooffset_t) bp->b_vp->v_mount->mnt_stat.f_iosize * bp->b_lblkno;
vfs_setdirty(bp);
- for (i = 0; i < bp->b_npages; i++) {
+ for (i = 0, off = 0; i < bp->b_npages; i++, off += PAGE_SIZE) {
vm_page_t m = bp->b_pages[i];
- int resid = IDX_TO_OFF(m->pindex + 1) - foff;
- if (resid > iocount)
- resid = iocount;
if ((bp->b_flags & B_CLUSTER) == 0) {
obj->paging_in_progress++;
m->busy++;
}
vm_page_protect(m, VM_PROT_NONE);
- if (clear_modify) {
- vm_page_set_validclean(m,
- (vm_offset_t) (foff & PAGE_MASK), resid);
- } else if (bp->b_bcount >= PAGE_SIZE) {
+ if (clear_modify)
+ vfs_page_set_valid(bp, off, m);
+ else if (bp->b_bcount >= PAGE_SIZE) {
if (m->valid && (bp->b_flags & B_CACHE) == 0) {
bp->b_pages[i] = bogus_page;
pmap_qenter(trunc_page(bp->b_data), bp->b_pages, bp->b_npages);
}
}
- foff += resid;
- iocount -= resid;
}
}
}
@@ -1820,26 +1886,12 @@ vfs_clean_pages(struct buf * bp)
int i;
if (bp->b_flags & B_VMIO) {
- vm_ooffset_t foff;
- int iocount = bp->b_bufsize;
-
- if (bp->b_vp->v_type == VBLK)
- foff = (vm_ooffset_t) DEV_BSIZE * bp->b_lblkno;
- else
- foff = (vm_ooffset_t) bp->b_vp->v_mount->mnt_stat.f_iosize * bp->b_lblkno;
+ vm_offset_t off;
- for (i = 0; i < bp->b_npages; i++) {
+ for (i = 0, off = 0; i < bp->b_npages; i++, off += PAGE_SIZE) {
vm_page_t m = bp->b_pages[i];
- int resid = IDX_TO_OFF(m->pindex + 1) - foff;
- if (resid > iocount)
- resid = iocount;
- if (resid > 0) {
- vm_page_set_validclean(m,
- ((vm_offset_t) foff & PAGE_MASK), resid);
- }
- foff += resid;
- iocount -= resid;
+ vfs_page_set_valid(bp, off, m);
}
}
}
diff --git a/sys/nfs/nfs.h b/sys/nfs/nfs.h
index 406024e..2dc19c1 100644
--- a/sys/nfs/nfs.h
+++ b/sys/nfs/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/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);
diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c
index d3ec002..ff5ad94 100644
--- a/sys/nfs/nfs_vnops.c
+++ b/sys/nfs/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/nfs/nfsnode.h b/sys/nfs/nfsnode.h
index 540d803..12553ef 100644
--- a/sys/nfs/nfsnode.h
+++ b/sys/nfs/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/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 *));
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index 406024e..2dc19c1 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/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/nfsserver/nfsrvstats.h b/sys/nfsserver/nfsrvstats.h
index 406024e..2dc19c1 100644
--- a/sys/nfsserver/nfsrvstats.h
+++ b/sys/nfsserver/nfsrvstats.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/vm/vm_fault.c b/sys/vm/vm_fault.c
index c96c42a..c138ff2 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -66,7 +66,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_fault.c,v 1.67 1997/04/06 02:29:41 dyson Exp $
+ * $Id: vm_fault.c,v 1.68 1997/04/06 16:16:11 peter Exp $
*/
/*
@@ -326,7 +326,7 @@ RetryFault:;
m->flags |= PG_BUSY;
- if (m->valid &&
+ if (/*m->valid && */
((m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) &&
m->object != kernel_object && m->object != kmem_object) {
goto readrest;
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index e4d7404..d258351 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -38,7 +38,7 @@
* SUCH DAMAGE.
*
* from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91
- * $Id: vnode_pager.c,v 1.69 1997/02/22 09:48:42 peter Exp $
+ * $Id: vnode_pager.c,v 1.70 1997/03/08 04:33:47 dyson Exp $
*/
/*
@@ -692,7 +692,12 @@ vnode_pager_leaf_getpages(object, m, count, reqpage)
/*
* if ANY DEV_BSIZE blocks are valid on a large filesystem block
* then, the entire page is valid --
+ * XXX no it isn't
*/
+
+ if (m[reqpage]->valid != VM_PAGE_BITS_ALL)
+ m[reqpage]->valid = 0;
+
if (m[reqpage]->valid) {
m[reqpage]->valid = VM_PAGE_BITS_ALL;
for (i = 0; i < count; i++) {
OpenPOWER on IntegriCloud