Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs/ufs PR kern/41147: race between nfsd and local rm



details:   https://anonhg.NetBSD.org/src/rev/666ef66f6154
branches:  trunk
changeset: 747555:666ef66f6154
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Sun Sep 20 14:00:24 2009 +0000

description:
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.

diffstat:

 sys/ufs/ufs/ufs_ihash.c |  13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diffs (34 lines):

diff -r f04645ff6e4a -r 666ef66f6154 sys/ufs/ufs/ufs_ihash.c
--- a/sys/ufs/ufs/ufs_ihash.c   Sun Sep 20 10:29:30 2009 +0000
+++ b/sys/ufs/ufs/ufs_ihash.c   Sun Sep 20 14:00:24 2009 +0000
@@ -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);
                }



Home | Main Index | Thread Index | Old Index