Module Name: src Committed By: snj Date: Mon Sep 28 01:43:02 UTC 2009
Modified Files: src/sys/ufs/ufs [netbsd-5]: ufs_ihash.c Log Message: Pull up following revision(s) (requested by bouyer in ticket #1029): sys/ufs/ufs/ufs_ihash.c: revision 1.27 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.26.10.1 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.26.10.1 --- src/sys/ufs/ufs/ufs_ihash.c:1.26 Mon May 5 17:11:17 2008 +++ src/sys/ufs/ufs/ufs_ihash.c Mon Sep 28 01:43:02 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.26.10.1 2009/09/28 01:43:02 snj 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.26.10.1 2009/09/28 01:43:02 snj 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); }