Fix zpool on zvol lock inversion deadlock
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 19 Dec 2012 21:51:44 +0000 (13:51 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 20 Dec 2012 17:57:39 +0000 (09:57 -0800)
commit65d56083b4617a4cade0cff68cbbaf68114169d6
tree7707c7061ed4be1f0100649d0f7ff6fe6c3e756a
parentd5446cfc528262ae3a41da31a8524c9d2e793f45
Fix zpool on zvol lock inversion deadlock

In all but one case the spa_namespace_lock is taken before the
bdev->bd_mutex lock.  But Linux __blkdev_get() function calls
fops->open() with the bdev->bd_mutex lock held and we must
somehow still safely acquire the spa_namespace_lock.

To avoid a potential lock inversion deadlock we preemptively
try to take the spa_namespace_lock().  Normally it will not
be contended and this is safe because spa_open_common() handles
the case where the caller already holds the spa_namespace_lock.

When it is contended we risk a lock inversion if we were to
block waiting for the lock.  Luckily, the __blkdev_get()
function allows us to return -ERESTARTSYS which will result in
bdev->bd_mutex being dropped, reacquired, and fops->open() being
called again.  This process can be repeated safely until both
locks are acquired.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Jorgen Lundman <lundman@lundman.net>
Closes #612
module/zfs/zvol.c