1 From: Hannes Reinecke <hare@suse.de>
2 Subject: Kernel bug triggered in multipath
5 Starting multipath on a cciss device will cause a kernel
6 warning to be triggered. Problem is that we're using the
7 ->queuedata field of the request_queue to derefence the
8 scsi device; however, for other (non-SCSI) devices this
9 points to a totally different structure.
10 So we should rather be using accessors here which make
11 sure we're only returning valid SCSI device structures.
13 Signed-off-by: Hannes Reinecke <hare@suse.de>
16 drivers/scsi/device_handler/scsi_dh.c | 10 +++++-----
17 drivers/scsi/scsi_lib.c | 11 +++++++++++
18 include/scsi/scsi_device.h | 1 +
19 3 files changed, 17 insertions(+), 5 deletions(-)
21 --- a/drivers/scsi/device_handler/scsi_dh.c
22 +++ b/drivers/scsi/device_handler/scsi_dh.c
23 @@ -427,7 +427,7 @@ int scsi_dh_activate(struct request_queu
24 struct scsi_device_handler *scsi_dh = NULL;
26 spin_lock_irqsave(q->queue_lock, flags);
27 - sdev = q->queuedata;
28 + sdev = scsi_device_from_queue(q);
29 if (sdev && sdev->scsi_dh_data)
30 scsi_dh = sdev->scsi_dh_data->scsi_dh;
31 if (!scsi_dh || !get_device(&sdev->sdev_gendev))
32 @@ -456,7 +456,7 @@ int scsi_dh_handler_exist(const char *na
33 EXPORT_SYMBOL_GPL(scsi_dh_handler_exist);
36 - * scsi_dh_handler_attach - Attach device handler
37 + * scsi_dh_attach - Attach device handler
38 * @sdev - sdev the handler should be attached to
39 * @name - name of the handler to attach
41 @@ -472,7 +472,7 @@ int scsi_dh_attach(struct request_queue
44 spin_lock_irqsave(q->queue_lock, flags);
45 - sdev = q->queuedata;
46 + sdev = scsi_device_from_queue(q);
47 if (!sdev || !get_device(&sdev->sdev_gendev))
49 spin_unlock_irqrestore(q->queue_lock, flags);
50 @@ -487,7 +487,7 @@ int scsi_dh_attach(struct request_queue
51 EXPORT_SYMBOL_GPL(scsi_dh_attach);
54 - * scsi_dh_handler_detach - Detach device handler
55 + * scsi_dh_detach - Detach device handler
56 * @sdev - sdev the handler should be detached from
58 * This function will detach the device handler only
59 @@ -501,7 +501,7 @@ void scsi_dh_detach(struct request_queue
60 struct scsi_device_handler *scsi_dh = NULL;
62 spin_lock_irqsave(q->queue_lock, flags);
63 - sdev = q->queuedata;
64 + sdev = scsi_device_from_queue(q);
65 if (!sdev || !get_device(&sdev->sdev_gendev))
67 spin_unlock_irqrestore(q->queue_lock, flags);
68 --- a/drivers/scsi/scsi_lib.c
69 +++ b/drivers/scsi/scsi_lib.c
70 @@ -1696,6 +1696,17 @@ static void scsi_request_fn(struct reque
71 spin_lock_irq(q->queue_lock);
74 +struct scsi_device *scsi_device_from_queue(struct request_queue *q)
76 + struct scsi_device *sdev = NULL;
78 + if (q->request_fn == scsi_request_fn)
79 + sdev = q->queuedata;
83 +EXPORT_SYMBOL_GPL(scsi_device_from_queue);
85 u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
87 struct device *host_dev;
88 --- a/include/scsi/scsi_device.h
89 +++ b/include/scsi/scsi_device.h
90 @@ -291,6 +291,7 @@ extern void starget_for_each_device(stru
91 extern void __starget_for_each_device(struct scsi_target *, void *,
92 void (*fn)(struct scsi_device *,
94 +extern struct scsi_device *scsi_device_from_queue(struct request_queue *);
96 /* only exposed to implement shost_for_each_device */
97 extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *,