Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 May 1997 16:52:46 +0100 (BST)
From:      Doug Rabson <dfr@nlsystems.com>
To:        Christoph Kukulies <kuku@gilberto.physik.rwth-aachen.de>
Cc:        dyson@freebsd.org, current@freebsd.org
Subject:   Re: can anyone confirm my NFS/VM problem?
Message-ID:  <Pine.BSF.3.95q.970517164819.5082B-100000@herring.nlsystems.com>
In-Reply-To: <199705161047.MAA00774@gil.physik.rwth-aachen.de>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, 16 May 1997, Christoph Kukulies wrote:

> 
> I have created a test case to repeat that weird NFS/VM problem I
> have here with a physics production program - the exposed bug is
> really a showstopper for our production and I'm not sure if it is
> not also in 2.2.1R.
> (Don't know if Doug is already going to deal with this group
> of NFS/VM/MMAP problems). Anyway, to assure it is really a
> repeatable problem independent of some local peculiarity here
> at my site, I'm seeking for someone with the following
> configuration:

Well I think I have a fix.  It was bloody painful too.  There were some
extremely ugly problems associated with NFS' use of b_validoff and
b_validend.  I attempted to fix them but it still feels pretty fragile
although it does pass Ghristoph's test case.

John, could you have a look at these changes and tell me whether they make
sense?

Index: kern/vfs_bio.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v
retrieving revision 1.115
diff -u -r1.115 vfs_bio.c
--- vfs_bio.c	1997/05/10 09:09:42	1.115
+++ vfs_bio.c	1997/05/17 15:37:52
@@ -1215,6 +1215,10 @@
 		splx(s);
 
 		allocbuf(bp, size);
+		if ((bp->b_flags & (B_VMIO|B_CACHE)) == (B_VMIO|B_CACHE)) {
+			bp->b_validoff = 0;
+			bp->b_validend = bp->b_bufsize;
+		}
 #ifdef	PC98
 		/*
 		 * 1024byte/sector support
@@ -1562,7 +1566,7 @@
 	}
 	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 +1576,7 @@
 			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 +1618,18 @@
 			 * 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);
+				vm_ooffset_t soff, eoff;
+				if (vp->v_tag == VT_NFS) {
+					soff = max((bfoff + bp->b_validoff + DEV_BSIZE - 1) & -DEV_BSIZE,
+						   foff);
+					eoff = min((bfoff + bp->b_validend) & -DEV_BSIZE,
+						   foff + resid);
+					vm_page_set_invalid(m, 0, PAGE_SIZE);
+					if (eoff > soff)
+						vm_page_set_validclean(m, soff, eoff - soff);
+				} else
+					vm_page_set_validclean(m,
+						(vm_offset_t) (foff & PAGE_MASK), resid);
 			}
 
 			/*
@@ -1774,14 +1789,16 @@
 	int i;
 
 	if (bp->b_flags & B_VMIO) {
-		vm_object_t obj = bp->b_vp->v_object;
-		vm_ooffset_t foff;
+		struct vnode *vp = bp->b_vp;
+		vm_object_t obj = vp->v_object;
+		vm_ooffset_t foff, bfoff;
 		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;
+			foff = (vm_ooffset_t) vp->v_mount->mnt_stat.f_iosize * bp->b_lblkno;
+		bfoff = foff;
 		vfs_setdirty(bp);
 		for (i = 0; i < bp->b_npages; i++) {
 			vm_page_t m = bp->b_pages[i];
@@ -1795,8 +1812,18 @@
 			}
 			vm_page_protect(m, VM_PROT_NONE);
 			if (clear_modify) {
-				vm_page_set_validclean(m,
-					(vm_offset_t) (foff & PAGE_MASK), resid);
+				vm_ooffset_t soff, eoff;
+				if (vp->v_tag == VT_NFS) {
+					soff = max((bfoff + bp->b_validoff + DEV_BSIZE - 1) & -DEV_BSIZE,
+						   foff);
+					eoff = min((bfoff + bp->b_validend) & -DEV_BSIZE,
+						   foff + resid);
+					vm_page_set_invalid(m, 0, PAGE_SIZE);
+					if (eoff > soff)
+						vm_page_set_validclean(m, soff, eoff - soff);
+				} else
+					vm_page_set_validclean(m,
+						(vm_offset_t) (foff & PAGE_MASK), resid);
 			} else if (bp->b_bcount >= PAGE_SIZE) {
 				if (m->valid && (bp->b_flags & B_CACHE) == 0) {
 					bp->b_pages[i] = bogus_page;
@@ -1820,13 +1847,15 @@
 	int i;
 
 	if (bp->b_flags & B_VMIO) {
-		vm_ooffset_t foff;
+		vm_ooffset_t foff, bfoff;
+		struct vnode *vp = bp->b_vp;
 		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;
+			foff = (vm_ooffset_t) vp->v_mount->mnt_stat.f_iosize * bp->b_lblkno;
+		bfoff = foff;
 
 		for (i = 0; i < bp->b_npages; i++) {
 			vm_page_t m = bp->b_pages[i];
@@ -1835,8 +1864,18 @@
 			if (resid > iocount)
 				resid = iocount;
 			if (resid > 0) {
-				vm_page_set_validclean(m,
-					((vm_offset_t) foff & PAGE_MASK), resid);
+				vm_ooffset_t soff, eoff;
+				if (vp->v_tag == VT_NFS) {
+					soff = max((bfoff + bp->b_validoff + DEV_BSIZE - 1) & -DEV_BSIZE,
+						   foff);
+					eoff = min((bfoff + bp->b_validend) & -DEV_BSIZE,
+						   foff + resid);
+					vm_page_set_invalid(m, 0, PAGE_SIZE);
+					if (eoff > soff)
+						vm_page_set_validclean(m, soff, eoff - soff);
+				} else
+					vm_page_set_validclean(m,
+						(vm_offset_t) (foff & PAGE_MASK), resid);
 			}
 			foff += resid;
 			iocount -= resid;
Index: vm/vm_fault.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/vm_fault.c,v
retrieving revision 1.68
diff -u -r1.68 vm_fault.c
--- vm_fault.c	1997/04/06 16:16:11	1.68
+++ vm_fault.c	1997/05/17 15:12:15
@@ -326,7 +326,7 @@
 
 			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;
Index: vm/vnode_pager.c
===================================================================
RCS file: /home/ncvs/src/sys/vm/vnode_pager.c,v
retrieving revision 1.70
diff -u -r1.70 vnode_pager.c
--- vnode_pager.c	1997/03/08 04:33:47	1.70
+++ vnode_pager.c	1997/05/17 15:28:25
@@ -692,7 +692,12 @@
 	/*
 	 * 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++) {


--
Doug Rabson				Mail:  dfr@nlsystems.com
Nonlinear Systems Ltd.			Phone: +44 181 951 1891




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