diff --git a/scst/include/scst.h b/scst/include/scst.h index 24a510ff6..95c7b18d9 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -360,11 +360,14 @@ enum scst_exec_context { /* Set if the cmd is aborted by other initiator */ #define SCST_CMD_ABORTED_OTHER 1 +/* Set if the cmd is aborted and counted in cmd_done_wait_count */ +#define SCST_CMD_DONE_COUNTED 2 + /* Set if no response should be sent to the target about this cmd */ -#define SCST_CMD_NO_RESP 2 +#define SCST_CMD_NO_RESP 3 /* Set if the cmd is dead and can be destroyed at any time */ -#define SCST_CMD_CAN_BE_DESTROYED 3 +#define SCST_CMD_CAN_BE_DESTROYED 4 /************************************************************* ** Tgt_dev's async. flags (tgt_dev_flags) @@ -386,10 +389,6 @@ enum scst_exec_context { #define SCST_TGT_DEV_CLUST_POOL 11 -#ifdef CONFIG_SCST_DEBUG_TM -#define SCST_TGT_DEV_UNDER_TM_DBG 20 -#endif - /************************************************************* ** Name of the entry in /proc *************************************************************/ diff --git a/scst/src/Makefile b/scst/src/Makefile index bd9fe746f..665575420 100644 --- a/scst/src/Makefile +++ b/scst/src/Makefile @@ -128,7 +128,7 @@ EXTRA_CFLAGS += -DCONFIG_SCST_EXTRACHECKS #EXTRA_CFLAGS += -DCONFIG_SCST_TRACING EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG -g -#EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG_TM -UCONFIG_SCST_TM_DBG_GO_OFFLINE +#EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG_TM -DCONFIG_SCST_TM_DBG_GO_OFFLINE #EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG_RETRY #EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG_OOM #EXTRA_CFLAGS += -DCONFIG_SCST_DEBUG_SN diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 021d7eee2..8195a310a 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -3594,7 +3594,7 @@ static int tm_dbg_passed_cmds_count; static int tm_dbg_state; static int tm_dbg_on_state_passes; static DEFINE_TIMER(tm_dbg_timer, tm_dbg_timer_fn, 0, 0); -static wait_queue_head_t *tm_dbg_p_cmd_list_waitQ; +struct scst_tgt_dev *tm_dbg_tgt_dev; static const int tm_dbg_on_state_num_passes[] = { 5, 1, 0x7ffffff }; @@ -3603,29 +3603,35 @@ static void tm_dbg_init_tgt_dev(struct scst_tgt_dev *tgt_dev, { if ((acg_dev->acg == scst_default_acg) && (acg_dev->lun == 0)) { unsigned long flags; + + if (tm_dbg_tgt_dev != NULL) + tm_dbg_deinit_tgt_dev(tm_dbg_tgt_dev); + /* Do TM debugging only for LUN 0 */ spin_lock_irqsave(&scst_tm_dbg_lock, flags); - tm_dbg_p_cmd_list_waitQ = - &tgt_dev->dev->p_cmd_lists->cmd_list_waitQ; tm_dbg_state = INIT_TM_DBG_STATE; tm_dbg_on_state_passes = tm_dbg_on_state_num_passes[tm_dbg_state]; - __set_bit(SCST_TGT_DEV_UNDER_TM_DBG, &tgt_dev->tgt_dev_flags); + tm_dbg_tgt_dev = tgt_dev; PRINT_INFO("LUN 0 connected from initiator %s is under " - "TM debugging", tgt_dev->sess->tgt->tgtt->name); + "TM debugging (tgt_dev %p)", + tgt_dev->sess->initiator_name, tgt_dev); spin_unlock_irqrestore(&scst_tm_dbg_lock, flags); } + return; } static void tm_dbg_deinit_tgt_dev(struct scst_tgt_dev *tgt_dev) { - if (test_bit(SCST_TGT_DEV_UNDER_TM_DBG, &tgt_dev->tgt_dev_flags)) { + if (tm_dbg_tgt_dev == tgt_dev) { unsigned long flags; + TRACE_MGMT_DBG("Deinit TM debugging tgt_dev %p", tgt_dev); del_timer_sync(&tm_dbg_timer); spin_lock_irqsave(&scst_tm_dbg_lock, flags); - tm_dbg_p_cmd_list_waitQ = NULL; + tm_dbg_tgt_dev = NULL; spin_unlock_irqrestore(&scst_tm_dbg_lock, flags); } + return; } static void tm_dbg_timer_fn(unsigned long arg) @@ -3634,7 +3640,8 @@ static void tm_dbg_timer_fn(unsigned long arg) tm_dbg_flags.tm_dbg_release = 1; /* Used to make sure that all woken up threads see the new value */ smp_wmb(); - wake_up_all(tm_dbg_p_cmd_list_waitQ); + wake_up_all(&tm_dbg_tgt_dev->dev->p_cmd_lists->cmd_list_waitQ); + return; } /* Called under scst_tm_dbg_lock and IRQs off */ @@ -3714,8 +3721,7 @@ static void tm_dbg_change_state(void) case TM_DBG_STATE_ABORT: TRACE_MGMT_DBG("%s", "Changing " "tm_dbg_state to RESET"); - tm_dbg_state = - TM_DBG_STATE_RESET; + tm_dbg_state = TM_DBG_STATE_RESET; tm_dbg_flags.tm_dbg_blocked = 0; break; case TM_DBG_STATE_RESET: @@ -3723,13 +3729,11 @@ static void tm_dbg_change_state(void) #ifdef CONFIG_SCST_TM_DBG_GO_OFFLINE TRACE_MGMT_DBG("%s", "Changing " "tm_dbg_state to OFFLINE"); - tm_dbg_state = - TM_DBG_STATE_OFFLINE; + tm_dbg_state = TM_DBG_STATE_OFFLINE; #else TRACE_MGMT_DBG("%s", "Changing " "tm_dbg_state to ABORT"); - tm_dbg_state = - TM_DBG_STATE_ABORT; + tm_dbg_state = TM_DBG_STATE_ABORT; #endif break; default: @@ -3740,7 +3744,8 @@ static void tm_dbg_change_state(void) } TRACE_MGMT_DBG("%s", "Deleting timer"); - del_timer(&tm_dbg_timer); + del_timer_sync(&tm_dbg_timer); + return; } /* No locks */ @@ -3764,8 +3769,7 @@ int tm_dbg_check_cmd(struct scst_cmd *cmd) (tm_dbg_state == TM_DBG_STATE_ABORT)) tm_dbg_change_state(); spin_unlock_irqrestore(&scst_tm_dbg_lock, flags); - } else if (cmd->tgt_dev && test_bit(SCST_TGT_DEV_UNDER_TM_DBG, - &cmd->tgt_dev->tgt_dev_flags)) { + } else if (cmd->tgt_dev && (tm_dbg_tgt_dev == cmd->tgt_dev)) { /* Delay 50th command */ spin_lock_irqsave(&scst_tm_dbg_lock, flags); if (tm_dbg_flags.tm_dbg_blocked || @@ -3816,6 +3820,7 @@ void tm_dbg_release_cmd(struct scst_cmd *cmd) } } spin_unlock_irqrestore(&scst_tm_dbg_lock, flags); + return; } /* Might be called under scst_mutex */ @@ -3824,21 +3829,10 @@ void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn, int force) unsigned long flags; if (dev != NULL) { - struct scst_tgt_dev *tgt_dev; - bool found = 0; + if (tm_dbg_tgt_dev == NULL) + goto out; - spin_lock_bh(&dev->dev_lock); - list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list, - dev_tgt_dev_list_entry) { - if (test_bit(SCST_TGT_DEV_UNDER_TM_DBG, - &tgt_dev->tgt_dev_flags)) { - found = 1; - break; - } - } - spin_unlock_bh(&dev->dev_lock); - - if (!found) + if (tm_dbg_tgt_dev->dev != dev) goto out; } @@ -3853,8 +3847,8 @@ void tm_dbg_task_mgmt(struct scst_device *dev, const char *fn, int force) * value. */ smp_wmb(); - if (tm_dbg_p_cmd_list_waitQ != NULL) - wake_up_all(tm_dbg_p_cmd_list_waitQ); + if (tm_dbg_tgt_dev != NULL) + wake_up_all(&tm_dbg_tgt_dev->dev->p_cmd_lists->cmd_list_waitQ); } else { TRACE_MGMT_DBG("%s: while OFFLINE state, doing nothing", fn); } diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 224e63581..a9bd93ca4 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -2087,6 +2087,14 @@ static int scst_exec(struct scst_cmd **active_cmd) int rc; cmd->sent_for_exec = 1; + /* + * To sync with scst_abort_cmd(). The above assignment must + * be before SCST_CMD_ABORTED test, done later in + * scst_check_local_events(). It's far from here, so the order + * is virtually guaranteed, but let's have it just in case. + */ + smp_mb(); + cmd->scst_cmd_done = scst_cmd_done_local; cmd->state = SCST_CMD_STATE_LOCAL_EXEC; @@ -3657,6 +3665,9 @@ void scst_done_cmd_mgmt(struct scst_cmd *cmd) spin_lock_irqsave(&scst_mcmd_lock, flags); + if (!test_bit(SCST_CMD_DONE_COUNTED, &cmd->cmd_flags)) + goto out_unlock; + list_for_each_entry(mstb, &cmd->mgmt_cmd_list, cmd_mgmt_cmd_list_entry) { struct scst_mgmt_cmd *mcmd = mstb->mcmd; @@ -3683,6 +3694,7 @@ void scst_done_cmd_mgmt(struct scst_cmd *cmd) } } +out_unlock: spin_unlock_irqrestore(&scst_mcmd_lock, flags); if (wake) @@ -3928,9 +3940,11 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd, mcmd->cmd_finish_wait_count++; - if (!cmd->done) { - TRACE_MGMT_DBG("cmd %p (tag %llu) not done yet", - cmd, (long long unsigned int)cmd->tag); + if (cmd->sent_for_exec && !cmd->done) { + TRACE_MGMT_DBG("cmd %p (tag %llu) is being executed " + "and not done yet", cmd, + (long long unsigned int)cmd->tag); + set_bit(SCST_CMD_DONE_COUNTED, &cmd->cmd_flags); mcmd->cmd_done_wait_count++; } } @@ -4086,6 +4100,8 @@ static int scst_abort_task_set(struct scst_mgmt_cmd *mcmd) __scst_abort_task_set(mcmd, tgt_dev); + tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "ABORT TASK SET", 0); + scst_unblock_aborted_cmds(0); scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0); @@ -4169,6 +4185,8 @@ static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd) &UA_tgt_devs); } + tm_dbg_task_mgmt(mcmd->mcmd_tgt_dev->dev, "CLEAR TASK SET", 0); + scst_unblock_aborted_cmds(1); mutex_unlock(&scst_mutex); @@ -4505,6 +4523,10 @@ static int scst_abort_all_nexus_loss_sess(struct scst_mgmt_cmd *mcmd, rc = scst_call_dev_task_mgmt_fn(mcmd, tgt_dev, 0); if (rc < 0 && mcmd->status == SCST_MGMT_STATUS_SUCCESS) mcmd->status = rc; + + tm_dbg_task_mgmt(tgt_dev->dev, "NEXUS LOSS SESS or " + "ABORT ALL SESS or UNREG SESS", + (mcmd->fn == SCST_UNREG_SESS_TM)); } } @@ -4584,6 +4606,9 @@ static int scst_abort_all_nexus_loss_tgt(struct scst_mgmt_cmd *mcmd, (mcmd->status == SCST_MGMT_STATUS_SUCCESS)) mcmd->status = rc; } + + tm_dbg_task_mgmt(tgt_dev->dev, "NEXUS LOSS or " + "ABORT ALL", 0); } } }