Subject: kernel panics with VNODE_LOCKDEBUG set
To: None <tech-kern@netbsd.org>
From: Brett Lymn <blymn@baesystems.com.au>
List: tech-kern
Date: 09/19/2006 21:55:37
Folks,

I have what I think is a locking problem and I thought that turning on
VNODE_LOCKDEBUG in my kernel config would help me track the problem
down.  Unfortunately, enabling this option causes the kernel to panic
when init is being executed.  The problem appears to be that the vnode
is locked with LK_SHARED (which does seem reasonable for a read
operation) but the VNODE_LOCKDEBUG code only checks if the vnode is
locked with LK_EXCLUSIVE and, hence, since the lock is not as expected
the debug code panics the kernel.

I fiddled with sys/kern/vnode_if.sh and added in an extra check to
check if there is a LK_SHARED lock which seems to make things run a
bit better but the kernel falls over in sys_mount() because VOP_LOCK
is called with a lock held _but_ the options on the lock allow
recursion on the lock so this should be a valid thing to do.  At the
moment I am not sure how to resolve this.

Anyway, is this a valid thing to do:

Index: vnode_if.sh
===================================================================
RCS file: /cvsroot/src/sys/kern/vnode_if.sh,v
retrieving revision 1.42
diff -u -r1.42 vnode_if.sh
--- vnode_if.sh 14 May 2006 21:15:12 -0000      1.42
+++ vnode_if.sh 19 Sep 2006 12:25:00 -0000
@@ -356,8 +356,8 @@
                printf("\ta.a_%s = %s;\n", argname[i], argname[i]);
                if (lockstate[i] != -1) {
                        printf("#ifdef VNODE_LOCKDEBUG\n");
-                       printf("\tislocked_%s = (%s->v_flag & VLOCKSWORK) ? (VOP_ISLOCKED(%s) == LK_EXCLUSIVE) : %d;\n",
-                           argname[i], argname[i], argname[i], lockstate[i]);
+                       printf("\tislocked_%s = (%s->v_flag & VLOCKSWORK) ? ((VOP_ISLOCKED(%s) == LK_EXCLUSIVE) || (VOP_ISLOCKED(%s) == LK_SHARED)) : %d;\n",
+                           argname[i], argname[i], argname[i], argname[i], lockstate[i]);
                        printf("\tif (islocked_%s != %d)\n", argname[i],
                            lockstate[i]);
                        printf("\t\tpanic(\"%s: %s: locked %%d, expected %%d\", islocked_%s, %d);\n", name, argname[i], argname[i], lockstate[i]);

-- 
Brett Lymn