lkml.org 
[lkml]   [2019]   [Apr]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 108/131] scsi: sd: Fix a race between closing an sd device and sd I/O
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

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

    From: Bart Van Assche <bvanassche@acm.org>

    commit c14a57264399efd39514a2329c591a4b954246d8 upstream.

    The scsi_end_request() function calls scsi_cmd_to_driver() indirectly and
    hence needs the disk->private_data pointer. Avoid that that pointer is
    cleared before all affected I/O requests have finished. This patch avoids
    that the following crash occurs:

    Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
    Call trace:
    scsi_mq_uninit_cmd+0x1c/0x30
    scsi_end_request+0x7c/0x1b8
    scsi_io_completion+0x464/0x668
    scsi_finish_command+0xbc/0x160
    scsi_eh_flush_done_q+0x10c/0x170
    sas_scsi_recover_host+0x84c/0xa98 [libsas]
    scsi_error_handler+0x140/0x5b0
    kthread+0x100/0x12c
    ret_from_fork+0x10/0x18

    Cc: Christoph Hellwig <hch@lst.de>
    Cc: Ming Lei <ming.lei@redhat.com>
    Cc: Hannes Reinecke <hare@suse.com>
    Cc: Johannes Thumshirn <jthumshirn@suse.de>
    Cc: Jason Yan <yanaijie@huawei.com>
    Cc: <stable@vger.kernel.org>
    Signed-off-by: Bart Van Assche <bvanassche@acm.org>
    Reported-by: Jason Yan <yanaijie@huawei.com>
    Reviewed-by: Christoph Hellwig <hch@lst.de>
    Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/scsi/sd.c | 19 +++++++++++++------
    1 file changed, 13 insertions(+), 6 deletions(-)

    --- a/drivers/scsi/sd.c
    +++ b/drivers/scsi/sd.c
    @@ -1276,11 +1276,6 @@ static void sd_release(struct gendisk *d
    scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW);
    }

    - /*
    - * XXX and what if there are packets in flight and this close()
    - * XXX is followed by a "rmmod sd_mod"?
    - */
    -
    scsi_disk_put(sdkp);
    }

    @@ -3227,11 +3222,23 @@ static void scsi_disk_release(struct dev
    {
    struct scsi_disk *sdkp = to_scsi_disk(dev);
    struct gendisk *disk = sdkp->disk;
    -
    + struct request_queue *q = disk->queue;
    +
    spin_lock(&sd_index_lock);
    ida_remove(&sd_index_ida, sdkp->index);
    spin_unlock(&sd_index_lock);

    + /*
    + * Wait until all requests that are in progress have completed.
    + * This is necessary to avoid that e.g. scsi_end_request() crashes
    + * due to clearing the disk->private_data pointer. Wait from inside
    + * scsi_disk_release() instead of from sd_release() to avoid that
    + * freezing and unfreezing the request queue affects user space I/O
    + * in case multiple processes open a /dev/sd... node concurrently.
    + */
    + blk_mq_freeze_queue(q);
    + blk_mq_unfreeze_queue(q);
    +
    disk->private_data = NULL;
    put_disk(disk);
    put_device(&sdkp->device->sdev_gendev);

    \
     
     \ /
      Last update: 2019-04-01 19:44    [W:5.951 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site