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
This commit is contained in:
parent
4fbc8b60fe
commit
b07b491ee6
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1760,6 +1770,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
|
||||
@ -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;
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 *));
|
||||
|
@ -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>
|
||||
@ -66,16 +71,71 @@ static struct buf *nfs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size,
|
||||
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 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
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);
|
||||
|
@ -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++;
|
||||
|
@ -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 *));
|
||||
|
@ -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 *));
|
||||
|
@ -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>
|
||||
@ -66,16 +71,71 @@ static struct buf *nfs_getcacheblk __P((struct vnode *vp, daddr_t bn, int size,
|
||||
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 @@ nfs_bioread(vp, uio, ioflag, cred)
|
||||
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);
|
||||
|
@ -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++;
|
||||
|
@ -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 *));
|
||||
|
@ -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 *));
|
||||
|
@ -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 *));
|
||||
|
@ -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 *));
|
||||
|
@ -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 *));
|
||||
|
@ -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;
|
||||
|
@ -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++) {
|
||||
|
Loading…
Reference in New Issue
Block a user