From 6c182cd88d179cbbd06f4f8a8a19b6977940753f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 10 Jul 2013 23:41:15 +0100 Subject: 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 Cc: Mike Snitzer Cc: stable@vger.kernel.org Signed-off-by: Alasdair G Kergon --- drivers/md/dm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/md/dm.c') diff --git a/drivers/md/dm.c b/drivers/md/dm.c index d5370a94b2c..33f20103d8d 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; } -- cgit v1.2.3-18-g5258