Subject: kern/32431: Assertion on vn_lock flags breaks layered mounts
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <cube@cubidou.net>
List: netbsd-bugs
Date: 01/02/2006 07:16:11
>Number: 32431
>Category: kern
>Synopsis: Assertion on vn_lock flags breaks layered mounts
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Jan 02 07:16:11 +0000 2006
>Originator: Quentin Garnier
>Release: very fresh -current (about 1 hour ago)
>Organization:
>Environment:
Architecture: x86_64
Machine: amd64
>Description:
Layered mounts can trigger an assertion in vn_lock() that was
introduced recently.
The code that triggers the assertion is there, in
genfs/layer_subr.c:layer_node_find()
150 /*
151 * We must be careful here as the fact the lower
152 * vnode is locked will imply vp is locked unless
153 * someone has decided to start vclean'ing either
154 * vp or lowervp.
155 *
156 * So we try for an exclusive, recursive lock
157 * on the upper vnode. If it fails, vcleaning
158 * is in progress (so when we try again, we'll
159 * fail). If it succeeds, we now have double
160 * locked the bottom node. So we do an explicit
161 * VOP_UNLOCK on it to keep the counts right. Note
162 * that we will end up with the upper node and
163 * the lower node locked once.
164 */
165 if (vget(vp, LK_EXCLUSIVE | LK_CANRECURSE)) {
166 printf ("layer_node_find: vget failed.\n");
167 goto loop;
168 };
It result in the following panic:
panic: kernel diagnostic assertion "(flags & ~(LK_INTERLOCK|LK_SHARED|LK_EXCLUSIVE|LK_DRAIN|LK_NOWAIT|LK_RETRY| LK_SETRECURSE)) == 0" failed: file "/cvsroot/commit/src/sys/kern/vfs_vnops.c", line 711
Stopped in pid 1111.1 (ksh) at netbsd:cpu_Debugger+0x5: leave
db{0}> bt
cpu_Debugger() at netbsd:cpu_Debugger+0x5
panic() at netbsd:panic+0x1c8
__assert() at netbsd:__assert+0x21
vn_lock() at netbsd:vn_lock+0xe3
vget() at netbsd:vget+0xf8
layer_node_find() at netbsd:layer_node_find+0xa7
layer_node_create() at netbsd:layer_node_create+0x2d
layer_lookup() at netbsd:layer_lookup+0xb4
VOP_LOOKUP() at netbsd:VOP_LOOKUP+0x2e
lookup() at netbsd:lookup+0x227
namei() at netbsd:namei+0x15c
sys___lstat30() at netbsd:sys___lstat30+0x70
syscall_plain() at netbsd:syscall_plain+0xfb
>How-To-Repeat:
mount_null /sbin /mnt
Then try auto-completion in /mnt. ls -l might do the trick,
too, considering it blows from lstat().
>Fix:
Unknown. Replace LK_CANRECURSE by something else, or add it to
the list of allowed flags for vn_lock()?