]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Hannes Reinecke <hare@suse.de> |
2 | Subject: Reattach device handler for multipath devices | |
3 | References: bnc#435688 | |
4 | ||
5 | The multipath daemon might have specified a different device_handler | |
6 | than the one a device is attached to by default. | |
7 | So we should try to re-attach with the user-specified device_handler | |
8 | and only return an error if that fails. | |
9 | And we should _not_ detach existing hardware handlers. This will | |
10 | set the path to failed during failover. | |
11 | ||
12 | Signed-off-by: Hannes Reinecke <hare@suse.de | |
13 | ||
14 | --- | |
15 | drivers/md/dm-mpath.c | 16 ++++++++++++---- | |
16 | drivers/scsi/device_handler/scsi_dh.c | 10 +++------- | |
17 | 2 files changed, 15 insertions(+), 11 deletions(-) | |
18 | ||
19 | --- a/drivers/md/dm-mpath.c | |
20 | +++ b/drivers/md/dm-mpath.c | |
21 | @@ -163,8 +163,6 @@ static void free_pgpaths(struct list_hea | |
22 | ||
23 | list_for_each_entry_safe(pgpath, tmp, pgpaths, list) { | |
24 | list_del(&pgpath->list); | |
25 | - if (m->hw_handler_name) | |
26 | - scsi_dh_detach(bdev_get_queue(pgpath->path.dev->bdev)); | |
27 | dm_put_device(ti, pgpath->path.dev); | |
28 | spin_lock_irqsave(&m->lock, flags); | |
29 | if (m->pgpath_to_activate == pgpath) | |
30 | @@ -599,9 +597,19 @@ static struct pgpath *parse_path(struct | |
31 | } | |
32 | ||
33 | if (m->hw_handler_name) { | |
34 | - r = scsi_dh_attach(bdev_get_queue(p->path.dev->bdev), | |
35 | - m->hw_handler_name); | |
36 | + struct request_queue *q = bdev_get_queue(p->path.dev->bdev); | |
37 | + | |
38 | + r = scsi_dh_attach(q, m->hw_handler_name); | |
39 | + if (r == -EBUSY) { | |
40 | + /* | |
41 | + * Already attached to different hw_handler, | |
42 | + * try to reattach with correct one. | |
43 | + */ | |
44 | + scsi_dh_detach(q); | |
45 | + r = scsi_dh_attach(q, m->hw_handler_name); | |
46 | + } | |
47 | if (r < 0) { | |
48 | + ti->error = "error attaching hardware handler"; | |
49 | dm_put_device(ti, p->path.dev); | |
50 | goto bad; | |
51 | } | |
52 | --- a/drivers/scsi/device_handler/scsi_dh.c | |
53 | +++ b/drivers/scsi/device_handler/scsi_dh.c | |
54 | @@ -498,7 +498,6 @@ void scsi_dh_detach(struct request_queue | |
55 | { | |
56 | unsigned long flags; | |
57 | struct scsi_device *sdev; | |
58 | - struct scsi_device_handler *scsi_dh = NULL; | |
59 | ||
60 | spin_lock_irqsave(q->queue_lock, flags); | |
61 | sdev = scsi_device_from_queue(q); | |
62 | @@ -509,12 +508,9 @@ void scsi_dh_detach(struct request_queue | |
63 | if (!sdev) | |
64 | return; | |
65 | ||
66 | - if (sdev->scsi_dh_data) { | |
67 | - /* if sdev is not on internal list, detach */ | |
68 | - scsi_dh = sdev->scsi_dh_data->scsi_dh; | |
69 | - if (!device_handler_match(scsi_dh, sdev)) | |
70 | - scsi_dh_handler_detach(sdev, scsi_dh); | |
71 | - } | |
72 | + if (sdev->scsi_dh_data) | |
73 | + scsi_dh_handler_detach(sdev, sdev->scsi_dh_data->scsi_dh); | |
74 | + | |
75 | put_device(&sdev->sdev_gendev); | |
76 | } | |
77 | EXPORT_SYMBOL_GPL(scsi_dh_detach); |