aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-mpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-mpath.c')
-rw-r--r--drivers/md/dm-mpath.c47
1 files changed, 30 insertions, 17 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 754f38f8a692..638dae048b4f 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
@@ -61,11 +62,11 @@ struct multipath {
61 struct list_head list; 62 struct list_head list;
62 struct dm_target *ti; 63 struct dm_target *ti;
63 64
64 spinlock_t lock;
65
66 const char *hw_handler_name; 65 const char *hw_handler_name;
67 char *hw_handler_params; 66 char *hw_handler_params;
68 67
68 spinlock_t lock;
69
69 unsigned nr_priority_groups; 70 unsigned nr_priority_groups;
70 struct list_head priority_groups; 71 struct list_head priority_groups;
71 72
@@ -81,16 +82,17 @@ struct multipath {
81 struct priority_group *next_pg; /* Switch to this PG if set */ 82 struct priority_group *next_pg; /* Switch to this PG if set */
82 unsigned repeat_count; /* I/Os left before calling PS again */ 83 unsigned repeat_count; /* I/Os left before calling PS again */
83 84
84 unsigned queue_io; /* Must we queue all I/O? */ 85 unsigned queue_io:1; /* Must we queue all I/O? */
85 unsigned queue_if_no_path; /* Queue I/O if last path fails? */ 86 unsigned queue_if_no_path:1; /* Queue I/O if last path fails? */
86 unsigned saved_queue_if_no_path;/* Saved state during suspension */ 87 unsigned saved_queue_if_no_path:1; /* Saved state during suspension */
88
87 unsigned pg_init_retries; /* Number of times to retry pg_init */ 89 unsigned pg_init_retries; /* Number of times to retry pg_init */
88 unsigned pg_init_count; /* Number of times pg_init called */ 90 unsigned pg_init_count; /* Number of times pg_init called */
89 unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */ 91 unsigned pg_init_delay_msecs; /* Number of msecs before pg_init retry */
90 92
93 unsigned queue_size;
91 struct work_struct process_queued_ios; 94 struct work_struct process_queued_ios;
92 struct list_head queued_ios; 95 struct list_head queued_ios;
93 unsigned queue_size;
94 96
95 struct work_struct trigger_event; 97 struct work_struct trigger_event;
96 98
@@ -328,14 +330,18 @@ static void __choose_pgpath(struct multipath *m, size_t nr_bytes)
328 /* 330 /*
329 * Loop through priority groups until we find a valid path. 331 * Loop through priority groups until we find a valid path.
330 * First time we skip PGs marked 'bypassed'. 332 * First time we skip PGs marked 'bypassed'.
331 * Second time we only try the ones we skipped. 333 * Second time we only try the ones we skipped, but set
334 * pg_init_delay_retry so we do not hammer controllers.
332 */ 335 */
333 do { 336 do {
334 list_for_each_entry(pg, &m->priority_groups, list) { 337 list_for_each_entry(pg, &m->priority_groups, list) {
335 if (pg->bypassed == bypassed) 338 if (pg->bypassed == bypassed)
336 continue; 339 continue;
337 if (!__choose_path_in_pg(m, pg, nr_bytes)) 340 if (!__choose_path_in_pg(m, pg, nr_bytes)) {
341 if (!bypassed)
342 m->pg_init_delay_retry = 1;
338 return; 343 return;
344 }
339 } 345 }
340 } while (bypassed--); 346 } while (bypassed--);
341 347
@@ -481,9 +487,6 @@ static void process_queued_ios(struct work_struct *work)
481 487
482 spin_lock_irqsave(&m->lock, flags); 488 spin_lock_irqsave(&m->lock, flags);
483 489
484 if (!m->queue_size)
485 goto out;
486
487 if (!m->current_pgpath) 490 if (!m->current_pgpath)
488 __choose_pgpath(m, 0); 491 __choose_pgpath(m, 0);
489 492
@@ -496,7 +499,6 @@ static void process_queued_ios(struct work_struct *work)
496 if (m->pg_init_required && !m->pg_init_in_progress && pgpath) 499 if (m->pg_init_required && !m->pg_init_in_progress && pgpath)
497 __pg_init_all_paths(m); 500 __pg_init_all_paths(m);
498 501
499out:
500 spin_unlock_irqrestore(&m->lock, flags); 502 spin_unlock_irqrestore(&m->lock, flags);
501 if (!must_queue) 503 if (!must_queue)
502 dispatch_queued_ios(m); 504 dispatch_queued_ios(m);
@@ -1517,11 +1519,16 @@ out:
1517static int multipath_ioctl(struct dm_target *ti, unsigned int cmd, 1519static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
1518 unsigned long arg) 1520 unsigned long arg)
1519{ 1521{
1520 struct multipath *m = (struct multipath *) ti->private; 1522 struct multipath *m = ti->private;
1521 struct block_device *bdev = NULL; 1523 struct block_device *bdev;
1522 fmode_t mode = 0; 1524 fmode_t mode;
1523 unsigned long flags; 1525 unsigned long flags;
1524 int r = 0; 1526 int r;
1527
1528again:
1529 bdev = NULL;
1530 mode = 0;
1531 r = 0;
1525 1532
1526 spin_lock_irqsave(&m->lock, flags); 1533 spin_lock_irqsave(&m->lock, flags);
1527 1534
@@ -1546,6 +1553,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
1546 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)
1547 r = scsi_verify_blk_ioctl(NULL, cmd); 1554 r = scsi_verify_blk_ioctl(NULL, cmd);
1548 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
1549 return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg); 1562 return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
1550} 1563}
1551 1564
@@ -1643,7 +1656,7 @@ out:
1643 *---------------------------------------------------------------*/ 1656 *---------------------------------------------------------------*/
1644static struct target_type multipath_target = { 1657static struct target_type multipath_target = {
1645 .name = "multipath", 1658 .name = "multipath",
1646 .version = {1, 3, 0}, 1659 .version = {1, 4, 0},
1647 .module = THIS_MODULE, 1660 .module = THIS_MODULE,
1648 .ctr = multipath_ctr, 1661 .ctr = multipath_ctr,
1649 .dtr = multipath_dtr, 1662 .dtr = multipath_dtr,