summaryrefslogtreecommitdiffstats
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.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 638dae048b4f..d8abb90a6c2f 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -85,6 +85,7 @@ struct multipath {
85 unsigned queue_io:1; /* Must we queue all I/O? */ 85 unsigned queue_io:1; /* Must we queue all I/O? */
86 unsigned queue_if_no_path:1; /* Queue I/O if last path fails? */ 86 unsigned queue_if_no_path:1; /* Queue I/O if last path fails? */
87 unsigned saved_queue_if_no_path:1; /* Saved state during suspension */ 87 unsigned saved_queue_if_no_path:1; /* Saved state during suspension */
88 unsigned retain_attached_hw_handler:1; /* If there's already a hw_handler present, don't change it. */
88 89
89 unsigned pg_init_retries; /* Number of times to retry pg_init */ 90 unsigned pg_init_retries; /* Number of times to retry pg_init */
90 unsigned pg_init_count; /* Number of times pg_init called */ 91 unsigned pg_init_count; /* Number of times pg_init called */
@@ -568,6 +569,8 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
568 int r; 569 int r;
569 struct pgpath *p; 570 struct pgpath *p;
570 struct multipath *m = ti->private; 571 struct multipath *m = ti->private;
572 struct request_queue *q = NULL;
573 const char *attached_handler_name;
571 574
572 /* we need at least a path arg */ 575 /* we need at least a path arg */
573 if (as->argc < 1) { 576 if (as->argc < 1) {
@@ -586,13 +589,37 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps
586 goto bad; 589 goto bad;
587 } 590 }
588 591
589 if (m->hw_handler_name) { 592 if (m->retain_attached_hw_handler || m->hw_handler_name)
590 struct request_queue *q = bdev_get_queue(p->path.dev->bdev); 593 q = bdev_get_queue(p->path.dev->bdev);
594
595 if (m->retain_attached_hw_handler) {
596 attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL);
597 if (attached_handler_name) {
598 /*
599 * Reset hw_handler_name to match the attached handler
600 * and clear any hw_handler_params associated with the
601 * ignored handler.
602 *
603 * NB. This modifies the table line to show the actual
604 * handler instead of the original table passed in.
605 */
606 kfree(m->hw_handler_name);
607 m->hw_handler_name = attached_handler_name;
608
609 kfree(m->hw_handler_params);
610 m->hw_handler_params = NULL;
611 }
612 }
591 613
614 if (m->hw_handler_name) {
615 /*
616 * Increments scsi_dh reference, even when using an
617 * already-attached handler.
618 */
592 r = scsi_dh_attach(q, m->hw_handler_name); 619 r = scsi_dh_attach(q, m->hw_handler_name);
593 if (r == -EBUSY) { 620 if (r == -EBUSY) {
594 /* 621 /*
595 * Already attached to different hw_handler, 622 * Already attached to different hw_handler:
596 * try to reattach with correct one. 623 * try to reattach with correct one.
597 */ 624 */
598 scsi_dh_detach(q); 625 scsi_dh_detach(q);
@@ -760,7 +787,7 @@ static int parse_features(struct dm_arg_set *as, struct multipath *m)
760 const char *arg_name; 787 const char *arg_name;
761 788
762 static struct dm_arg _args[] = { 789 static struct dm_arg _args[] = {
763 {0, 5, "invalid number of feature args"}, 790 {0, 6, "invalid number of feature args"},
764 {1, 50, "pg_init_retries must be between 1 and 50"}, 791 {1, 50, "pg_init_retries must be between 1 and 50"},
765 {0, 60000, "pg_init_delay_msecs must be between 0 and 60000"}, 792 {0, 60000, "pg_init_delay_msecs must be between 0 and 60000"},
766 }; 793 };
@@ -781,6 +808,11 @@ static int parse_features(struct dm_arg_set *as, struct multipath *m)
781 continue; 808 continue;
782 } 809 }
783 810
811 if (!strcasecmp(arg_name, "retain_attached_hw_handler")) {
812 m->retain_attached_hw_handler = 1;
813 continue;
814 }
815
784 if (!strcasecmp(arg_name, "pg_init_retries") && 816 if (!strcasecmp(arg_name, "pg_init_retries") &&
785 (argc >= 1)) { 817 (argc >= 1)) {
786 r = dm_read_arg(_args + 1, as, &m->pg_init_retries, &ti->error); 818 r = dm_read_arg(_args + 1, as, &m->pg_init_retries, &ti->error);
@@ -1346,7 +1378,7 @@ static void multipath_resume(struct dm_target *ti)
1346 * num_paths num_selector_args [path_dev [selector_args]* ]+ ]+ 1378 * num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
1347 */ 1379 */
1348static int multipath_status(struct dm_target *ti, status_type_t type, 1380static int multipath_status(struct dm_target *ti, status_type_t type,
1349 char *result, unsigned int maxlen) 1381 unsigned status_flags, char *result, unsigned maxlen)
1350{ 1382{
1351 int sz = 0; 1383 int sz = 0;
1352 unsigned long flags; 1384 unsigned long flags;
@@ -1364,13 +1396,16 @@ static int multipath_status(struct dm_target *ti, status_type_t type,
1364 else { 1396 else {
1365 DMEMIT("%u ", m->queue_if_no_path + 1397 DMEMIT("%u ", m->queue_if_no_path +
1366 (m->pg_init_retries > 0) * 2 + 1398 (m->pg_init_retries > 0) * 2 +
1367 (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) * 2); 1399 (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) * 2 +
1400 m->retain_attached_hw_handler);
1368 if (m->queue_if_no_path) 1401 if (m->queue_if_no_path)
1369 DMEMIT("queue_if_no_path "); 1402 DMEMIT("queue_if_no_path ");
1370 if (m->pg_init_retries) 1403 if (m->pg_init_retries)
1371 DMEMIT("pg_init_retries %u ", m->pg_init_retries); 1404 DMEMIT("pg_init_retries %u ", m->pg_init_retries);
1372 if (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT) 1405 if (m->pg_init_delay_msecs != DM_PG_INIT_DELAY_DEFAULT)
1373 DMEMIT("pg_init_delay_msecs %u ", m->pg_init_delay_msecs); 1406 DMEMIT("pg_init_delay_msecs %u ", m->pg_init_delay_msecs);
1407 if (m->retain_attached_hw_handler)
1408 DMEMIT("retain_attached_hw_handler ");
1374 } 1409 }
1375 1410
1376 if (!m->hw_handler_name || type == STATUSTYPE_INFO) 1411 if (!m->hw_handler_name || type == STATUSTYPE_INFO)
@@ -1656,7 +1691,7 @@ out:
1656 *---------------------------------------------------------------*/ 1691 *---------------------------------------------------------------*/
1657static struct target_type multipath_target = { 1692static struct target_type multipath_target = {
1658 .name = "multipath", 1693 .name = "multipath",
1659 .version = {1, 4, 0}, 1694 .version = {1, 5, 0},
1660 .module = THIS_MODULE, 1695 .module = THIS_MODULE,
1661 .ctr = multipath_ctr, 1696 .ctr = multipath_ctr,
1662 .dtr = multipath_dtr, 1697 .dtr = multipath_dtr,