Skip to content

Commit

Permalink
[SCSI] target: Fix t_transport_aborted handling in LUN_RESET + active…
Browse files Browse the repository at this point in the history
… 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>
  • Loading branch information
Nicholas Bellinger authored and James Bottomley committed Feb 28, 2011
1 parent 493f335 commit 52208ae
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 2 deletions.
5 changes: 5 additions & 0 deletions drivers/target/target_core_tmr.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ int core_tmr_lun_reset(

atomic_set(&task->task_active, 0);
atomic_set(&task->task_stop, 0);
} else {
if (atomic_read(&task->task_execute_queue) != 0)
transport_remove_task_from_execute_queue(task, dev);
}
__transport_stop_task_timer(task, &flags);

Expand All @@ -301,6 +304,7 @@ int core_tmr_lun_reset(
DEBUG_LR("LUN_RESET: got t_transport_active = 1 for"
" task: %p, t_fe_count: %d dev: %p\n", task,
fe_count, dev);
atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock,
flags);
core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
Expand All @@ -310,6 +314,7 @@ int core_tmr_lun_reset(
}
DEBUG_LR("LUN_RESET: Got t_transport_active = 0 for task: %p,"
" t_fe_count: %d dev: %p\n", task, fe_count, dev);
atomic_set(&T_TASK(cmd)->t_transport_aborted, 1);
spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);

Expand Down
8 changes: 6 additions & 2 deletions drivers/target/target_core_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,7 @@ transport_get_task_from_execute_queue(struct se_device *dev)
*
*
*/
static void transport_remove_task_from_execute_queue(
void transport_remove_task_from_execute_queue(
struct se_task *task,
struct se_device *dev)
{
Expand Down Expand Up @@ -5549,7 +5549,8 @@ static void transport_generic_wait_for_tasks(

atomic_set(&T_TASK(cmd)->transport_lun_stop, 0);
}
if (!atomic_read(&T_TASK(cmd)->t_transport_active))
if (!atomic_read(&T_TASK(cmd)->t_transport_active) ||
atomic_read(&T_TASK(cmd)->t_transport_aborted))
goto remove;

atomic_set(&T_TASK(cmd)->t_transport_stop, 1);
Expand Down Expand Up @@ -5956,6 +5957,9 @@ static void transport_processing_shutdown(struct se_device *dev)

atomic_set(&task->task_active, 0);
atomic_set(&task->task_stop, 0);
} else {
if (atomic_read(&task->task_execute_queue) != 0)
transport_remove_task_from_execute_queue(task, dev);
}
__transport_stop_task_timer(task, &flags);

Expand Down
2 changes: 2 additions & 0 deletions include/target/target_core_transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ extern void transport_complete_task(struct se_task *, int);
extern void transport_add_task_to_execute_queue(struct se_task *,
struct se_task *,
struct se_device *);
extern void transport_remove_task_from_execute_queue(struct se_task *,
struct se_device *);
unsigned char *transport_dump_cmd_direction(struct se_cmd *);
extern void transport_dump_dev_state(struct se_device *, char *, int *);
extern void transport_dump_dev_info(struct se_device *, struct se_lun *,
Expand Down

0 comments on commit 52208ae

Please sign in to comment.