Subject: Re: vnode refcount panic, perhaps due to kern/vfs_lookup.c:lookup()
To: Greg Troxel <gdt@ir.bbn.com>
From: Bill Studenmund <wrstuden@netbsd.org>
List: tech-kern
Date: 03/14/2003 14:24:59
On 14 Mar 2003, Greg Troxel wrote:

> I just read some more code, and noticed that
> coda/coda_vfsops.c:coda_symlink() calls vput just before calling
> lookup.  From what I can tell, lookup expects that the vnode passed in
> is both locked and referenced, so this seems just plain wrong.  So it
> may be that there were two locks on the same vnode in lookup, and that
> code is correct.  But, I really don't understand vfs/vnode rules very
> well.

lookup() is complicated, but it isn't that bad.

Here's how VOP_LOOKUP()'s locking is described in vnode_if.src:

# XXX - the lookup locking protocol defies simple description and depends
#     on the flags and operation fields in the (cnp) structure.  Note
#     especially that *vpp may equal dvp and both may be locked.
#
#    More details:
#     There are three types of lookups: ".", ".." (ISDOTDOT), and other.
#     On successful lookup of ".", a reference is added to dvp, and it
#          is returned in *vpp.
#     To look up ISDOTDOT, dvp is unlocked, the ".." node is locked, and
#          then dvp is relocked iff LOCKPARENT is set and this is the last
#          component name (ISLASTCN set). This preserves the
#          protocol of always locking nodes from root ("/") downward and
#          prevents deadlock.
#     Other lookups find the named node (creating the vnode if needed) and
#          return it, locked, in *vpp.
#     For non-"." lookups, if LOCKPARENT is not set or this was not the
#          last component name, dvp is returned unlocked on a successful
#          lookup.
#     On failure, *vpp is NULL, and *dvp is usually left locked. If there was
#          an error re-locking dvp (for instance in the ISDOTDOT case),
#          or dvp was not re-locked for some other reason, the error is
#          returned and the PDIRUNLOCK flag is set.
#
#     *vpp is always locked on return if the operation succeeds.
#     typically, if *vpp == dvp, you need to release twice, but unlock once.
#
#     The PDIRUNLOCK flag is set when dvp is unlocked in the lookup routine.
#          It signals the caller that dvp's lock state changed. It will
#          be set on exit if either a successful lookup unlocked the
#          parrent, there was an error re-locking dvp in the ISDOTDOT case,
#          or if there was some other error and the lookup routine did
#          not re-lock dvp.

The only time that *vpp and dvp should match is if you're looking up '.',
which you aren't.

Something looks wrong...

Take care,

Bill