Module Name:    src
Committed By:   bouyer
Date:           Sun Sep 20 14:00:24 UTC 2009

Modified Files:
        src/sys/ufs/ufs: ufs_ihash.c

Log Message:
PR kern/41147: race between nfsd and local rm
Note that the race also exists between 2 nfs client, one of them doing the rm.
In ufs_ihashget(), vget() can return a vnode that has been vclean'ed because
vget() can sleep. After vget returns, check that vp is still connected with
ip, and that ip still points to the inode we want. This fix the NULL
pointer dereference in ufs_fhtovp() I've been seeing on a NFS server.

XXX I have no idea why using vput() instead of
vlockmgr(vp->v_vnlock, LK_RELEASE); vrele(vp); does not work.


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/ufs/ufs/ufs_ihash.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/ufs/ufs/ufs_ihash.c
diff -u src/sys/ufs/ufs/ufs_ihash.c:1.26 src/sys/ufs/ufs/ufs_ihash.c:1.27
--- src/sys/ufs/ufs/ufs_ihash.c:1.26	Mon May  5 17:11:17 2008
+++ src/sys/ufs/ufs/ufs_ihash.c	Sun Sep 20 14:00:24 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_ihash.c,v 1.26 2008/05/05 17:11:17 ad Exp $	*/
+/*	$NetBSD: ufs_ihash.c,v 1.27 2009/09/20 14:00:24 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_ihash.c,v 1.26 2008/05/05 17:11:17 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_ihash.c,v 1.27 2009/09/20 14:00:24 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -152,6 +152,15 @@
 				mutex_exit(&ufs_ihash_lock);
 				if (vget(vp, flags | LK_INTERLOCK))
 					goto loop;
+				if (VTOI(vp) != ip ||
+				    ip->i_number != inum || ip->i_dev != dev) {
+					/* lost race against vclean() */
+					if (vlockmgr(vp->v_vnlock, LK_RELEASE))
+						printf("can't release lock\n");
+					vrele(vp);
+					vp = NULL;
+					goto loop;
+				}
 			}
 			return (vp);
 		}

Reply via email to