Module Name: src Committed By: yamt Date: Sun May 10 05:18:26 UTC 2009
Modified Files: src/sys/nfs: nfs_vnops.c Log Message: nfs_lookup: vn_lock the vnode returned by cache_lookup_raw before feeding it to VOP_GETATTR. it's necessary because the vnode might be being cleaned by getcleanvnode. it's an instance of more general races between vnode reclaim and unlocked VOPs. however, this one happens somewhat often because it can be triggered by getnewvnode rather than revoke. To generate a diff of this commit: cvs rdiff -u -r1.277 -r1.278 src/sys/nfs/nfs_vnops.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/nfs/nfs_vnops.c diff -u src/sys/nfs/nfs_vnops.c:1.277 src/sys/nfs/nfs_vnops.c:1.278 --- src/sys/nfs/nfs_vnops.c:1.277 Sun May 10 03:51:43 2009 +++ src/sys/nfs/nfs_vnops.c Sun May 10 05:18:26 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_vnops.c,v 1.277 2009/05/10 03:51:43 yamt Exp $ */ +/* $NetBSD: nfs_vnops.c,v 1.278 2009/05/10 05:18:26 yamt Exp $ */ /* * Copyright (c) 1989, 1993 @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.277 2009/05/10 03:51:43 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.278 2009/05/10 05:18:26 yamt Exp $"); #ifdef _KERNEL_OPT #include "opt_nfs.h" @@ -855,31 +855,30 @@ * investigate the vnode returned by cache_lookup_raw. * if it isn't appropriate, do an rpc. */ - newvp = *vpp; + if ((flags & ISDOTDOT) != 0) { + VOP_UNLOCK(dvp, 0); + } + error = vn_lock(newvp, LK_EXCLUSIVE); + if ((flags & ISDOTDOT) != 0) { + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); + } + if (error != 0) { + /* newvp has been reclaimed. */ + vrele(newvp); + *vpp = NULLVP; + goto dorpc; + } if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred) && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { nfsstats.lookupcache_hits++; - if ((flags & ISDOTDOT) != 0) { - VOP_UNLOCK(dvp, 0); - } - error = vn_lock(newvp, LK_EXCLUSIVE); - if ((flags & ISDOTDOT) != 0) { - vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY); - } - if (error != 0) { - /* newvp has been revoked. */ - vrele(newvp); - *vpp = NULLVP; - goto dorpc; - } if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; KASSERT(newvp->v_type != VNON); return (0); } cache_purge1(newvp, NULL, PURGE_PARENTS); - vrele(newvp); + vput(newvp); *vpp = NULLVP; } dorpc: