From owner-freebsd-current Fri May 30 02:09:30 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id CAA07392 for current-outgoing; Fri, 30 May 1997 02:09:30 -0700 (PDT) Received: from nlsystems.com (nlsys.demon.co.uk [158.152.125.33]) by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id CAA07387 for ; Fri, 30 May 1997 02:09:27 -0700 (PDT) Received: from herring.nlsystems.com (herring.nlsystems.com [10.0.0.2]) by nlsystems.com (8.8.5/8.8.5) with SMTP id KAA03622; Fri, 30 May 1997 10:08:50 +0100 (BST) Date: Fri, 30 May 1997 10:08:50 +0100 (BST) From: Doug Rabson To: Bruce Evans cc: current@freebsd.org Subject: Re: disk cache challenged by small block sizes In-Reply-To: <199705292116.HAA29423@godzilla.zeta.org.au> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-current@freebsd.org X-Loop: FreeBSD.org Precedence: bulk On Fri, 30 May 1997, Bruce Evans wrote: > >This is caused by my recent changes to vfs_bio to make NFS mmap work > >properly. I didn't test on a filesystem with small block sizes. This > >patch should fix it: > > Thanks. > > This sometimes traps. It only works on my test system. I think soff needs > to be reduced (mod PAGE_SIZE)? This version fixes a bug (passing an offset instead of a size to vm_page_set_invalid) which was probably the cause of the trap, should work properly for large files (I was using the wrong offset type) and possibly has a more acceptable style(9). Index: vfs_bio.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v retrieving revision 1.116 diff -u -r1.116 vfs_bio.c --- vfs_bio.c 1997/05/19 14:36:36 1.116 +++ vfs_bio.c 1997/05/30 08:53:16 @@ -80,7 +80,8 @@ 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_page_set_valid(struct buf *bp, vm_ooffset_t off, + int pageno, 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); @@ -1572,7 +1573,7 @@ } if (bp->b_flags & B_VMIO) { int i, resid; - vm_ooffset_t foff, bfoff; + vm_ooffset_t foff; vm_page_t m; vm_object_t obj; int iosize; @@ -1582,7 +1583,6 @@ 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"); @@ -1624,7 +1624,7 @@ * here in the read case. */ if ((bp->b_flags & B_READ) && !bogusflag && resid > 0) { - vfs_page_set_valid(bp, foff - bfoff, m); + vfs_page_set_valid(bp, foff, i, m); } /* @@ -1818,23 +1818,31 @@ /* * 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. + * the offset within the file and pageno is the page index within the buf. */ static void -vfs_page_set_valid(struct buf *bp, vm_offset_t off, vm_page_t m) +vfs_page_set_valid(struct buf *bp, vm_ooffset_t off, int pageno, vm_page_t m) { struct vnode *vp = bp->b_vp; - vm_offset_t soff, eoff; + vm_ooffset_t soff, eoff; soff = off; - eoff = min(off + PAGE_SIZE, bp->b_bufsize); + eoff = off + min(PAGE_SIZE, bp->b_bufsize); + vm_page_set_invalid(m, + (vm_offset_t) (soff & PAGE_MASK), + (vm_offset_t) (eoff - soff)); 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_ooffset_t sv, ev; + off = off - pageno * PAGE_SIZE; + sv = off + ((bp->b_validoff + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1)); + ev = off + (bp->b_validend & ~(DEV_BSIZE - 1)); + soff = max(sv, soff); + eoff = min(ev, eoff); } - vm_page_set_invalid(m, 0, PAGE_SIZE); if (eoff > soff) - vm_page_set_validclean(m, soff, eoff - soff); + vm_page_set_validclean(m, + (vm_offset_t) (soff & PAGE_MASK), + (vm_offset_t) (eoff - soff)); } /* @@ -1851,11 +1859,16 @@ int i; if (bp->b_flags & B_VMIO) { - vm_object_t obj = bp->b_vp->v_object; - vm_offset_t off; + struct vnode *vp = bp->b_vp; + vm_object_t obj = vp->v_object; + vm_ooffset_t foff; + if (vp->v_type == VBLK) + foff = (vm_ooffset_t) DEV_BSIZE * bp->b_lblkno; + else + foff = (vm_ooffset_t) vp->v_mount->mnt_stat.f_iosize * bp->b_lblkno; vfs_setdirty(bp); - for (i = 0, off = 0; i < bp->b_npages; i++, off += PAGE_SIZE) { + for (i = 0; i < bp->b_npages; i++, foff += PAGE_SIZE) { vm_page_t m = bp->b_pages[i]; if ((bp->b_flags & B_CLUSTER) == 0) { @@ -1864,7 +1877,7 @@ } vm_page_protect(m, VM_PROT_NONE); if (clear_modify) - vfs_page_set_valid(bp, off, m); + vfs_page_set_valid(bp, foff, i, m); else if (bp->b_bcount >= PAGE_SIZE) { if (m->valid && (bp->b_flags & B_CACHE) == 0) { bp->b_pages[i] = bogus_page; @@ -1886,12 +1899,18 @@ int i; if (bp->b_flags & B_VMIO) { - vm_offset_t off; + struct vnode *vp = bp->b_vp; + vm_object_t obj = vp->v_object; + vm_ooffset_t foff; - for (i = 0, off = 0; i < bp->b_npages; i++, off += PAGE_SIZE) { + if (vp->v_type == VBLK) + foff = (vm_ooffset_t) DEV_BSIZE * bp->b_lblkno; + else + foff = (vm_ooffset_t) vp->v_mount->mnt_stat.f_iosize * bp->b_lblkno; + for (i = 0; i < bp->b_npages; i++, foff += PAGE_SIZE) { vm_page_t m = bp->b_pages[i]; - vfs_page_set_valid(bp, off, m); + vfs_page_set_valid(bp, foff, i, m); } } } -- Doug Rabson Mail: dfr@nlsystems.com Nonlinear Systems Ltd. Phone: +44 181 951 1891 Fax: +44 181 381 1039