aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-mpath.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-mpath.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-mpath.c')
-rw-r--r--drivers/md/dm-mpath.c8
1 files changed, 2 insertions, 6 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index bdf26f5bd326..5adede17ddf6 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1561,7 +1561,6 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
1561 unsigned long flags; 1561 unsigned long flags;
1562 int r; 1562 int r;
1563 1563
1564again:
1565 bdev = NULL; 1564 bdev = NULL;
1566 mode = 0; 1565 mode = 0;
1567 r = 0; 1566 r = 0;
@@ -1579,7 +1578,7 @@ again:
1579 } 1578 }
1580 1579
1581 if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) 1580 if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
1582 r = -EAGAIN; 1581 r = -ENOTCONN;
1583 else if (!bdev) 1582 else if (!bdev)
1584 r = -EIO; 1583 r = -EIO;
1585 1584
@@ -1591,11 +1590,8 @@ again:
1591 if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) 1590 if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
1592 r = scsi_verify_blk_ioctl(NULL, cmd); 1591 r = scsi_verify_blk_ioctl(NULL, cmd);
1593 1592
1594 if (r == -EAGAIN && !fatal_signal_pending(current)) { 1593 if (r == -ENOTCONN && !fatal_signal_pending(current))
1595 queue_work(kmultipathd, &m->process_queued_ios); 1594 queue_work(kmultipathd, &m->process_queued_ios);
1596 msleep(10);
1597 goto again;
1598 }
1599 1595
1600 return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); 1596 return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
1601} 1597}