Subject: kern/17107
To: NetBSD GNATS <gnats-bugs@netbsd.org>
From: Artem Belevich <art@riverstonenet.com>
List: tech-kern
Date: 10/07/2002 14:26:29
I've got somewhat ugly workaround that seems to be working on i386.
It performs some paranoid checks to catch cases with bogus mount point
pointer and refuses to touch it if something seems wrong.

With the patch kernel seems to be a bit more stable. 

Oct  6 08:08:55 tyr /netbsd: nfs_reclaim: vnode 0xdf4d89bc has bogus MP 0xc1841c00
Oct  6 08:08:55 tyr /netbsd: nfs_reclaim: vnode 0xdf7426d4 has bogus MP 0xc1828400
Oct  6 08:13:24 tyr /netbsd: Data modified on freelist: word 5 of object 0xc1828400 size 512 previous type NFS mount (0x0 != 0xdeadbeef)
Oct  6 08:13:26 tyr /netbsd: Data modified on freelist: word 5 of object 0xc1841c00 size 512 previous type mount (0x0 != 0xdeadbeef)

--Artem


Index: nfs/nfs_node.c
===================================================================
RCS file: /net/odin/usr/home/netbsd/cvsroot/syssrc/sys/nfs/nfs_node.c,v
retrieving revision 1.53
diff -u -u -p -r1.53 nfs_node.c
--- nfs/nfs_node.c	2002/03/16 23:05:25	1.53
+++ nfs/nfs_node.c	2002/10/02 20:32:42
@@ -272,17 +272,37 @@ nfs_reclaim(v)
 	} */ *ap = v;
 	struct vnode *vp = ap->a_vp;
 	struct nfsnode *np = VTONFS(vp);
-	struct nfsmount *nmp = VFSTONFS(vp->v_mount);
+	struct nfsmount *nmp = NULL;
+;
 
 	if (prtactive && vp->v_usecount != 0)
 		vprint("nfs_reclaim: pushing active", vp);
 
 	LIST_REMOVE(np, n_hash);
 
+	{
+		extern struct vfsops nfs_vfsops;
+		u_int32_t *ptr = (u_int32_t*) vp->v_mount;
+		if (ptr < (u_int32_t*)VM_MIN_KERNEL_ADDRESS
+			|| ptr >= (u_int32_t*)VM_MAX_KERNEL_ADDRESS
+			|| *ptr == 0xdeadbeef){
+			printf("nfs_reclaim: vnode %p has bogus MP %p\n", vp, vp->v_mount);
+		} else if (vp->v_mount->mnt_op != &nfs_vfsops){
+			printf("nfs_reclaim: vnode %p MP->mnt_ops %p != nfs_vfsops\n", vp, vp->v_mount->mnt_op);
+		} else {
+			nmp = VFSTONFS(vp->v_mount);
+			if ((vaddr_t)nmp < VM_MIN_KERNEL_ADDRESS
+				|| (vaddr_t)nmp >= VM_MAX_KERNEL_ADDRESS ){
+				printf("nfs_reclaim: vnode %p has bogus NMP %p\n", vp, nmp);
+				nmp = NULL;
+			}
+		}
+	}
+	
 	/*
 	 * For nqnfs, take it off the timer queue as required.
 	 */
-	if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
+	if (nmp && (nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
 		CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
 	}