diff mbox

[3.5.y.z,extended,stable] Patch "dm mpath: fix ioctl deadlock when no paths" has been added to staging queue

Message ID 1374657101-11117-1-git-send-email-luis.henriques@canonical.com
State New
Headers show

Commit Message

Luis Henriques July 24, 2013, 9:11 a.m. UTC
This is a note to let you know that I have just added a patch titled

    dm mpath: fix ioctl deadlock when no paths

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.5.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Luis

------

From 8c882678b274dd28209e1e05e774d27f4306515c Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Wed, 10 Jul 2013 23:41:15 +0100
Subject: [PATCH] dm mpath: fix ioctl deadlock when no paths

commit 6c182cd88d179cbbd06f4f8a8a19b6977940753f upstream.

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>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
---
 drivers/md/dm-mpath.c | 8 ++------
 drivers/md/dm.c       | 9 ++++++++-
 2 files changed, 10 insertions(+), 7 deletions(-)

--
1.8.1.2
diff mbox

Patch

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 1ca41d2..93b3c2d 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1526,7 +1526,6 @@  static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
 	unsigned long flags;
 	int r;

-again:
 	bdev = NULL;
 	mode = 0;
 	r = 0;
@@ -1544,7 +1543,7 @@  again:
 	}

 	if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
-		r = -EAGAIN;
+		r = -ENOTCONN;
 	else if (!bdev)
 		r = -EIO;

@@ -1556,11 +1555,8 @@  again:
 	if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
 		r = scsi_verify_blk_ioctl(NULL, cmd);

-	if (r == -EAGAIN && !fatal_signal_pending(current)) {
+	if (r == -ENOTCONN && !fatal_signal_pending(current))
 		queue_work(kmultipathd, &m->process_queued_ios);
-		msleep(10);
-		goto again;
-	}

 	return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
 }
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 32370ea..9a7290b 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -414,10 +414,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;

@@ -438,6 +440,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;
 }