lkml.org 
[lkml]   [2011]   [May]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH-v2 3/4] target: Fix bug with task_sg chained transport_free_dev_tasks release
    Date
    From: Nicholas Bellinger <nab@linux-iscsi.org>

    This patch addresses a bug in the target core release path for HW
    operation where transport_free_dev_tasks() was incorrectly being called
    from transport_lun_remove_cmd() while releasing a se_cmd reference and
    calling struct target_core_fabric_ops->queue_data_in().

    This would result in a OOPs with HW target mode when the release of
    se_task->task_sg[] would happen before pci_unmap_sg() can be called in
    HW target mode fabric module code. This patch addresses the issue by
    moving transport_free_dev_tasks() from transport_lun_remove_cmd() into
    transport_generic_free_cmd(), and adding TRANSPORT_FREE_CMD_INTR and
    transport_generic_free_cmd_intr() to allow se_cmd descriptor release
    to happen fromfrom within transport_processing_thread() process context
    when release of se_cmd is not possible from HW interrupt context.

    Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
    ---
    drivers/target/target_core_transport.c | 13 ++++++++++++-
    include/target/target_core_base.h | 1 +
    include/target/target_core_transport.h | 1 +
    3 files changed, 14 insertions(+), 1 deletions(-)

    diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
    index fefe10a..3eeb3e2 100644
    --- a/drivers/target/target_core_transport.c
    +++ b/drivers/target/target_core_transport.c
    @@ -762,7 +762,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd)
    transport_all_task_dev_remove_state(cmd);
    spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);

    - transport_free_dev_tasks(cmd);

    check_lun:
    spin_lock_irqsave(&lun->lun_cmd_lock, flags);
    @@ -2058,6 +2057,13 @@ int transport_generic_handle_tmr(
    }
    EXPORT_SYMBOL(transport_generic_handle_tmr);

    +void transport_generic_free_cmd_intr(
    + struct se_cmd *cmd)
    +{
    + transport_add_cmd_to_queue(cmd, TRANSPORT_FREE_CMD_INTR);
    +}
    +EXPORT_SYMBOL(transport_generic_free_cmd_intr);
    +
    static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
    {
    struct se_task *task, *task_tmp;
    @@ -5301,6 +5307,8 @@ void transport_generic_free_cmd(
    if (wait_for_tasks && cmd->transport_wait_for_tasks)
    cmd->transport_wait_for_tasks(cmd, 0, 0);

    + transport_free_dev_tasks(cmd);
    +
    transport_generic_remove(cmd, release_to_pool,
    session_reinstatement);
    }
    @@ -6136,6 +6144,9 @@ get_cmd:
    case TRANSPORT_REMOVE:
    transport_generic_remove(cmd, 1, 0);
    break;
    + case TRANSPORT_FREE_CMD_INTR:
    + transport_generic_free_cmd(cmd, 0, 1, 0);
    + break;
    case TRANSPORT_PROCESS_TMR:
    transport_generic_do_tmr(cmd);
    break;
    diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
    index 1d3b5b2..561ac99 100644
    --- a/include/target/target_core_base.h
    +++ b/include/target/target_core_base.h
    @@ -98,6 +98,7 @@ enum transport_state_table {
    TRANSPORT_REMOVE = 14,
    TRANSPORT_FREE = 15,
    TRANSPORT_NEW_CMD_MAP = 16,
    + TRANSPORT_FREE_CMD_INTR = 17,
    };

    /* Used for struct se_cmd->se_cmd_flags */
    diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h
    index 59aa464..24a1c6c 100644
    --- a/include/target/target_core_transport.h
    +++ b/include/target/target_core_transport.h
    @@ -172,6 +172,7 @@ extern int transport_generic_handle_cdb_map(struct se_cmd *);
    extern int transport_generic_handle_data(struct se_cmd *);
    extern void transport_new_cmd_failure(struct se_cmd *);
    extern int transport_generic_handle_tmr(struct se_cmd *);
    +extern void transport_generic_free_cmd_intr(struct se_cmd *);
    extern void __transport_stop_task_timer(struct se_task *, unsigned long *);
    extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]);
    extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32,
    --
    1.7.5.1


    \
     
     \ /
      Last update: 2011-05-11 20:57    [W:0.058 / U:0.044 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site