diff options
author | Hannes Reinecke <hare@suse.de> | 2008-07-17 20:49:02 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-26 15:14:53 -0400 |
commit | ae11b1b36da726a8a93409b896704edc6b4f3402 (patch) | |
tree | 737e3602cb426c87f64ad26ccbfc12ce707d7b9e /drivers/md/dm-mpath.c | |
parent | 057ea7c9683c3d684128cced796f03c179ecf1c2 (diff) |
[SCSI] scsi_dh: attach to hardware handler from dm-mpath
multipath keeps a separate device table which may be
more current than the built-in one.
So we should make sure to always call ->attach whenever
a multipath map with hardware handler is instantiated.
And we should call ->detach on removal, too.
[sekharan: update as per comments from agk]
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/md/dm-mpath.c')
-rw-r--r-- | drivers/md/dm-mpath.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index fea966d66f98..71dd65aa31b6 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c | |||
@@ -147,9 +147,12 @@ static struct priority_group *alloc_priority_group(void) | |||
147 | static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) | 147 | static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti) |
148 | { | 148 | { |
149 | struct pgpath *pgpath, *tmp; | 149 | struct pgpath *pgpath, *tmp; |
150 | struct multipath *m = ti->private; | ||
150 | 151 | ||
151 | list_for_each_entry_safe(pgpath, tmp, pgpaths, list) { | 152 | list_for_each_entry_safe(pgpath, tmp, pgpaths, list) { |
152 | list_del(&pgpath->list); | 153 | list_del(&pgpath->list); |
154 | if (m->hw_handler_name) | ||
155 | scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev)); | ||
153 | dm_put_device(ti, pgpath->path.dev); | 156 | dm_put_device(ti, pgpath->path.dev); |
154 | free_pgpath(pgpath); | 157 | free_pgpath(pgpath); |
155 | } | 158 | } |
@@ -548,6 +551,7 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, | |||
548 | { | 551 | { |
549 | int r; | 552 | int r; |
550 | struct pgpath *p; | 553 | struct pgpath *p; |
554 | struct multipath *m = ti->private; | ||
551 | 555 | ||
552 | /* we need at least a path arg */ | 556 | /* we need at least a path arg */ |
553 | if (as->argc < 1) { | 557 | if (as->argc < 1) { |
@@ -566,6 +570,15 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps, | |||
566 | goto bad; | 570 | goto bad; |
567 | } | 571 | } |
568 | 572 | ||
573 | if (m->hw_handler_name) { | ||
574 | r = scsi_dh_attach(bdev_get_queue(p->path.dev->bdev), | ||
575 | m->hw_handler_name); | ||
576 | if (r < 0) { | ||
577 | dm_put_device(ti, p->path.dev); | ||
578 | goto bad; | ||
579 | } | ||
580 | } | ||
581 | |||
569 | r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error); | 582 | r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error); |
570 | if (r) { | 583 | if (r) { |
571 | dm_put_device(ti, p->path.dev); | 584 | dm_put_device(ti, p->path.dev); |