[Bug 151631] "Synchronizing SCSI cache" fails during(and delays) reboot/shutdown

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



https://bugzilla.kernel.org/show_bug.cgi?id=151631

--- Comment #12 from Jesse Stone (fatalfeel@xxxxxxxxxxx) ---
//if under linux 4.12 (include 4.12) add this patch
void __scsi_remove_device(struct scsi_device *sdev)
{
    struct device *dev = &sdev->sdev_gendev;
    int res;
    int ret;

    /*
     * This cleanup path is not reentrant and while it is impossible
     * to get a new reference with scsi_device_get() someone can still
     * hold a previously acquired one.
     */
    if (sdev->sdev_state == SDEV_DEL)
        return;

    if (sdev->is_visible) {
        /*
         * If scsi_internal_target_block() is running concurrently,
         * wait until it has finished before changing the device state.
         */
        mutex_lock(&sdev->state_mutex);
        /*
         * If blocked, we go straight to DEL and restart the queue so
         * any commands issued during driver shutdown (like sync
         * cache) are errored immediately.
         */
        res = scsi_device_set_state(sdev, SDEV_CANCEL);
        //if (res != 0) {
        ret = scsi_device_set_state(sdev, SDEV_DEL);
        if ( !ret )
        {
            scsi_start_queue(sdev);
        }
        //}
        mutex_unlock(&sdev->state_mutex);

        if (res != 0)
            return;

        bsg_unregister_queue(sdev->request_queue);
        device_unregister(&sdev->sdev_dev);
        transport_remove_device(dev);
        scsi_dh_remove_device(sdev);
        device_del(dev);
    } else {
        put_device(&sdev->sdev_dev);
    }

    /*
     * Stop accepting new requests and wait until all queuecommand() and
     * scsi_run_queue() invocations have finished before tearing down the
     * device.
     */
    mutex_lock(&sdev->state_mutex);
    scsi_device_set_state(sdev, SDEV_DEL);
    mutex_unlock(&sdev->state_mutex);

    blk_cleanup_queue(sdev->request_queue);
    cancel_work_sync(&sdev->requeue_work);

    if (sdev->host->hostt->slave_destroy)
    {
        sdev->host->hostt->slave_destroy(sdev);
    }

    transport_destroy_device(dev);

    /*
     * Paired with the kref_get() in scsi_sysfs_initialize().  We have
     * remoed sysfs visibility from the device, so make the target
     * invisible if this was the last device underneath it.
     */
    scsi_target_reap(scsi_target(sdev));

    put_device(dev);
}

//if above linux 4.13 (include 4.13)
void __scsi_remove_device(struct scsi_device *sdev)
{
        struct device *dev = &sdev->sdev_gendev;
        int res;
#ifdef MY_PATCH 
        int ret;
#endif  

        /*
         * This cleanup path is not reentrant and while it is impossible
         * to get a new reference with scsi_device_get() someone can still
         * hold a previously acquired one.
         */
        if (sdev->sdev_state == SDEV_DEL)
                return;

        if (sdev->is_visible) {
                /*
                 * If scsi_internal_target_block() is running concurrently,
                 * wait until it has finished before changing the device state.
                 */
                mutex_lock(&sdev->state_mutex);
                /*
                 * If blocked, we go straight to DEL and restart the queue so
                 * any commands issued during driver shutdown (like sync
                 * cache) are errored immediately.
                 */
                res = scsi_device_set_state(sdev, SDEV_CANCEL);
#ifdef MY_PATCH
                ret = scsi_device_set_state(sdev, SDEV_DEL);
                if ( !ret )
                        scsi_start_queue(sdev);
#else
                if (res != 0) {
                        res = scsi_device_set_state(sdev, SDEV_DEL);
                        if (res == 0)
                                scsi_start_queue(sdev);
                }
#endif          
                mutex_unlock(&sdev->state_mutex);

                if (res != 0)
                        return;

                if (sdev->host->hostt->sdev_groups)
                        sysfs_remove_groups(&sdev->sdev_gendev.kobj,
                                        sdev->host->hostt->sdev_groups);

                bsg_unregister_queue(sdev->request_queue);
                device_unregister(&sdev->sdev_dev);
                transport_remove_device(dev);
                device_del(dev);
        } else
                put_device(&sdev->sdev_dev);

        /*
         * Stop accepting new requests and wait until all queuecommand() and
         * scsi_run_queue() invocations have finished before tearing down the
         * device.
         */
        mutex_lock(&sdev->state_mutex);
        scsi_device_set_state(sdev, SDEV_DEL);
        mutex_unlock(&sdev->state_mutex);

        blk_cleanup_queue(sdev->request_queue);
        cancel_work_sync(&sdev->requeue_work);

        if (sdev->host->hostt->slave_destroy)
                sdev->host->hostt->slave_destroy(sdev);
        transport_destroy_device(dev);

        /*
         * Paired with the kref_get() in scsi_sysfs_initialize().  We have
         * removed sysfs visibility from the device, so make the target
         * invisible if this was the last device underneath it.
         */
        scsi_target_reap(scsi_target(sdev));

        put_device(dev);
}

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are the assignee for the bug.




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux