Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 May 1997 10:08:50 +0100 (BST)
From:      Doug Rabson <dfr@nlsystems.com>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        current@freebsd.org
Subject:   Re: disk cache challenged by small block sizes
Message-ID:  <Pine.BSF.3.95q.970530100631.390D-100000@herring.nlsystems.com>
In-Reply-To: <199705292116.HAA29423@godzilla.zeta.org.au>

next in thread | previous in thread | raw e-mail | index | archive | help
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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.95q.970530100631.390D-100000>