Re: [PATCH 17/34] target: Make ABORT and LUN RESET handling synchronous

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

 



On Thu, 2017-01-26 at 09:06 +0100, Hannes Reinecke wrote:
> On 01/26/2017 12:36 AM, Bart Van Assche wrote:
> > Instead of invoking target driver callback functions from the
> > context that handles an abort or LUN RESET task management function,
> > only set the abort flag from that context and perform the actual
> > abort handling from the context of the regular command processing
> > flow. This approach has the following advantages:
> > - The task management function code becomes much easier to read and
> >   to verify since the number of potential race conditions against
> >   the command processing flow is strongly reduced.
> > - It is no longer needed to store the command state into the command
> >   itself since that information is no longer needed from the context
> >   where a task management function is processed.
> > 
> > Notes:
> > - With this patch applied the CMD_T_ABORTED flag is checked at two points
> >   by the target core: just before local execution of a command starts
> >   (see also target_execute_cmd()) and also just before the response is
> >   sent (see also target_complete_cmd()).
> > - Two .release_cmd() calls have been changed into transport_put_cmd()
> >   calls to ensure that the 'finished' completion is set before
> >   .release_cmd() is called.
> > 
> > Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx>
> > Cc: Christoph Hellwig <hch@xxxxxx>
> > Cc: Andy Grover <agrover@xxxxxxxxxx>
> > Cc: David Disseldorp <ddiss@xxxxxxx>
> > ---
> >  drivers/target/target_core_internal.h  |   2 -
> >  drivers/target/target_core_tmr.c       |  73 ++++++++--------
> >  drivers/target/target_core_transport.c | 153 +++++++++++++--------------------
> >  include/target/target_core_base.h      |   2 +
> >  4 files changed, 95 insertions(+), 135 deletions(-)
> > 
> 
> [ .. ]
> >  static int target_check_cdb_and_preempt(struct list_head *list,
> >  		struct se_cmd *cmd)
> >  {
> > @@ -192,13 +173,13 @@ void core_tmr_abort_task(
> >  			continue;
> >  		}
> >  
> > -		list_del_init(&se_cmd->se_cmd_list);
> > +		se_cmd->send_abort_response = false;
> >  		spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
> >  
> > -		cancel_work_sync(&se_cmd->work);
> > -		transport_wait_for_tasks(se_cmd);
> > +		while (!wait_for_completion_timeout(&se_cmd->finished, 180 * HZ))
> > +			pr_debug("ABORT TASK: still waiting for ITT %#llx\n",
> > +				 ref_tag);
> >  
> > -		transport_cmd_finish_abort(se_cmd, true);
> >  		target_put_sess_cmd(se_cmd);
> >  
> >  		printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for"
> 
> What happens if the timeout expires here?
> Can you still call target_put_sess_cmd()?
> And is it valid to return TMR_FUNCTION_COMPLETE, seeing that the
> function most definitely has _not_ completed?
> 
> > @@ -295,14 +276,31 @@ static void core_tmr_drain_tmr_list(
> >  			(preempt_and_abort_list) ? "Preempt" : "", tmr_p,
> >  			tmr_p->function, tmr_p->response, cmd->t_state);
> >  
> > -		cancel_work_sync(&cmd->work);
> > -		transport_wait_for_tasks(cmd);
> > -
> > -		transport_cmd_finish_abort(cmd, 1);
> > +		while (!wait_for_completion_timeout(&cmd->finished, 180 * HZ))
> > +			pr_debug("LUN RESET: still waiting for ITT %#llx\n",
> > +				 cmd->tag);
> >  		target_put_sess_cmd(cmd);
> >  	}
> >  }
> >  
> 
> Same problem as above...
> 
> [ .. ]
> > @@ -387,17 +392,9 @@ static void core_tmr_drain_state_list(
> >  			(cmd->transport_state & CMD_T_STOP) != 0,
> >  			(cmd->transport_state & CMD_T_SENT) != 0);
> >  
> > -		/*
> > -		 * If the command may be queued onto a workqueue cancel it now.
> > -		 *
> > -		 * This is equivalent to removal from the execute queue in the
> > -		 * loop above, but we do it down here given that
> > -		 * cancel_work_sync may block.
> > -		 */
> > -		cancel_work_sync(&cmd->work);
> > -		transport_wait_for_tasks(cmd);
> > -
> > -		core_tmr_handle_tas_abort(cmd, tas);
> > +		while (!wait_for_completion_timeout(&cmd->finished, 180 * HZ))
> > +			pr_debug("LUN RESET: still waiting for cmd with ITT %#llx\n",
> > +				 cmd->tag);
> >  		target_put_sess_cmd(cmd);
> >  	}
> >  }
> 
> And here, too.

Hello Hannes,

If the timeout expires that means that there is a bug in the target driver
through which the SCSI command has been received, namely a reference leak.
The only purpose of the pr_debug() commands in the above three while
(!wait_for_completion_timeout()) loops is to help target driver developers
with debugging such reference leaks.

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