diff options
author | Mike Snitzer <snitzer@redhat.com> | 2012-09-26 18:45:41 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2012-09-26 18:45:41 -0400 |
commit | 7ba10aa6fbac7158a50bec142132b04bc480bb29 (patch) | |
tree | 161bfefb7c6f3552ae723554f8725b0dff37314d /drivers/md | |
parent | 307615a26e95406c42c95916a66ba50434567e0f (diff) |
dm mpath: only retry ioctl when no paths if queue_if_no_path set
When there are no paths and multipath receives an ioctl, it waits until
a path becomes available. This behaviour is incorrect if the
"queue_if_no_path" setting was not specified, as then the ioctl should
be rejected immediately, which this patch now does.
commit 35991652b ("dm mpath: allow ioctls to trigger pg init") should
have checked if queue_if_no_path was configured before queueing IO.
Checking for the queue_if_no_path feature, like is done in map_io(),
allows the following table load to work without blocking in the
multipath_ioctl retry loop:
echo "0 1024 multipath 0 0 0 0" | dmsetup create mpath_nodevs
Without this fix the multipath_ioctl will block with the following stack
trace:
blkid D 0000000000000002 0 23936 1 0x00000000
ffff8802b89e5cd8 0000000000000082 ffff8802b89e5fd8 0000000000012440
ffff8802b89e4010 0000000000012440 0000000000012440 0000000000012440
ffff8802b89e5fd8 0000000000012440 ffff88030c2aab30 ffff880325794040
Call Trace:
[<ffffffff814ce099>] schedule+0x29/0x70
[<ffffffff814cc312>] schedule_timeout+0x182/0x2e0
[<ffffffff8104dee0>] ? lock_timer_base+0x70/0x70
[<ffffffff814cc48e>] schedule_timeout_uninterruptible+0x1e/0x20
[<ffffffff8104f840>] msleep+0x20/0x30
[<ffffffffa0000839>] multipath_ioctl+0x109/0x170 [dm_multipath]
[<ffffffffa06bfb9c>] dm_blk_ioctl+0xbc/0xd0 [dm_mod]
[<ffffffff8122a408>] __blkdev_driver_ioctl+0x28/0x30
[<ffffffff8122a79e>] blkdev_ioctl+0xce/0x730
[<ffffffff811970ac>] block_ioctl+0x3c/0x40
[<ffffffff8117321c>] do_vfs_ioctl+0x8c/0x340
[<ffffffff81166293>] ? sys_newfstat+0x33/0x40
[<ffffffff81173571>] sys_ioctl+0xa1/0xb0
[<ffffffff814d70a9>] system_call_fastpath+0x16/0x1b
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org # 3.5+
Acked-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-mpath.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index d8abb90a6c2f..034233eefc82 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -1555,6 +1555,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, | |||
1555 | unsigned long arg) | 1555 | unsigned long arg) |
1556 | { | 1556 | { |
1557 | struct multipath *m = ti->private; | 1557 | struct multipath *m = ti->private; |
1558 | struct pgpath *pgpath; | ||
1558 | struct block_device *bdev; | 1559 | struct block_device *bdev; |
1559 | fmode_t mode; | 1560 | fmode_t mode; |
1560 | unsigned long flags; | 1561 | unsigned long flags; |
@@ -1570,12 +1571,14 @@ again: | |||
1570 | if (!m->current_pgpath) | 1571 | if (!m->current_pgpath) |
1571 | __choose_pgpath(m, 0); | 1572 | __choose_pgpath(m, 0); |
1572 | 1573 | ||
1573 | if (m->current_pgpath) { | 1574 | pgpath = m->current_pgpath; |
1574 | bdev = m->current_pgpath->path.dev->bdev; | 1575 | |
1575 | mode = m->current_pgpath->path.dev->mode; | 1576 | if (pgpath) { |
1577 | bdev = pgpath->path.dev->bdev; | ||
1578 | mode = pgpath->path.dev->mode; | ||
1576 | } | 1579 | } |
1577 | 1580 | ||
1578 | if (m->queue_io) | 1581 | if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path)) |
1579 | r = -EAGAIN; | 1582 | r = -EAGAIN; |
1580 | else if (!bdev) | 1583 | else if (!bdev) |
1581 | r = -EIO; | 1584 | r = -EIO; |