aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorXiaotian Feng <xtfeng@gmail.com>2012-12-04 06:33:54 -0500
committerTejun Heo <tj@kernel.org>2012-12-04 10:29:47 -0500
commitc1d390d8e6128b050f0f66b1c33d390760deb3f4 (patch)
treeedbdf78f783da84eeacb7041a8b64d3096ce1f81 /drivers
parent8852aac25e79e38cc6529f20298eed154f60b574 (diff)
megaraid: fix BUG_ON() from incorrect use of delayed work
megaraid use INIT_WORK to declare a hotplug_work, but cast the hotplug_work from work_struct to delayed_work and schedule_delayed_work on it. This is very dangerous, as other part of delayed_work might be kernel memories allocated by others. With commit 8852aac ("workqueue: mod_delayed_work_on() shouldn't queue timer on 0 delay"), schedule_delayed_work() will check dwork->timer before queue_work even when @delay is 0, this causes megaraid code to hit the BUG_ON() in workqueue code. Change megaraid code to use delayed work. Signed-off-by: Xiaotian Feng <dannyfeng@tencent.com> Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Neela Syam Kolli <megaraidlinux@lsi.com> Cc: "James E.J. Bottomley" <JBottomley@parallels.com> Cc: linux-scsi@vger.kernel.org
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c14
2 files changed, 7 insertions, 9 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 16b7a72a70c4..3b2365c8eab2 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1276,7 +1276,7 @@ struct megasas_evt_detail {
1276} __attribute__ ((packed)); 1276} __attribute__ ((packed));
1277 1277
1278struct megasas_aen_event { 1278struct megasas_aen_event {
1279 struct work_struct hotplug_work; 1279 struct delayed_work hotplug_work;
1280 struct megasas_instance *instance; 1280 struct megasas_instance *instance;
1281}; 1281};
1282 1282
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index d2c5366aff7f..e4f2baacf1e1 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -2060,9 +2060,9 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
2060 } else { 2060 } else {
2061 ev->instance = instance; 2061 ev->instance = instance;
2062 instance->ev = ev; 2062 instance->ev = ev;
2063 INIT_WORK(&ev->hotplug_work, megasas_aen_polling); 2063 INIT_DELAYED_WORK(&ev->hotplug_work,
2064 schedule_delayed_work( 2064 megasas_aen_polling);
2065 (struct delayed_work *)&ev->hotplug_work, 0); 2065 schedule_delayed_work(&ev->hotplug_work, 0);
2066 } 2066 }
2067 } 2067 }
2068} 2068}
@@ -4352,8 +4352,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
4352 /* cancel the delayed work if this work still in queue */ 4352 /* cancel the delayed work if this work still in queue */
4353 if (instance->ev != NULL) { 4353 if (instance->ev != NULL) {
4354 struct megasas_aen_event *ev = instance->ev; 4354 struct megasas_aen_event *ev = instance->ev;
4355 cancel_delayed_work_sync( 4355 cancel_delayed_work_sync(&ev->hotplug_work);
4356 (struct delayed_work *)&ev->hotplug_work);
4357 instance->ev = NULL; 4356 instance->ev = NULL;
4358 } 4357 }
4359 4358
@@ -4545,8 +4544,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
4545 /* cancel the delayed work if this work still in queue*/ 4544 /* cancel the delayed work if this work still in queue*/
4546 if (instance->ev != NULL) { 4545 if (instance->ev != NULL) {
4547 struct megasas_aen_event *ev = instance->ev; 4546 struct megasas_aen_event *ev = instance->ev;
4548 cancel_delayed_work_sync( 4547 cancel_delayed_work_sync(&ev->hotplug_work);
4549 (struct delayed_work *)&ev->hotplug_work);
4550 instance->ev = NULL; 4548 instance->ev = NULL;
4551 } 4549 }
4552 4550
@@ -5190,7 +5188,7 @@ static void
5190megasas_aen_polling(struct work_struct *work) 5188megasas_aen_polling(struct work_struct *work)
5191{ 5189{
5192 struct megasas_aen_event *ev = 5190 struct megasas_aen_event *ev =
5193 container_of(work, struct megasas_aen_event, hotplug_work); 5191 container_of(work, struct megasas_aen_event, hotplug_work.work);
5194 struct megasas_instance *instance = ev->instance; 5192 struct megasas_instance *instance = ev->instance;
5195 union megasas_evt_class_locale class_locale; 5193 union megasas_evt_class_locale class_locale;
5196 struct Scsi_Host *host; 5194 struct Scsi_Host *host;