aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2012-06-02 19:29:58 -0400
committerAlasdair G Kergon <agk@redhat.com>2012-06-02 19:29:58 -0400
commit35991652baa12ff3d0e420c0d0cb2ad9f7076e5b (patch)
tree82d6d2bbd03be95dfb91e0678a94b613cbfc28ae /drivers
parentf220fd4efb334a772f9a14b2372175f38d89355e (diff)
dm mpath: allow ioctls to trigger pg init
After the failure of a group of paths, any alternative paths that need initialising do not become available until further I/O is sent to the device. Until this has happened, ioctls return -EAGAIN. With this patch, new paths are made available in response to an ioctl too. The processing of the ioctl gets delayed until this has happened. Instead of returning an error, we submit a work item to kmultipathd (that will potentially activate the new path) and retry in ten milliseconds. Note that the patch doesn't retry an ioctl if the ioctl itself fails due to a path failure. Such retries should be handled intelligently by the code that generated the ioctl in the first place, noting that some SCSI commands should not be retried because they are not idempotent (XOR write commands). For commands that could be retried, there is a danger that if the device rejected the SCSI command, the path could be errorneously marked as failed, and the request would be retried on another path which might fail too. It can be determined if the failure happens on the device or on the SCSI controller, but there is no guarantee that all SCSI drivers set these flags correctly. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/dm-mpath.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 2469ba68dc2..638dae048b4 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -18,6 +18,7 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/time.h> 19#include <linux/time.h>
20#include <linux/workqueue.h> 20#include <linux/workqueue.h>
21#include <linux/delay.h>
21#include <scsi/scsi_dh.h> 22#include <scsi/scsi_dh.h>
22#include <linux/atomic.h> 23#include <linux/atomic.h>
23 24
@@ -486,9 +487,6 @@ static void process_queued_ios(struct work_struct *work)
486 487
487 spin_lock_irqsave(&m->lock, flags); 488 spin_lock_irqsave(&m->lock, flags);
488 489
489 if (!m->queue_size)
490 goto out;
491
492 if (!m->current_pgpath) 490 if (!m->current_pgpath)
493 __choose_pgpath(m, 0); 491 __choose_pgpath(m, 0);
494 492
@@ -501,7 +499,6 @@ static void process_queued_ios(struct work_struct *work)
501 if (m->pg_init_required && !m->pg_init_in_progress && pgpath) 499 if (m->pg_init_required && !m->pg_init_in_progress && pgpath)
502 __pg_init_all_paths(m); 500 __pg_init_all_paths(m);
503 501
504out:
505 spin_unlock_irqrestore(&m->lock, flags); 502 spin_unlock_irqrestore(&m->lock, flags);
506 if (!must_queue) 503 if (!must_queue)
507 dispatch_queued_ios(m); 504 dispatch_queued_ios(m);
@@ -1522,11 +1519,16 @@ out:
1522static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, 1519static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
1523 unsigned long arg) 1520 unsigned long arg)
1524{ 1521{
1525 struct multipath *m = (struct multipath *) ti->private; 1522 struct multipath *m = ti->private;
1526 struct block_device *bdev = NULL; 1523 struct block_device *bdev;
1527 fmode_t mode = 0; 1524 fmode_t mode;
1528 unsigned long flags; 1525 unsigned long flags;
1529 int r = 0; 1526 int r;
1527
1528again:
1529 bdev = NULL;
1530 mode = 0;
1531 r = 0;
1530 1532
1531 spin_lock_irqsave(&m->lock, flags); 1533 spin_lock_irqsave(&m->lock, flags);
1532 1534
@@ -1551,6 +1553,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
1551 if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) 1553 if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
1552 r = scsi_verify_blk_ioctl(NULL, cmd); 1554 r = scsi_verify_blk_ioctl(NULL, cmd);
1553 1555
1556 if (r == -EAGAIN && !fatal_signal_pending(current)) {
1557 queue_work(kmultipathd, &m->process_queued_ios);
1558 msleep(10);
1559 goto again;
1560 }
1561
1554 return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); 1562 return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
1555} 1563}
1556 1564
@@ -1648,7 +1656,7 @@ out:
1648 *---------------------------------------------------------------*/ 1656 *---------------------------------------------------------------*/
1649static struct target_type multipath_target = { 1657static struct target_type multipath_target = {
1650 .name = "multipath", 1658 .name = "multipath",
1651 .version = {1, 3, 0}, 1659 .version = {1, 4, 0},
1652 .module = THIS_MODULE, 1660 .module = THIS_MODULE,
1653 .ctr = multipath_ctr, 1661 .ctr = multipath_ctr,
1654 .dtr = multipath_dtr, 1662 .dtr = multipath_dtr,