zfsonlinux/zfs — pull request #1157 by ryao (2012-12-19 00:01:05+00:00)
Title: Fix deadlock when making ZFS pools on zvols.

When making a pool, zpool is invoked, which takes spa_namespace_lock and
invokes vdev_open_children(). vdev_open_children() has two code paths.
One that is used for zvols and one used for any other type of vdev. The
zvol path will call vdev_open() for each child in the same thread while
the other path will use a taskqueue. zvol_open() will invoke
spa_vdev_remove(), which will check whether or not the lock is held and
grab it if it is not held.

vdev_open_children() invokes vdev_uses_zvols() to determine which of the
two code paths to take. It currently unconditionally returns false, causing
vdev_open_children() to use task queues unconditionally. The consequence
is that spa_namespace_lock is always being held by another thread when
vdev_open() is called, guaranteeing a deadlock.

We can fix this at the cost of some parallelism by making
vdev_uses_zvols() return B_TRUE instead of B_FALSE. A proper fix will
involve making vdev_uses_zvols() properly detect whether a device is a
zvol.

Signed-off-by: Richard Yao