Commit 52208ae3fc60cbcb214c10fb8b82304199e2cc3a

Authored by Nicholas Bellinger
Committed by James Bottomley
1 parent 493f3358cb

[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>

Showing 3 changed files with 13 additions and 2 deletions Side-by-side Diff

drivers/target/target_core_tmr.c
... ... @@ -282,6 +282,9 @@
282 282  
283 283 atomic_set(&task->task_active, 0);
284 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 289 __transport_stop_task_timer(task, &flags);
287 290  
... ... @@ -301,6 +304,7 @@
301 304 DEBUG_LR("LUN_RESET: got t_transport_active = 1 for"
302 305 " task: %p, t_fe_count: %d dev: %p\n", task,
303 306 fe_count, dev);
  307 + atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
304 308 spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
305 309 flags);
306 310 core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
... ... @@ -310,6 +314,7 @@
310 314 }
311 315 DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p,"
312 316 " t_fe_count: %d dev: %p\n", task, fe_count, dev);
  317 + atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
313 318 spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
314 319 core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
315 320  
drivers/target/target_core_transport.c
... ... @@ -1207,7 +1207,7 @@
1207 1207 *
1208 1208 *
1209 1209 */
1210   -static void transport_remove_task_from_execute_queue(
  1210 +void transport_remove_task_from_execute_queue(
1211 1211 struct se_task *task,
1212 1212 struct se_device *dev)
1213 1213 {
... ... @@ -5549,7 +5549,8 @@
5549 5549  
5550 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 5554 goto remove;
5554 5555  
5555 5556 atomic_set(&T_TASK(cmd)->t_transport_stop, 1);
... ... @@ -5956,6 +5957,9 @@
5956 5957  
5957 5958 atomic_set(&task->task_active, 0);
5958 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 5964 __transport_stop_task_timer(task, &flags);
5961 5965  
include/target/target_core_transport.h
... ... @@ -135,6 +135,8 @@
135 135 extern void transport_add_task_to_execute_queue(struct se_task *,
136 136 struct se_task *,
137 137 struct se_device *);
  138 +extern void transport_remove_task_from_execute_queue(struct se_task *,
  139 + struct se_device *);
138 140 unsigned char *transport_dump_cmd_direction(struct se_cmd *);
139 141 extern void transport_dump_dev_state(struct se_device *, char *, int *);
140 142 extern void transport_dump_dev_info(struct se_device *, struct se_lun *,