Re: [PATCH 07/33] target: Introduce a function that shows the command state

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2017-05-23 at 16:48 -0700, Bart Van Assche wrote:
> Introduce target_show_cmd() and use it where appropriate. 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_tmr.c       |  18 ++---
>  drivers/target/target_core_transport.c | 121 +++++++++++++++++++++++++++++----
>  include/target/target_core_fabric.h    |   1 +
>  3 files changed, 113 insertions(+), 27 deletions(-)
> 

I'm crazy about this patch, but not so much about the memory
allocations.

> diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
> index 33bb2a16ce75..cfe69c1fc879 100644
> --- a/drivers/target/target_core_transport.c
> +++ b/drivers/target/target_core_transport.c
> @@ -2653,6 +2647,107 @@ 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";
> +	case TRANSPORT_COMPLETE_QF_ERR:	return "COMPLETE_QF_ERR";
> +	}
> +
> +	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);
> +}

Let's avoid doing memory allocations, since the failure path it not
handled at all.

> +
> +/*
> + * 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;
> +}
> +

Yeah, find a way to do this without memory allocations for every state
bit.

> +void target_show_cmd(const char *pfx, struct se_cmd *cmd)
> +{
> +	char *ts_str = target_ts_to_str(cmd->transport_state);
> +	const u8 *cdb = cmd->t_task_cdb;
> +	struct se_tmr_req *tmf = cmd->se_tmr_req;
> +
> +	if (!(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
> +		pr_debug("%scmd %#02x:%#02x with tag %#llx dir %s i_state %d t_state %s len %d refcnt %d transport_state %s\n",
> +			 pfx, cdb[0], cdb[1], cmd->tag,
> +			 data_dir_name(cmd->data_direction),
> +			 cmd->se_tfo->get_cmd_state(cmd),
> +			 cmd_state_name(cmd->t_state), cmd->data_length,
> +			 kref_read(&cmd->cmd_kref), ts_str);
> +	else
> +		pr_debug("%stmf %s with tag %#llx ref_task_tag %#llx i_state %d t_state %s refcnt %d transport_state %s\n",
> +			 pfx, target_tmf_name(tmf->function), cmd->tag,
> +			 tmf->ref_task_tag, cmd->se_tfo->get_cmd_state(cmd),
> +			 cmd_state_name(cmd->t_state),
> +			 kref_read(&cmd->cmd_kref), ts_str);
> +	kfree(ts_str);

Missing brackets for multi-line conditionals.

> +}
> +EXPORT_SYMBOL(target_show_cmd);
> +
>  /* target_sess_cmd_list_set_waiting - Flag all commands in
>   *         sess_cmd_list to complete cmd_wait_comp.  Set
>   *         sess_tearing_down so no more commands are queued.
> @@ -2797,13 +2892,13 @@ __transport_wait_for_tasks(struct se_cmd *cmd, bool fabric_stop,
>  
>  	cmd->transport_state |= CMD_T_STOP;
>  
> -	pr_debug("wait_for_tasks: Stopping %p ITT: 0x%08llx i_state: %d,"
> -		 " t_state: %d, CMD_T_STOP\n", cmd, cmd->tag,
> -		 cmd->se_tfo->get_cmd_state(cmd), cmd->t_state);
> +	target_show_cmd("wait_for_tasks: Stopping ", cmd);
>  
>  	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("wait for tasks: ", cmd);
>  

Very useful.

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



[Index of Archives]     [Linux SCSI]     [Kernel Newbies]     [Linux SCSI Target Infrastructure]     [Share Photos]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Device Mapper]

  Powered by Linux