vgone() calling VOP_CLOSE() -> blocked threads?

Bruce Evans brde at optusnet.com.au
Wed Mar 19 15:23:32 UTC 2008


On Mon, 17 Mar 2008, Ed Schouten wrote:

> * Bruce Evans <brde at optusnet.com.au> wrote:
>> ...
>> I don't think it would work well to move everything except d_close to
>> deadfs.
>
> It wasn't my idea to make revoke() wait for all threads to leave. It
> should just inform the device driver that a revoke() has been performed,
> to wake up sleeping threads, and change the vnode to prevent further
> access.

OK...  Keep the move of d_close to deadfs too.  The driver might need to
call d_close to complete the effects of the revoke, but userland and vfs
shouldn't.

> The problem with the current implementation is that the device driver
> cannot sanely determine whether a revoke() or a real close() is called.
> Especially in my new TTY design, where a TTY could even be deallocated
> when a close() is performed - when the device driver has abandoned the
> TTY device - it would even destroy the TTY object that's being used by
> the sleeping threads.
>
> This is why I chose an approach that would allow threads to just leave
> the device driver as they normally would, which reduces complexity a
> lot.

Yes, kib's reply gives the rule that device close cannot destroy all device
structs.  It doesn't seem useful to destroy some structs earlier and then
have to check all over not to access them while the synchronization is
in progress.

Some drivers (mainly rp?) get into trouble in another way, by calling
dev_unbusy() in device close.  Last-close doesn't work well enough for
an unconditional dev_unbusy() to work there.  vfs refcounts don't
work well enough for a conditional dev_unbusy() (conditional on vfs counts
alone) to work there either.  Just checking si_threadcount in d_close()
and providing d_purge() to call dev_unbusy() if d_close() missed doing it
seems to be insufficient, since (I think) d_purge() and destroy_devl()
designed to destroy the whole device but not to synchronize when last-close
is performed out of order.

> My question is: what approach would you take in such a situation?
> Thanks for your input so far.

Something like the old tty approach (a generation count) with more wakeups
and more checking of the generation count.  It should be possible to check
a generation count more efficiently than si_*.  For si_*, some device locking
is needed.  Locking for si_* seems to be undocumented, but seems to be
simply mtx_lock() on the global devmtx mutex.  A generation count in struct
tty would be automatically locked by a tty mutex.

Bruce


More information about the freebsd-arch mailing list