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()?