diff options
author | James Bottomley <James.Bottomley@steeleye.com> | 2006-02-14 11:48:46 -0500 |
---|---|---|
committer | <jejb@mulgrave.il.steeleye.com> | 2006-02-14 12:15:11 -0500 |
commit | 65110b2168950a19cc78b5027ed18cb811fbdae8 (patch) | |
tree | 8cdf4fc26b707e0e6ba988fd56da118d3206dceb /drivers/scsi/scsi_sysfs.c | |
parent | faead26d7a06605add627f29aee73ba654ce11f9 (diff) |
[SCSI] fix wrong context bugs in SCSI
There's a bug in releasing scsi_device where the release function
actually frees the block queue. However, the block queue release
calls flush_work(), which requires process context (the scsi_device
structure may release from irq context). Update the release function
to invoke via the execute_in_process_context() API.
Also clean up the scsi_target structure releasing via this API.
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index a77b32deaf8f..902a5def8e62 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -217,8 +217,9 @@ static void scsi_device_cls_release(struct class_device *class_dev) | |||
217 | put_device(&sdev->sdev_gendev); | 217 | put_device(&sdev->sdev_gendev); |
218 | } | 218 | } |
219 | 219 | ||
220 | static void scsi_device_dev_release(struct device *dev) | 220 | static void scsi_device_dev_release_usercontext(void *data) |
221 | { | 221 | { |
222 | struct device *dev = data; | ||
222 | struct scsi_device *sdev; | 223 | struct scsi_device *sdev; |
223 | struct device *parent; | 224 | struct device *parent; |
224 | struct scsi_target *starget; | 225 | struct scsi_target *starget; |
@@ -237,6 +238,7 @@ static void scsi_device_dev_release(struct device *dev) | |||
237 | 238 | ||
238 | if (sdev->request_queue) { | 239 | if (sdev->request_queue) { |
239 | sdev->request_queue->queuedata = NULL; | 240 | sdev->request_queue->queuedata = NULL; |
241 | /* user context needed to free queue */ | ||
240 | scsi_free_queue(sdev->request_queue); | 242 | scsi_free_queue(sdev->request_queue); |
241 | /* temporary expedient, try to catch use of queue lock | 243 | /* temporary expedient, try to catch use of queue lock |
242 | * after free of sdev */ | 244 | * after free of sdev */ |
@@ -252,6 +254,11 @@ static void scsi_device_dev_release(struct device *dev) | |||
252 | put_device(parent); | 254 | put_device(parent); |
253 | } | 255 | } |
254 | 256 | ||
257 | static void scsi_device_dev_release(struct device *dev) | ||
258 | { | ||
259 | scsi_execute_in_process_context(scsi_device_dev_release_usercontext, dev); | ||
260 | } | ||
261 | |||
255 | static struct class sdev_class = { | 262 | static struct class sdev_class = { |
256 | .name = "scsi_device", | 263 | .name = "scsi_device", |
257 | .release = scsi_device_cls_release, | 264 | .release = scsi_device_cls_release, |