Subject: CVS commit: [netbsd-2] src/sys/kern
To: None <source-changes@NetBSD.org>
From: Jeff Rizzo <email@example.com>
Date: 12/29/2005 01:37:07
Module Name: src
Committed By: riz
Date: Thu Dec 29 01:37:07 UTC 2005
src/sys/kern [netbsd-2]: vfs_subr.c
Pull up following revision(s) (requested by chs in ticket #10207):
sys/kern/vfs_subr.c: revision 1.231
There is an annoying deadlock that goes like this:
* Process A is closing one file descriptor belonging to a device. In doing so,
ffs_update() is called and starts writing a block synchronously. (Note: This
leaves the vnode locked. It also has other instances -- stdin, et al -- of
the same device open, so v_usecount is definitely non-zero.)
* Process B does a revoke() on the device. The revoke() has to wait for the
vnode to be unlocked because ffs_update() is still in progress.
* Process C tries to open() the device. It wedges in checkalias() repeatedly
calling vget() because it returns EBUSY immediately.
To fix, this:
* checkalias() now uses LK_SLEEPFAIL rather than LK_NOWAIT. Therefore it will
wait for the vnode to become unlocked, but it will recheck that it is on the
hash list, in case it was in the process of being revoke()d or was revoke()d
again before we were woken up.
* Since we're relying on the vnode lock to tell us that the vnode hasn't been
removed from the hash list *anyway*, I have moved the code to remove it into
the DOCLOSE section of vclean(), inside the vnode lock.
In the example at hand, process A was sh(1), process B was a child of init(8),
and process C was syslogd(8).
To generate a diff of this commit:
cvs rdiff -r22.214.171.124 -r126.96.36.199.2.1 src/sys/kern/vfs_subr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.