• Roland Dreier's avatar
    target: Fix missing CMD_T_ACTIVE bit regression for pending WRITEs · e627c615
    Roland Dreier authored
    This patch fixes a regression bug introduced during v3.6.x code with
    the following commit to drop transport_add_cmd_to_queue(), which
    originally re-set CMD_T_ACTIVE during pending WRITE I/O submission:
    
    commit af877292
    Author: Christoph Hellwig <hch@infradead.org>
    Date:   Sun Jul 8 15:58:49 2012 -0400
    
        target: replace the processing thread with a TMR work queue
    
    The following sequence happens for write commands (or any other
    commands with a data out phase):
    
     - The transport calls target_submit_cmd(), which sets CMD_T_ACTIVE in
       cmd->transport_state and sets cmd->t_state to TRANSPORT_NEW_CMD.
     - Things go on transport_generic_new_cmd(), which notices that the
       command needs to transfer data, so it sets cmd->t_state to
       TRANSPORT_WRITE_PENDING and calls transport_cmd_check_stop().
     - transport_cmd_check_stop() clears CMD_T_ACTIVE in cmd->transport_state
       and returns in the normal case.
     - Then we continue on to call ->se_tfo->write_pending().
     - The data comes back from the initiator, and the transport calls
       target_execute_cmd(), which sets cmd->t_state to TRANSPORT_PROCESSING
       and calls into the backend to actually write the data.
    
    At this point, the backend might take a long time to complete the
    command, since it has to do real IO.  If an abort request comes in for
    this command at this point, it will not wait for the command to finish
    since CMD_T_ACTIVE is not set.  Then when the command does finally
    finish, we blow up with use-after-free.
    
    Avoid this by setting CMD_T_ACTIVE in target_execute_cmd() so that
    transport_wait_for_tasks() waits for the command to finish executing.
    This matches the behavior from before commit 1389533e ("target:
    remove transport_generic_handle_data"), when data was signaled via
    transport_generic_handle_data(), which set CMD_T_ACTIVE because it
    called transport_add_cmd_to_queue().
    Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
    Reported-by: default avatarMartin Svec <martin.svec@zoner.cz>
    Cc: Christoph Hellwig <hch@lst.de>
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
    e627c615
target_core_transport.c 77.5 KB