Re: [PATCH] target: iscsi: handle abort for WRITE_PENDING cmds

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

 



On 7/13/22 3:42 PM, Dmitry Bogdanov wrote:
> Sometimes an initiator does not send data for WRITE commands and tries
> to abort it. The abort hangs waiting for frontend driver completion.
> iSCSI driver waits for for data and that timeout eventually initiates
> connection reinstatment. The connection closing releases the commands in
> the connection, but those aborted commands still did not handle the
> abort and did not decrease a command ref counter. Because of that the
> connection reinstatement hangs indefinitely and prevents re-login for
> that initiator.
> 
> This patch adds a handling in TCM of the abort for the WRITE_PENDING
> commands at connection closing moment to make it possible to release
> them.
> 
> Signed-off-by: Dmitry Bogdanov <d.bogdanov@xxxxxxxxx>
> ---
>  drivers/target/iscsi/iscsi_target.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
> index e368f038ff5c..27eca5e72f52 100644
> --- a/drivers/target/iscsi/iscsi_target.c
> +++ b/drivers/target/iscsi/iscsi_target.c
> @@ -26,6 +26,7 @@
>  #include <target/target_core_base.h>
>  #include <target/target_core_fabric.h>
>  
> +#include <target/target_core_backend.h>
>  #include <target/iscsi/iscsi_target_core.h>
>  #include "iscsi_target_parameters.h"
>  #include "iscsi_target_seq_pdu_list.h"
> @@ -4171,7 +4172,8 @@ static void iscsit_release_commands_from_conn(struct iscsit_conn *conn)
>  
>  		if (se_cmd->se_tfo != NULL) {
>  			spin_lock_irq(&se_cmd->t_state_lock);
> -			if (se_cmd->transport_state & CMD_T_ABORTED) {
> +			if (se_cmd->t_state != TRANSPORT_WRITE_PENDING &&
> +			    se_cmd->transport_state & CMD_T_ABORTED) {
>  				/*
>  				 * LIO's abort path owns the cleanup for this,
>  				 * so put it back on the list and let
> @@ -4191,8 +4193,13 @@ static void iscsit_release_commands_from_conn(struct iscsit_conn *conn)
>  		list_del_init(&cmd->i_conn_node);
>  
>  		iscsit_increment_maxcmdsn(cmd, sess);
> -		iscsit_free_cmd(cmd, true);
> -
> +		if (cmd->se_cmd.t_state == TRANSPORT_WRITE_PENDING &&
> +		    cmd->se_cmd.transport_state & CMD_T_ABORTED) {
> +			/* handle an abort in TCM */
> +			target_complete_cmd(&cmd->se_cmd, SAM_STAT_TASK_ABORTED);
>

Will we have an extra ref left on the se_cmd if TAS is used so the se_cmd
does not get freed?

For TAS, it looks like we would do:

- target_handle_abort -> queue_status. This would not do anything because
before calling iscsit_release_commands_from_conn we have killed the iscsi tx
thread.

- target_handle_abort -> transport_cmd_check_stop_to_fabric -> check_stop_free ->
target_put_sess_cmd.

iscsi creates the se_cmd with TARGET_SCF_ACK_KREF set so do we have one ref
left?

For the non TAS case we do two puts:

target_handle_abort -> SCF_ACK_KREF is set so we do a target_put_sess_cmd here.

target_handle_abort -> transport_cmd_check_stop_to_fabric -> check_stop_free ->
target_put_sess_cmd which does a second put.



[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