summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm.c
diff options
context:
space:
mode:
authorHannes Reinecke2013-07-11 00:41:15 +0200
committerAlasdair G Kergon2013-07-11 00:41:15 +0200
commit6c182cd88d179cbbd06f4f8a8a19b6977940753f (patch)
tree27971aeafbdd2410699e77477565157c67d8ffea /drivers/md/dm.c
parentLinux 3.10 (diff)
downloadkernel-qcow2-linux-6c182cd88d179cbbd06f4f8a8a19b6977940753f.tar.gz
kernel-qcow2-linux-6c182cd88d179cbbd06f4f8a8a19b6977940753f.tar.xz
kernel-qcow2-linux-6c182cd88d179cbbd06f4f8a8a19b6977940753f.zip
dm mpath: fix ioctl deadlock when no paths
When multipath needs to retry an ioctl the reference to the current live table needs to be dropped. Otherwise a deadlock occurs when all paths are down: - dm_blk_ioctl takes a reference to the current table and spins in multipath_ioctl(). - A new table is being loaded, but upon resume the process hangs in dm_table_destroy() waiting for references to drop to zero. With this patch the reference to the old table is dropped prior to retry, thereby avoiding the deadlock. Signed-off-by: Hannes Reinecke <hare@suse.de> Cc: Mike Snitzer <snitzer@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r--drivers/md/dm.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index d5370a94b2c1..33f20103d8d5 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -386,10 +386,12 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct mapped_device *md = bdev->bd_disk->private_data;
- struct dm_table *map = dm_get_live_table(md);
+ struct dm_table *map;
struct dm_target *tgt;
int r = -ENOTTY;
+retry:
+ map = dm_get_live_table(md);
if (!map || !dm_table_get_size(map))
goto out;
@@ -410,6 +412,11 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
out:
dm_table_put(map);
+ if (r == -ENOTCONN) {
+ msleep(10);
+ goto retry;
+ }
+
return r;
}