:It's not hard. vput() VOP_UNLOCK()s a vnode and then vrele() (opposite of
:vref())'s it (decreases v_usecount, I believe.) So when a file system
:is mounted, with these bugs, the locked vnodes are never unlocked.
:The unmount call will end up sleeping with the state "vnlock" waiting for
:the operation that has the vnode in question vref()d to vrele() and
:let go of it.
:
:At least, that's how it looks to me, but I never really looked at vnode
:code until today.
:
: Brian Fundakowski Feldman _ __ ___ ____ ___ ___ ___
: [EMAIL PROTECTED] _ __ ___ | _ ) __| \
: FreeBSD: The Power to Serve! _ __ | _ \._ \ |) |
: http://www.FreeBSD.org/ _ |___/___/___/
Basically, yes. The NFS code is a morass no matter what. Here's a
full explanation:
readdirplus is like readdir except it returns stat info along with the
directory entries, since most NFS clients will stat the files it picks
up scanning a directory.
In order to accomplish this, the underlying vnode representing each
directory entry is retrieved and locked. However, there is a special
case: We *already* have a reference on the directory vnode itself,
and one of the directory entries, ".", will be the same vnode. Our
reference vnode, vp is *NOT* locked. In fact, we *can't* lock it
without creating a potential deadlock situation (at least that is my
take).
Ok, so while scanning the directory we generate 'newvp' vnode pointers.
If the directory entry is "." the newvp == vp (vp is the parent
directory), and there is no lock on the vp, only a reference. If
newvp != vp then it is a directory entry other then "." and newvp is
both referenced *and* locked.
When we are through retrieving the stat info from newvp, we have to
release it. We either have to release and unlock newvp, or we simply
have to release it depending on whether it was locked or not.
vrele() will release a vnode without messing with any locks.
vput() will release and unlock a vnode.
Hence the complexity: if (newvp == vp) vrele(newvp); else; vput(newvp);
-Matt
Matthew Dillon
<[EMAIL PROTECTED]>
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message