diff options
Diffstat (limited to 'drivers/md/dm-mpath.c')
-rw-r--r-- | drivers/md/dm-mpath.c | 27 |
1 files changed, 6 insertions, 21 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index eff7bdd7731d..5a67671a3973 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -159,12 +159,9 @@ static struct priority_group *alloc_priority_group(void) | |||
159 | static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) | 159 | static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) |
160 | { | 160 | { |
161 | struct pgpath *pgpath, *tmp; | 161 | struct pgpath *pgpath, *tmp; |
162 | struct multipath *m = ti->private; | ||
163 | 162 | ||
164 | list_for_each_entry_safe(pgpath, tmp, pgpaths, list) { | 163 | list_for_each_entry_safe(pgpath, tmp, pgpaths, list) { |
165 | list_del(&pgpath->list); | 164 | list_del(&pgpath->list); |
166 | if (m->hw_handler_name) | ||
167 | scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev)); | ||
168 | dm_put_device(ti, pgpath->path.dev); | 165 | dm_put_device(ti, pgpath->path.dev); |
169 | free_pgpath(pgpath); | 166 | free_pgpath(pgpath); |
170 | } | 167 | } |
@@ -580,6 +577,7 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps | |||
580 | q = bdev_get_queue(p->path.dev->bdev); | 577 | q = bdev_get_queue(p->path.dev->bdev); |
581 | 578 | ||
582 | if (m->retain_attached_hw_handler) { | 579 | if (m->retain_attached_hw_handler) { |
580 | retain: | ||
583 | attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL); | 581 | attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL); |
584 | if (attached_handler_name) { | 582 | if (attached_handler_name) { |
585 | /* | 583 | /* |
@@ -599,20 +597,14 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps | |||
599 | } | 597 | } |
600 | 598 | ||
601 | if (m->hw_handler_name) { | 599 | if (m->hw_handler_name) { |
602 | /* | ||
603 | * Increments scsi_dh reference, even when using an | ||
604 | * already-attached handler. | ||
605 | */ | ||
606 | r = scsi_dh_attach(q, m->hw_handler_name); | 600 | r = scsi_dh_attach(q, m->hw_handler_name); |
607 | if (r == -EBUSY) { | 601 | if (r == -EBUSY) { |
608 | /* | 602 | char b[BDEVNAME_SIZE]; |
609 | * Already attached to different hw_handler: | ||
610 | * try to reattach with correct one. | ||
611 | */ | ||
612 | scsi_dh_detach(q); | ||
613 | r = scsi_dh_attach(q, m->hw_handler_name); | ||
614 | } | ||
615 | 603 | ||
604 | printk(KERN_INFO "dm-mpath: retaining handler on device %s\n", | ||
605 | bdevname(p->path.dev->bdev, b)); | ||
606 | goto retain; | ||
607 | } | ||
616 | if (r < 0) { | 608 | if (r < 0) { |
617 | ti->error = "error attaching hardware handler"; | 609 | ti->error = "error attaching hardware handler"; |
618 | dm_put_device(ti, p->path.dev); | 610 | dm_put_device(ti, p->path.dev); |
@@ -624,7 +616,6 @@ static struct pgpath *parse_path(struct dm_arg_set *as, struct path_selector *ps | |||
624 | if (r < 0) { | 616 | if (r < 0) { |
625 | ti->error = "unable to set hardware " | 617 | ti->error = "unable to set hardware " |
626 | "handler parameters"; | 618 | "handler parameters"; |
627 | scsi_dh_detach(q); | ||
628 | dm_put_device(ti, p->path.dev); | 619 | dm_put_device(ti, p->path.dev); |
629 | goto bad; | 620 | goto bad; |
630 | } | 621 | } |
@@ -734,12 +725,6 @@ static int parse_hw_handler(struct dm_arg_set *as, struct multipath *m) | |||
734 | return 0; | 725 | return 0; |
735 | 726 | ||
736 | m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL); | 727 | m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL); |
737 | if (!try_then_request_module(scsi_dh_handler_exist(m->hw_handler_name), | ||
738 | "scsi_dh_%s", m->hw_handler_name)) { | ||
739 | ti->error = "unknown hardware handler type"; | ||
740 | ret = -EINVAL; | ||
741 | goto fail; | ||
742 | } | ||
743 | 728 | ||
744 | if (hw_argc > 1) { | 729 | if (hw_argc > 1) { |
745 | char *p; | 730 | char *p; |