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); }