Move cv_destroy() outside zp->z_range_lock()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Fri, 4 Feb 2011 22:38:11 +0000 (14:38 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 10 Feb 2011 17:27:21 +0000 (09:27 -0800)
commit8926ab7a50d60d855e4d49d2ed7bdef49dd56149
treed87a6ca7624381f1a8c500ba7be772a3ba0499ca
parentc0d35759c5ab1abaa6b72062cc4ecd0d86628de8
Move cv_destroy() outside zp->z_range_lock()

With the recent SPL change (d599e4fa) that forces cv_destroy()
to block until all waiters have been woken.  It is now unsafe
to call cv_destroy() under the zp->z_range_lock() because it
is used as the condition variable mutex.  If there are waiters
cv_destroy() will block until they wake up and aquire the mutex.
However, they will never aquire the mutex because cv_destroy()
will not return allowing it's caller to drop the lock.  Deadlock.

To avoid this cv_destroy() is now run asynchronously in a taskq.
This solves two problems:

1) It is no longer run under the zp->z_range_lock so no deadlock.
2) Since cv_destroy() may now block we don't want this slowing
   down zfs_range_unlock() and throttling the system.

This was not as much of an issue under OpenSolaris because their
cv_destroy() implementation does not do anything.  They do however
risk a bad paging request if cv_destroy() returns, the memory holding
the condition variable is free'd, and then the waiters wake up and
try to reference it.  It's a very small unlikely race, but it is
possible.
module/zfs/zfs_rlock.c