aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-02-24 19:58:20 -0500
committerJames Bottomley <James.Bottomley@suse.de>2011-02-28 12:23:32 -0500
commit52208ae3fc60cbcb214c10fb8b82304199e2cc3a (patch)
treed7c7e938453b257ce49197cb91f64fed1860b254 /drivers/target
parent493f3358cb289ccf716c5a14fa5bb52ab75943e5 (diff)
[SCSI] target: Fix t_transport_aborted handling in LUN_RESET + active I/O shutdown
This patch addresses two outstanding bugs related to T_TASK(cmd)->t_transport_aborted handling during TMR LUN_RESET and active I/O shutdown. This first involves adding two explict t_transport_aborted=1 assignments in core_tmr_lun_reset() in order to signal the task has been aborted, and updating transport_generic_wait_for_tasks() to skip sleeping when t_transport_aborted=1 has been set. This fixes an issue where transport_generic_wait_for_tasks() would end up sleeping indefinately when called from fabric module context while TMR LUN_RESET was happening with long outstanding backend struct se_task not yet being completed. The second adds a missing call to transport_remove_task_from_execute_queue() when task->task_execute_queue=1 is set in order to fix an OOPs when task->t_execute_list has not been dropped. It also fixes the same case in transport_processing_shutdown() to prevent the issue from happening during active I/O struct se_device shutdown. Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_tmr.c5
-rw-r--r--drivers/target/target_core_transport.c8
2 files changed, 11 insertions, 2 deletions
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index 158cecbec718..4a109835e420 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -282,6 +282,9 @@ int core_tmr_lun_reset(
282 282
283 atomic_set(&task->task_active, 0); 283 atomic_set(&task->task_active, 0);
284 atomic_set(&task->task_stop, 0); 284 atomic_set(&task->task_stop, 0);
285 } else {
286 if (atomic_read(&task->task_execute_queue) != 0)
287 transport_remove_task_from_execute_queue(task, dev);
285 } 288 }
286 __transport_stop_task_timer(task, &flags); 289 __transport_stop_task_timer(task, &flags);
287 290
@@ -301,6 +304,7 @@ int core_tmr_lun_reset(
301 DEBUG_LR("LUN_RESET: got t_transport_active = 1 for" 304 DEBUG_LR("LUN_RESET: got t_transport_active = 1 for"
302 " task: %p, t_fe_count: %d dev: %p\n", task, 305 " task: %p, t_fe_count: %d dev: %p\n", task,
303 fe_count, dev); 306 fe_count, dev);
307 atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
304 spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, 308 spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
305 flags); 309 flags);
306 core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); 310 core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
@@ -310,6 +314,7 @@ int core_tmr_lun_reset(
310 } 314 }
311 DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p," 315 DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p,"
312 " t_fe_count: %d dev: %p\n", task, fe_count, dev); 316 " t_fe_count: %d dev: %p\n", task, fe_count, dev);
317 atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
313 spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags); 318 spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
314 core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count); 319 core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
315 320
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 236e22d8cfae..4bbf6c147f89 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1207,7 +1207,7 @@ transport_get_task_from_execute_queue(struct se_device *dev)
1207 * 1207 *
1208 * 1208 *
1209 */ 1209 */
1210static void transport_remove_task_from_execute_queue( 1210void transport_remove_task_from_execute_queue(
1211 struct se_task *task, 1211 struct se_task *task,
1212 struct se_device *dev) 1212 struct se_device *dev)
1213{ 1213{
@@ -5549,7 +5549,8 @@ static void transport_generic_wait_for_tasks(
5549 5549
5550 atomic_set(&T_TASK(cmd)->transport_lun_stop, 0); 5550 atomic_set(&T_TASK(cmd)->transport_lun_stop, 0);
5551 } 5551 }
5552 if (!atomic_read(&T_TASK(cmd)->t_transport_active)) 5552 if (!atomic_read(&T_TASK(cmd)->t_transport_active) ||
5553 atomic_read(&T_TASK(cmd)->t_transport_aborted))
5553 goto remove; 5554 goto remove;
5554 5555
5555 atomic_set(&T_TASK(cmd)->t_transport_stop, 1); 5556 atomic_set(&T_TASK(cmd)->t_transport_stop, 1);
@@ -5956,6 +5957,9 @@ static void transport_processing_shutdown(struct se_device *dev)
5956 5957
5957 atomic_set(&task->task_active, 0); 5958 atomic_set(&task->task_active, 0);
5958 atomic_set(&task->task_stop, 0); 5959 atomic_set(&task->task_stop, 0);
5960 } else {
5961 if (atomic_read(&task->task_execute_queue) != 0)
5962 transport_remove_task_from_execute_queue(task, dev);
5959 } 5963 }
5960 __transport_stop_task_timer(task, &flags); 5964 __transport_stop_task_timer(task, &flags);
5961 5965