If transport_wait_for_tasks() takes too long, make it show the state of the command it is waiting for. Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx> Cc: Hannes Reinecke <hare@xxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Andy Grover <agrover@xxxxxxxxxx> Cc: David Disseldorp <ddiss@xxxxxxx> --- drivers/target/target_core_internal.h | 1 + drivers/target/target_core_transport.c | 79 +++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 48de996ad28d..86880c6d6c8e 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -148,6 +148,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int); void transport_clear_lun_ref(struct se_lun *); int __target_put_sess_cmd(struct se_cmd *se_cmd); void transport_send_task_abort(struct se_cmd *); +void target_show_cmd(const char *ctxt, struct se_cmd *cmd); sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); void target_qf_do_work(struct work_struct *work); bool target_check_wce(struct se_device *dev); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 27a6df77c078..5e0aaae96817 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2650,6 +2650,81 @@ int target_put_sess_cmd(struct se_cmd *se_cmd) } EXPORT_SYMBOL(target_put_sess_cmd); +static const char *data_dir_name(enum dma_data_direction d) +{ + switch (d) { + case DMA_BIDIRECTIONAL: return "BIDI"; + case DMA_TO_DEVICE: return "WRITE"; + case DMA_FROM_DEVICE: return "READ"; + case DMA_NONE: return "NONE"; + } + + return "(?)"; +} + +static const char *cmd_state_name(enum transport_state_table t) +{ + switch (t) { + case TRANSPORT_NO_STATE: return "NO_STATE"; + case TRANSPORT_NEW_CMD: return "NEW_CMD"; + case TRANSPORT_WRITE_PENDING: return "WRITE_PENDING"; + case TRANSPORT_PROCESSING: return "PROCESSING"; + case TRANSPORT_COMPLETE: return "COMPLETE"; + case TRANSPORT_ISTATE_PROCESSING: + return "ISTATE_PROCESSING"; + case TRANSPORT_COMPLETE_QF_WP: return "COMPLETE_QF_WP"; + case TRANSPORT_COMPLETE_QF_OK: return "COMPLETE_QF_OK"; + } + + return "(?)"; +} + +static void target_append_str(char **str, const char *txt) +{ + char *prev = *str; + + *str = *str ? kasprintf(GFP_ATOMIC, "%s,%s", *str, txt) : + kstrdup(txt, GFP_ATOMIC); + kfree(prev); +} + +/* + * Convert a transport state bitmask into a string. The caller is + * responsible for freeing the returned pointer. + */ +static char *target_ts_to_str(u32 ts) +{ + char *str = NULL; + + if (ts & CMD_T_ABORTED) + target_append_str(&str, "aborted"); + if (ts & CMD_T_ACTIVE) + target_append_str(&str, "active"); + if (ts & CMD_T_COMPLETE) + target_append_str(&str, "complete"); + if (ts & CMD_T_SENT) + target_append_str(&str, "sent"); + if (ts & CMD_T_STOP) + target_append_str(&str, "stop"); + if (ts & CMD_T_FABRIC_STOP) + target_append_str(&str, "fabric_stop"); + + return str; +} + +void target_show_cmd(const char *ctxt, struct se_cmd *cmd) +{ + char *ts_str = target_ts_to_str(cmd->transport_state); + + pr_debug("%s: still waiting for %s with tag %#llx; dir %s i_state %d t_state %s len %d tgt_ref %d refcnt %d transport_state %s\n", + ctxt, cmd->se_cmd_flags & SCF_SCSI_TMR_CDB ? "tmf" : "cmd", + cmd->tag, data_dir_name(cmd->data_direction), + cmd->se_tfo->get_cmd_state(cmd), cmd_state_name(cmd->t_state), + cmd->data_length, atomic_read(&cmd->tgt_ref.refcount), + atomic_read(&cmd->cmd_kref.refcount), ts_str); + kfree(ts_str); +} + /** * target_sess_cmd_list_set_waiting - prevent new commands to be queued * @se_sess: session to flag @@ -2771,7 +2846,9 @@ __transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop, spin_unlock_irqrestore(&cmd->t_state_lock, *flags); - wait_for_completion(&cmd->t_transport_stop_comp); + while (!wait_for_completion_timeout(&cmd->t_transport_stop_comp, + 180 * HZ)) + target_show_cmd(__func__, cmd); spin_lock_irqsave(&cmd->t_state_lock, *flags); cmd->transport_state &= ~(CMD_T_ACTIVE | CMD_T_STOP); -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html