diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-05-19 23:19:10 -0400 |
---|---|---|
committer | James Bottomley <jbottomley@parallels.com> | 2011-05-24 12:58:17 -0400 |
commit | 53ab6709b4d35b1924240854d794482fd7d33d4a (patch) | |
tree | 9a1b10d03d4c6aa91076dd6ea55a3874f0db590c /drivers/target | |
parent | 97868c8905a1537153d406c4a3aa39a503a5c299 (diff) |
[SCSI] target: Fix interrupt context bug with stats_lock and core_tmr_alloc_req
This patch fixes two bugs wrt to the interrupt context usage of target
core with HW target mode drivers. It first converts the usage of struct
se_device->stats_lock in transport_get_lun_for_cmd() and core_tmr_lun_reset()
to properly use spin_lock_irq() to address an BUG with CONFIG_LOCKDEP_SUPPORT=y
enabled.
This patch also adds a 'in_interrupt()' check to allow GFP_ATOMIC usage from
core_tmr_alloc_req() to fix a 'sleeping in interrupt context' BUG with HW
target fabrics that require this logic to function.
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Cc: stable@kernel.org
Signed-off-by: James Bottomley <jbottomley@parallels.com>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/target_core_device.c | 4 | ||||
-rw-r--r-- | drivers/target/target_core_tmr.c | 7 |
2 files changed, 6 insertions, 5 deletions
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index d25e20829012..fc10ed4ac493 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
@@ -150,13 +150,13 @@ out: | |||
150 | 150 | ||
151 | { | 151 | { |
152 | struct se_device *dev = se_lun->lun_se_dev; | 152 | struct se_device *dev = se_lun->lun_se_dev; |
153 | spin_lock(&dev->stats_lock); | 153 | spin_lock_irq(&dev->stats_lock); |
154 | dev->num_cmds++; | 154 | dev->num_cmds++; |
155 | if (se_cmd->data_direction == DMA_TO_DEVICE) | 155 | if (se_cmd->data_direction == DMA_TO_DEVICE) |
156 | dev->write_bytes += se_cmd->data_length; | 156 | dev->write_bytes += se_cmd->data_length; |
157 | else if (se_cmd->data_direction == DMA_FROM_DEVICE) | 157 | else if (se_cmd->data_direction == DMA_FROM_DEVICE) |
158 | dev->read_bytes += se_cmd->data_length; | 158 | dev->read_bytes += se_cmd->data_length; |
159 | spin_unlock(&dev->stats_lock); | 159 | spin_unlock_irq(&dev->stats_lock); |
160 | } | 160 | } |
161 | 161 | ||
162 | /* | 162 | /* |
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 4a109835e420..59b8b9c5ad72 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c | |||
@@ -55,7 +55,8 @@ struct se_tmr_req *core_tmr_alloc_req( | |||
55 | { | 55 | { |
56 | struct se_tmr_req *tmr; | 56 | struct se_tmr_req *tmr; |
57 | 57 | ||
58 | tmr = kmem_cache_zalloc(se_tmr_req_cache, GFP_KERNEL); | 58 | tmr = kmem_cache_zalloc(se_tmr_req_cache, (in_interrupt()) ? |
59 | GFP_ATOMIC : GFP_KERNEL); | ||
59 | if (!(tmr)) { | 60 | if (!(tmr)) { |
60 | printk(KERN_ERR "Unable to allocate struct se_tmr_req\n"); | 61 | printk(KERN_ERR "Unable to allocate struct se_tmr_req\n"); |
61 | return ERR_PTR(-ENOMEM); | 62 | return ERR_PTR(-ENOMEM); |
@@ -398,9 +399,9 @@ int core_tmr_lun_reset( | |||
398 | printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n"); | 399 | printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n"); |
399 | } | 400 | } |
400 | 401 | ||
401 | spin_lock(&dev->stats_lock); | 402 | spin_lock_irq(&dev->stats_lock); |
402 | dev->num_resets++; | 403 | dev->num_resets++; |
403 | spin_unlock(&dev->stats_lock); | 404 | spin_unlock_irq(&dev->stats_lock); |
404 | 405 | ||
405 | DEBUG_LR("LUN_RESET: %s for [%s] Complete\n", | 406 | DEBUG_LR("LUN_RESET: %s for [%s] Complete\n", |
406 | (preempt_and_abort_list) ? "Preempt" : "TMR", | 407 | (preempt_and_abort_list) ? "Preempt" : "TMR", |