Skip to content

Commit 3599165

Browse files
Mikulas Patockakergon
authored andcommitted
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>
1 parent f220fd4 commit 3599165

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

drivers/md/dm-mpath.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/slab.h>
1919
#include <linux/time.h>
2020
#include <linux/workqueue.h>
21+
#include <linux/delay.h>
2122
#include <scsi/scsi_dh.h>
2223
#include <linux/atomic.h>
2324

@@ -486,9 +487,6 @@ static void process_queued_ios(struct work_struct *work)
486487

487488
spin_lock_irqsave(&m->lock, flags);
488489

489-
if (!m->queue_size)
490-
goto out;
491-
492490
if (!m->current_pgpath)
493491
__choose_pgpath(m, 0);
494492

@@ -501,7 +499,6 @@ static void process_queued_ios(struct work_struct *work)
501499
if (m->pg_init_required && !m->pg_init_in_progress && pgpath)
502500
__pg_init_all_paths(m);
503501

504-
out:
505502
spin_unlock_irqrestore(&m->lock, flags);
506503
if (!must_queue)
507504
dispatch_queued_ios(m);
@@ -1522,11 +1519,16 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
15221519
static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
15231520
unsigned long arg)
15241521
{
1525-
struct multipath *m = (struct multipath *) ti->private;
1526-
struct block_device *bdev = NULL;
1527-
fmode_t mode = 0;
1522+
struct multipath *m = ti->private;
1523+
struct block_device *bdev;
1524+
fmode_t mode;
15281525
unsigned long flags;
1529-
int r = 0;
1526+
int r;
1527+
1528+
again:
1529+
bdev = NULL;
1530+
mode = 0;
1531+
r = 0;
15301532

15311533
spin_lock_irqsave(&m->lock, flags);
15321534

@@ -1551,6 +1553,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
15511553
if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
15521554
r = scsi_verify_blk_ioctl(NULL, cmd);
15531555

1556+
if (r == -EAGAIN && !fatal_signal_pending(current)) {
1557+
queue_work(kmultipathd, &m->process_queued_ios);
1558+
msleep(10);
1559+
goto again;
1560+
}
1561+
15541562
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
15551563
}
15561564

@@ -1648,7 +1656,7 @@ static int multipath_busy(struct dm_target *ti)
16481656
*---------------------------------------------------------------*/
16491657
static struct target_type multipath_target = {
16501658
.name = "multipath",
1651-
.version = {1, 3, 0},
1659+
.version = {1, 4, 0},
16521660
.module = THIS_MODULE,
16531661
.ctr = multipath_ctr,
16541662
.dtr = multipath_dtr,

0 commit comments

Comments
 (0)