lkml.org 
[lkml]   [2013]   [Sep]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[082/251] sd: fix crash when UA received on DIF enabled device
    3.6.11.9-rc1 stable review patch.
    If anyone has any objections, please let me know.

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

    From: "Ewan D. Milne" <emilne@redhat.com>

    [ Upstream commit 085b513f97d8d799d28491239be4b451bcd8c2c5 ]

    sd_prep_fn will allocate a larger CDB for the command via mempool_alloc
    for devices using DIF type 2 protection. This CDB was being freed
    in sd_done, which results in a kernel crash if the command is retried
    due to a UNIT ATTENTION. This change moves the code to free the larger
    CDB into sd_unprep_fn instead, which is invoked after the request is
    complete.

    It is no longer necessary to call scsi_print_command separately for
    this case as the ->cmnd will no longer be NULL in the normal code path.

    Also removed conditional test for DIF type 2 when freeing the larger
    CDB because the protection_type could have been changed via sysfs while
    the command was executing.

    Signed-off-by: Ewan D. Milne <emilne@redhat.com>
    Acked-by: Martin K. Petersen <martin.petersen@oracle.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: James Bottomley <JBottomley@Parallels.com>
    Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
    ---
    drivers/scsi/sd.c | 22 +++++++---------------
    1 file changed, 7 insertions(+), 15 deletions(-)

    diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
    index a2ecd324..e157a93 100644
    --- a/drivers/scsi/sd.c
    +++ b/drivers/scsi/sd.c
    @@ -673,10 +673,17 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)

    static void sd_unprep_fn(struct request_queue *q, struct request *rq)
    {
    + struct scsi_cmnd *SCpnt = rq->special;
    +
    if (rq->cmd_flags & REQ_DISCARD) {
    free_page((unsigned long)rq->buffer);
    rq->buffer = NULL;
    }
    + if (SCpnt->cmnd != rq->cmd) {
    + mempool_free(SCpnt->cmnd, sd_cdb_pool);
    + SCpnt->cmnd = NULL;
    + SCpnt->cmd_len = 0;
    + }
    }

    /**
    @@ -1540,21 +1547,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
    if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt))
    sd_dif_complete(SCpnt, good_bytes);

    - if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type)
    - == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) {
    -
    - /* We have to print a failed command here as the
    - * extended CDB gets freed before scsi_io_completion()
    - * is called.
    - */
    - if (result)
    - scsi_print_command(SCpnt);
    -
    - mempool_free(SCpnt->cmnd, sd_cdb_pool);
    - SCpnt->cmnd = NULL;
    - SCpnt->cmd_len = 0;
    - }
    -
    return good_bytes;
    }

    --
    1.7.10.4



    \
     
     \ /
      Last update: 2013-09-12 01:41    [W:6.394 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site