lkml.org 
[lkml]   [2016]   [Nov]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 093/346] target: Fix missing complete during ABORT_TASK + CMD_T_FABRIC_STOP
    3.16.39-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Nicholas Bellinger <nab@linux-iscsi.org>

    commit 5e2c956b8aa24d4f33ff7afef92d409eed164746 upstream.

    During transport_generic_free_cmd() with a concurrent TMR
    ABORT_TASK and shutdown CMD_T_FABRIC_STOP bit set, the
    caller will be blocked on se_cmd->cmd_wait_stop completion
    until the final kref_put() -> target_release_cmd_kref()
    has been invoked to call complete().

    However, when ABORT_TASK is completed with FUNCTION_COMPLETE
    in core_tmr_abort_task(), the aborted se_cmd will have already
    been removed from se_sess->sess_cmd_list via list_del_init().

    This results in target_release_cmd_kref() hitting the
    legacy list_empty() == true check, invoking ->release_cmd()
    but skipping complete() to wakeup se_cmd->cmd_wait_stop
    blocked earlier in transport_generic_free_cmd() code.

    To address this bug, it's safe to go ahead and drop the
    original list_empty() check so that fabric_stop invokes
    the complete() as expected, since list_del_init() can
    safely be used on a empty list.

    Cc: Mike Christie <mchristi@redhat.com>
    Cc: Quinn Tran <quinn.tran@qlogic.com>
    Cc: Himanshu Madhani <himanshu.madhani@qlogic.com>
    Cc: Christoph Hellwig <hch@lst.de>
    Cc: Hannes Reinecke <hare@suse.de>
    Tested-by: Nicholas Bellinger <nab@linux-iscsi.org>
    Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
    [bwh: Backported to 3.16: adjust context]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/target/target_core_transport.c | 6 ------
    1 file changed, 6 deletions(-)

    --- a/drivers/target/target_core_transport.c
    +++ b/drivers/target/target_core_transport.c
    @@ -2455,12 +2455,6 @@ static void target_release_cmd_kref(stru
    struct se_session *se_sess = se_cmd->se_sess;
    bool fabric_stop;

    - if (list_empty(&se_cmd->se_cmd_list)) {
    - spin_unlock(&se_sess->sess_cmd_lock);
    - target_free_cmd_mem(se_cmd);
    - se_cmd->se_tfo->release_cmd(se_cmd);
    - return;
    - }

    spin_lock(&se_cmd->t_state_lock);
    fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP);
    \
     
     \ /
      Last update: 2016-11-14 04:52    [W:2.917 / U:0.188 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site