aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm.c
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2013-07-10 18:41:15 -0400
committerAlasdair G Kergon <agk@redhat.com>2013-07-10 18:41:15 -0400
commit6c182cd88d179cbbd06f4f8a8a19b6977940753f (patch)
tree27971aeafbdd2410699e77477565157c67d8ffea /drivers/md/dm.c
parent8bb495e3f02401ee6f76d1b1d77f3ac9f079e376 (diff)
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,
386 unsigned int cmd, unsigned long arg) 386 unsigned int cmd, unsigned long arg)
387{ 387{
388 struct mapped_device *md = bdev->bd_disk->private_data; 388 struct mapped_device *md = bdev->bd_disk->private_data;
389 struct dm_table *map = dm_get_live_table(md); 389 struct dm_table *map;
390 struct dm_target *tgt; 390 struct dm_target *tgt;
391 int r = -ENOTTY; 391 int r = -ENOTTY;
392 392
393retry:
394 map = dm_get_live_table(md);
393 if (!map || !dm_table_get_size(map)) 395 if (!map || !dm_table_get_size(map))
394 goto out; 396 goto out;
395 397
@@ -410,6 +412,11 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode,
410out: 412out:
411 dm_table_put(map); 413 dm_table_put(map);
412 414
415 if (r == -ENOTCONN) {
416 msleep(10);
417 goto retry;
418 }
419
413 return r; 420 return r;
414} 421}
415 422