Subject: Re: kern/35542: NFS rename(?) panics (panic: lockmgr: release of unlocked lock!)
To: Antti Kantee <pooka@cs.hut.fi>
From: Chuck Silvers <chuq@chuq.com>
List: netbsd-bugs
Date: 02/03/2007 15:19:27
On Sat, Feb 03, 2007 at 05:15:57PM +0200, Antti Kantee wrote:
> Seems the problem is caused when attempting to rename stuff without
> enough permissions.  What's happening under the hood is that nfs_namei()
> now releases the lock on the directory vnode in case of an error, so
> releasing it again in nfsrv_rename() causes the panic.

dirp can be non-NULL even when nfs_namei() returns an error,
so we just need to change the errant vput() back to vrele(),
like it was before my changes.  the usage of dirp here would then
match all the other callers of nfs_namei().  the subsequent call
that I added to unlock dirp should really refer to fromnd.ni_dvp
(which for non-WebNFS is always the same vnode as dirp, which is
why we didn't notice).

looking more closely at nfs_namei(), in the WebNFS error cases
we actually release the hold on the returned dirp, so we ought to
fix that as well while we're here.

oh, and I see that the fix you made to rename_files() is needed
in nfsrv_rename() as well.

here's the diff for all these:

Index: nfs/nfs_serv.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_serv.c,v
retrieving revision 1.122
diff -u -p -r1.122 nfs_serv.c
--- nfs/nfs_serv.c	4 Jan 2007 20:24:08 -0000	1.122
+++ nfs/nfs_serv.c	3 Feb 2007 17:41:00 -0000
@@ -1898,11 +1898,13 @@ nfsrv_rename(nfsd, slp, lwp, mrq)
 		nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
 		nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
 		if (fdirp)
-			vput(fdirp);
+			vrele(fdirp);
 		vn_finished_write(mp, 0);
 		return (0);
 	}
-	VOP_UNLOCK(fdirp, 0);
+	if (fromnd.ni_dvp != fromnd.ni_vp) {
+		VOP_UNLOCK(fromnd.ni_dvp, 0);
+	}
 	fvp = fromnd.ni_vp;
 	nfsm_srvmtofh(&tnsfh);
 	if (v3) {
Index: nfs/nfs_subs.c
===================================================================
RCS file: /cvsroot/src/sys/nfs/nfs_subs.c,v
retrieving revision 1.179
diff -u -p -r1.179 nfs_subs.c
--- nfs/nfs_subs.c	27 Dec 2006 12:10:09 -0000	1.179
+++ nfs/nfs_subs.c	3 Feb 2007 17:41:01 -0000
@@ -2133,7 +2133,6 @@ nfs_namei(ndp, nsfh, len, slp, nam, mdp,
 			 */
 			default:
 				error = EIO;
-				vrele(dp);
 				PNBUF_PUT(cp);
 				goto out;
 			}
@@ -2150,7 +2149,6 @@ nfs_namei(ndp, nsfh, len, slp, nam, mdp,
 					continue;
 				} else {
 					error = ENOENT;
-					vrele(dp);
 					PNBUF_PUT(cp);
 					goto out;
 				}




-Chuck