lkml.org 
[lkml]   [2016]   [Apr]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 111/210] mtip32xx: Cleanup queued requests after surprise removal
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

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

    From: Asai Thambi SP <asamymuthupa@micron.com>

    commit 008e56d200225321371748d95908e6222436f06d upstream.

    Fail all pending requests after surprise removal of a drive.

    Signed-off-by: Vignesh Gunasekaran <vgunasekaran@micron.com>
    Signed-off-by: Selvan Mani <smani@micron.com>
    Signed-off-by: Asai Thambi S P <asamymuthupa@micron.com>
    Signed-off-by: Jens Axboe <axboe@fb.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/block/mtip32xx/mtip32xx.c | 78 +++++++++++++++++++++++++++++---------
    1 file changed, 60 insertions(+), 18 deletions(-)

    --- a/drivers/block/mtip32xx/mtip32xx.c
    +++ b/drivers/block/mtip32xx/mtip32xx.c
    @@ -173,7 +173,13 @@ static struct mtip_cmd *mtip_get_int_com
    {
    struct request *rq;

    + if (mtip_check_surprise_removal(dd->pdev))
    + return NULL;
    +
    rq = blk_mq_alloc_request(dd->queue, 0, __GFP_RECLAIM, true);
    + if (IS_ERR(rq))
    + return NULL;
    +
    return blk_mq_rq_to_pdu(rq);
    }

    @@ -575,6 +581,8 @@ static void mtip_completion(struct mtip_
    dev_warn(&port->dd->pdev->dev,
    "Internal command %d completed with TFE\n", tag);

    + command->comp_func = NULL;
    + command->comp_data = NULL;
    complete(waiting);
    }

    @@ -1009,12 +1017,14 @@ static bool mtip_pause_ncq(struct mtip_p
    *
    * @port Pointer to port data structure
    * @timeout Max duration to wait (ms)
    + * @atomic gfp_t flag to indicate blockable context or not
    *
    * return value
    * 0 Success
    * -EBUSY Commands still active
    */
    -static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
    +static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout,
    + gfp_t atomic)
    {
    unsigned long to;
    unsigned int n;
    @@ -1025,16 +1035,21 @@ static int mtip_quiesce_io(struct mtip_p
    to = jiffies + msecs_to_jiffies(timeout);
    do {
    if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) &&
    - test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
    + test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags) &&
    + atomic == GFP_KERNEL) {
    msleep(20);
    continue; /* svc thd is actively issuing commands */
    }

    - msleep(100);
    + if (atomic == GFP_KERNEL)
    + msleep(100);
    + else {
    + cpu_relax();
    + udelay(100);
    + }
    +
    if (mtip_check_surprise_removal(port->dd->pdev))
    goto err_fault;
    - if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
    - goto err_fault;

    /*
    * Ignore s_active bit 0 of array element 0.
    @@ -1096,6 +1111,10 @@ static int mtip_exec_internal_command(st
    }

    int_cmd = mtip_get_int_command(dd);
    + if (!int_cmd) {
    + dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n");
    + return -EFAULT;
    + }

    set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);

    @@ -1108,7 +1127,7 @@ static int mtip_exec_internal_command(st
    if (fis->command != ATA_CMD_STANDBYNOW1) {
    /* wait for io to complete if non atomic */
    if (mtip_quiesce_io(port,
    - MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) {
    + MTIP_QUIESCE_IO_TIMEOUT_MS, atomic) < 0) {
    dev_warn(&dd->pdev->dev,
    "Failed to quiesce IO\n");
    mtip_put_int_command(dd, int_cmd);
    @@ -3354,10 +3373,6 @@ static int mtip_standby_drive(struct dri
    */
    static int mtip_hw_exit(struct driver_data *dd)
    {
    - /*
    - * Send standby immediate (E0h) to the drive so that it
    - * saves its state.
    - */
    if (!dd->sr) {
    /* de-initialize the port. */
    mtip_deinit_port(dd->port);
    @@ -3974,7 +3989,7 @@ static int mtip_block_initialize(struct
    if (rv) {
    dev_err(&dd->pdev->dev,
    "Unable to allocate request queue\n");
    - goto block_queue_alloc_init_error;
    + goto block_queue_alloc_tag_error;
    }

    /* Allocate the request queue. */
    @@ -4086,8 +4101,9 @@ kthread_run_error:
    read_capacity_error:
    init_hw_cmds_error:
    blk_cleanup_queue(dd->queue);
    - blk_mq_free_tag_set(&dd->tags);
    block_queue_alloc_init_error:
    + blk_mq_free_tag_set(&dd->tags);
    +block_queue_alloc_tag_error:
    mtip_hw_debugfs_exit(dd);
    disk_index_error:
    spin_lock(&rssd_index_lock);
    @@ -4104,6 +4120,22 @@ protocol_init_error:
    return rv;
    }

    +static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv)
    +{
    + struct driver_data *dd = (struct driver_data *)data;
    + struct mtip_cmd *cmd;
    +
    + if (likely(!reserv))
    + blk_mq_complete_request(rq, -ENODEV);
    + else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) {
    +
    + cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
    + if (cmd->comp_func)
    + cmd->comp_func(dd->port, MTIP_TAG_INTERNAL,
    + cmd, -ENODEV);
    + }
    +}
    +
    /*
    * Block layer deinitialization function.
    *
    @@ -4135,12 +4167,23 @@ static int mtip_block_remove(struct driv
    }
    }

    - if (!dd->sr)
    - mtip_standby_drive(dd);
    + if (!dd->sr) {
    + /*
    + * Explicitly wait here for IOs to quiesce,
    + * as mtip_standby_drive usually won't wait for IOs.
    + */
    + if (!mtip_quiesce_io(dd->port, MTIP_QUIESCE_IO_TIMEOUT_MS,
    + GFP_KERNEL))
    + mtip_standby_drive(dd);
    + }
    else
    dev_info(&dd->pdev->dev, "device %s surprise removal\n",
    dd->disk->disk_name);

    + blk_mq_freeze_queue_start(dd->queue);
    + blk_mq_stop_hw_queues(dd->queue);
    + blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd);
    +
    /*
    * Delete our gendisk structure. This also removes the device
    * from /dev
    @@ -4555,16 +4598,15 @@ static void mtip_pci_remove(struct pci_d
    } while (atomic_read(&dd->irq_workers_active) != 0 &&
    time_before(jiffies, to));

    - fsync_bdev(dd->bdev);
    + if (!dd->sr)
    + fsync_bdev(dd->bdev);

    if (atomic_read(&dd->irq_workers_active) != 0) {
    dev_warn(&dd->pdev->dev,
    "Completion workers still active!\n");
    }

    - if (dd->sr)
    - blk_mq_stop_hw_queues(dd->queue);
    -
    + blk_set_queue_dying(dd->queue);
    set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);

    /* Clean up the block layer. */

    \
     
     \ /
      Last update: 2016-04-10 22:21    [W:4.082 / U:0.228 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site