Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Mar 2019 21:58:49 +0000 (14:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Mar 2019 21:58:49 +0000 (14:58 -0700)
Pull SCSI fixes from James Bottomley:
 "Thirteen fixes, seven of which are for IBM fibre channel and three
  additional for fairly serious bugs in drivers (qla2xxx, mpt3sas,
  aacraid).

  Of the three core fixes, the most significant is probably the missed
  run queue causing an indefinite hang. The others are fixing a
  potential use after free on device close and silencing an incorrect
  warning"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: ibmvfc: Clean up transport events
  scsi: ibmvfc: Byte swap status and error codes when logging
  scsi: ibmvfc: Add failed PRLI to cmd_status lookup array
  scsi: ibmvfc: Remove "failed" from logged errors
  scsi: zfcp: reduce flood of fcrscn1 trace records on multi-element RSCN
  scsi: zfcp: fix scsi_eh host reset with port_forced ERP for non-NPIV FCP devices
  scsi: zfcp: fix rport unblock if deleted SCSI devices on Scsi_Host
  scsi: sd: Quiesce warning if device does not report optimal I/O size
  scsi: sd: Fix a race between closing an sd device and sd I/O
  scsi: core: Run queue when state is set to running after being blocked
  scsi: qla4xxx: fix a potential NULL pointer dereference
  scsi: aacraid: Insure we don't access PCIe space during AER/EEH
  scsi: mpt3sas: Fix kernel panic during expander reset

13 files changed:
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fc.c
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commsup.c
drivers/scsi/ibmvscsi/ibmvfc.c
drivers/scsi/ibmvscsi/ibmvfc.h
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sd.c

index 744a64680d5b0d16c982012bfe2b351becd54a9a..e8fc28dba8dfc3521532c3c87d26d199b8ed9b6c 100644 (file)
@@ -624,6 +624,20 @@ static void zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action)
        add_timer(&erp_action->timer);
 }
 
+void zfcp_erp_port_forced_reopen_all(struct zfcp_adapter *adapter,
+                                    int clear, char *dbftag)
+{
+       unsigned long flags;
+       struct zfcp_port *port;
+
+       write_lock_irqsave(&adapter->erp_lock, flags);
+       read_lock(&adapter->port_list_lock);
+       list_for_each_entry(port, &adapter->port_list, list)
+               _zfcp_erp_port_forced_reopen(port, clear, dbftag);
+       read_unlock(&adapter->port_list_lock);
+       write_unlock_irqrestore(&adapter->erp_lock, flags);
+}
+
 static void _zfcp_erp_port_reopen_all(struct zfcp_adapter *adapter,
                                      int clear, char *dbftag)
 {
@@ -1341,6 +1355,9 @@ static void zfcp_erp_try_rport_unblock(struct zfcp_port *port)
                struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
                int lun_status;
 
+               if (sdev->sdev_state == SDEV_DEL ||
+                   sdev->sdev_state == SDEV_CANCEL)
+                       continue;
                if (zsdev->port != port)
                        continue;
                /* LUN under port of interest */
index 3fce47b0b21b55142a64bb3b838bf28168ddd89e..c6acca521ffec71ee7b3f7e7231a32b18fdceff7 100644 (file)
@@ -70,6 +70,8 @@ extern void zfcp_erp_port_reopen(struct zfcp_port *port, int clear,
                                 char *dbftag);
 extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *);
 extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *);
+extern void zfcp_erp_port_forced_reopen_all(struct zfcp_adapter *adapter,
+                                           int clear, char *dbftag);
 extern void zfcp_erp_set_lun_status(struct scsi_device *, u32);
 extern void zfcp_erp_clear_lun_status(struct scsi_device *, u32);
 extern void zfcp_erp_lun_reopen(struct scsi_device *, int, char *);
index db00b5e3abbe361143c83dc5d6becfaa0e62aac0..33eddb02ee300238897f0f9018119717b387fd58 100644 (file)
@@ -239,10 +239,6 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
        list_for_each_entry(port, &adapter->port_list, list) {
                if ((port->d_id & range) == (ntoh24(page->rscn_fid) & range))
                        zfcp_fc_test_link(port);
-               if (!port->d_id)
-                       zfcp_erp_port_reopen(port,
-                                            ZFCP_STATUS_COMMON_ERP_FAILED,
-                                            "fcrscn1");
        }
        read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }
@@ -250,6 +246,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
 static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
 {
        struct fsf_status_read_buffer *status_buffer = (void *)fsf_req->data;
+       struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fc_els_rscn *head;
        struct fc_els_rscn_page *page;
        u16 i;
@@ -263,6 +260,22 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
        no_entries = be16_to_cpu(head->rscn_plen) /
                sizeof(struct fc_els_rscn_page);
 
+       if (no_entries > 1) {
+               /* handle failed ports */
+               unsigned long flags;
+               struct zfcp_port *port;
+
+               read_lock_irqsave(&adapter->port_list_lock, flags);
+               list_for_each_entry(port, &adapter->port_list, list) {
+                       if (port->d_id)
+                               continue;
+                       zfcp_erp_port_reopen(port,
+                                            ZFCP_STATUS_COMMON_ERP_FAILED,
+                                            "fcrscn1");
+               }
+               read_unlock_irqrestore(&adapter->port_list_lock, flags);
+       }
+
        for (i = 1; i < no_entries; i++) {
                /* skip head and start with 1st element */
                page++;
index f4f6a07c52220234fb0e865ca3f0d87a2d2fdbe0..221d0dfb849329eb5ebf1758004628301b500ba8 100644 (file)
@@ -368,6 +368,10 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
        struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
        int ret = SUCCESS, fc_ret;
 
+       if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE)) {
+               zfcp_erp_port_forced_reopen_all(adapter, 0, "schrh_p");
+               zfcp_erp_wait(adapter);
+       }
        zfcp_erp_adapter_reopen(adapter, 0, "schrh_1");
        zfcp_erp_wait(adapter);
        fc_ret = fc_block_scsi_eh(scpnt);
index 1df5171594b89dc70087def629200c30b4149d1f..11fb68d7e60de6ed5ab388250691b647cbc030bc 100644 (file)
@@ -2640,9 +2640,14 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor)
        return capacity;
 }
 
+static inline int aac_pci_offline(struct aac_dev *dev)
+{
+       return pci_channel_offline(dev->pdev) || dev->handle_pci_error;
+}
+
 static inline int aac_adapter_check_health(struct aac_dev *dev)
 {
-       if (unlikely(pci_channel_offline(dev->pdev)))
+       if (unlikely(aac_pci_offline(dev)))
                return -1;
 
        return (dev)->a_ops.adapter_check_health(dev);
index e67e032936ef015b66c242eaf9c3111cfb3812c2..78430a7b294c6e651024300d86aaec5eecbe53c4 100644 (file)
@@ -672,7 +672,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                                        return -ETIMEDOUT;
                                }
 
-                               if (unlikely(pci_channel_offline(dev->pdev)))
+                               if (unlikely(aac_pci_offline(dev)))
                                        return -EFAULT;
 
                                if ((blink = aac_adapter_check_health(dev)) > 0) {
@@ -772,7 +772,7 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback,
 
                spin_unlock_irqrestore(&fibptr->event_lock, flags);
 
-               if (unlikely(pci_channel_offline(dev->pdev)))
+               if (unlikely(aac_pci_offline(dev)))
                        return -EFAULT;
 
                fibptr->flags |= FIB_CONTEXT_FLAG_WAIT;
index dbaa4f131433abde497c843c17e2b0e677b4544e..3ad997ac351034bd2e556a17c6f9d14addf2921a 100644 (file)
@@ -139,6 +139,7 @@ static const struct {
        { IBMVFC_FC_FAILURE, IBMVFC_VENDOR_SPECIFIC, DID_ERROR, 1, 1, "vendor specific" },
 
        { IBMVFC_FC_SCSI_ERROR, 0, DID_OK, 1, 0, "SCSI error" },
+       { IBMVFC_FC_SCSI_ERROR, IBMVFC_COMMAND_FAILED, DID_ERROR, 0, 1, "PRLI to device failed." },
 };
 
 static void ibmvfc_npiv_login(struct ibmvfc_host *);
@@ -1494,9 +1495,9 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
        if (rsp->flags & FCP_RSP_LEN_VALID)
                rsp_code = rsp->data.info.rsp_code;
 
-       scmd_printk(KERN_ERR, cmnd, "Command (%02X) failed: %s (%x:%x) "
+       scmd_printk(KERN_ERR, cmnd, "Command (%02X) : %s (%x:%x) "
                    "flags: %x fcp_rsp: %x, resid=%d, scsi_status: %x\n",
-                   cmnd->cmnd[0], err, vfc_cmd->status, vfc_cmd->error,
+                   cmnd->cmnd[0], err, be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error),
                    rsp->flags, rsp_code, scsi_get_resid(cmnd), rsp->scsi_status);
 }
 
@@ -2022,7 +2023,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
                sdev_printk(KERN_ERR, sdev, "%s reset failed: %s (%x:%x) "
                            "flags: %x fcp_rsp: %x, scsi_status: %x\n", desc,
                            ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)),
-                           rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code,
+                           be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error), fc_rsp->flags, rsp_code,
                            fc_rsp->scsi_status);
                rsp_rc = -EIO;
        } else
@@ -2381,7 +2382,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
                sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) "
                            "flags: %x fcp_rsp: %x, scsi_status: %x\n",
                            ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)),
-                           rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code,
+                           be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error), fc_rsp->flags, rsp_code,
                            fc_rsp->scsi_status);
                rsp_rc = -EIO;
        } else
@@ -2755,16 +2756,18 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
                ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE);
                if (crq->format == IBMVFC_PARTITION_MIGRATED) {
                        /* We need to re-setup the interpartition connection */
-                       dev_info(vhost->dev, "Re-enabling adapter\n");
+                       dev_info(vhost->dev, "Partition migrated, Re-enabling adapter\n");
                        vhost->client_migrated = 1;
                        ibmvfc_purge_requests(vhost, DID_REQUEUE);
                        ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN);
                        ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_REENABLE);
-               } else {
-                       dev_err(vhost->dev, "Virtual adapter failed (rc=%d)\n", crq->format);
+               } else if (crq->format == IBMVFC_PARTNER_FAILED || crq->format == IBMVFC_PARTNER_DEREGISTER) {
+                       dev_err(vhost->dev, "Host partner adapter deregistered or failed (rc=%d)\n", crq->format);
                        ibmvfc_purge_requests(vhost, DID_ERROR);
                        ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN);
                        ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_RESET);
+               } else {
+                       dev_err(vhost->dev, "Received unknown transport event from partner (rc=%d)\n", crq->format);
                }
                return;
        case IBMVFC_CRQ_CMD_RSP:
@@ -3348,7 +3351,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
 
                tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n",
                        ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
-                       rsp->status, rsp->error, status);
+                       be16_to_cpu(rsp->status), be16_to_cpu(rsp->error), status);
                break;
        }
 
@@ -3446,9 +3449,10 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
                        ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
 
                tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
-                       ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error,
-                       ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), rsp->fc_type,
-                       ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), rsp->fc_explain, status);
+                       ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+                                            be16_to_cpu(rsp->status), be16_to_cpu(rsp->error),
+                       ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), be16_to_cpu(rsp->fc_type),
+                       ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), be16_to_cpu(rsp->fc_explain), status);
                break;
        }
 
@@ -3619,7 +3623,7 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
                fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8;
                tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
                         ibmvfc_get_cmd_error(be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error)),
-                        mad->iu.status, mad->iu.error,
+                        be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error),
                         ibmvfc_get_fc_type(fc_reason), fc_reason,
                         ibmvfc_get_ls_explain(fc_explain), fc_explain, status);
                break;
@@ -3831,9 +3835,10 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
 
                tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
                        ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
-                       rsp->status, rsp->error, ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)),
-                       rsp->fc_type, ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)),
-                       rsp->fc_explain, status);
+                       be16_to_cpu(rsp->status), be16_to_cpu(rsp->error),
+                       ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), be16_to_cpu(rsp->fc_type),
+                       ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)), be16_to_cpu(rsp->fc_explain),
+                       status);
                break;
        }
 
@@ -3959,7 +3964,7 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt)
                level += ibmvfc_retry_host_init(vhost);
                ibmvfc_log(vhost, level, "Discover Targets failed: %s (%x:%x)\n",
                           ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
-                          rsp->status, rsp->error);
+                          be16_to_cpu(rsp->status), be16_to_cpu(rsp->error));
                break;
        case IBMVFC_MAD_DRIVER_FAILED:
                break;
@@ -4024,7 +4029,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
                        ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
                ibmvfc_log(vhost, level, "NPIV Login failed: %s (%x:%x)\n",
                           ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
-                                               rsp->status, rsp->error);
+                                               be16_to_cpu(rsp->status), be16_to_cpu(rsp->error));
                ibmvfc_free_event(evt);
                return;
        case IBMVFC_MAD_CRQ_ERROR:
index b81a53c4a9a8b1020a96a85fd5e84cde2adb9900..459cc288ba1d01abe63c28454bf73c7190bb64a4 100644 (file)
@@ -78,9 +78,14 @@ enum ibmvfc_crq_valid {
        IBMVFC_CRQ_XPORT_EVENT          = 0xFF,
 };
 
-enum ibmvfc_crq_format {
+enum ibmvfc_crq_init_msg {
        IBMVFC_CRQ_INIT                 = 0x01,
        IBMVFC_CRQ_INIT_COMPLETE        = 0x02,
+};
+
+enum ibmvfc_crq_xport_evts {
+       IBMVFC_PARTNER_FAILED           = 0x01,
+       IBMVFC_PARTNER_DEREGISTER       = 0x02,
        IBMVFC_PARTITION_MIGRATED       = 0x06,
 };
 
index e57774472e752013ce762912a6ceec512905fc2a..1d8c584ec1e9197595acf2baa61bccae4305b646 100644 (file)
@@ -3281,12 +3281,18 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 
        if (smid < ioc->hi_priority_smid) {
                struct scsiio_tracker *st;
+               void *request;
 
                st = _get_st_from_smid(ioc, smid);
                if (!st) {
                        _base_recovery_check(ioc);
                        return;
                }
+
+               /* Clear MPI request frame */
+               request = mpt3sas_base_get_msg_frame(ioc, smid);
+               memset(request, 0, ioc->request_sz);
+
                mpt3sas_base_clear_st(ioc, st);
                _base_recovery_check(ioc);
                return;
index 8bb5b8f9f4d2cdbbc127c73cda4d9672b4adcf77..1ccfbc7eebe0323ce88b1c450e52bb87aba3c45e 100644 (file)
@@ -1462,11 +1462,23 @@ mpt3sas_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
        struct scsi_cmnd *scmd = NULL;
        struct scsiio_tracker *st;
+       Mpi25SCSIIORequest_t *mpi_request;
 
        if (smid > 0  &&
            smid <= ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT) {
                u32 unique_tag = smid - 1;
 
+               mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+
+               /*
+                * If SCSI IO request is outstanding at driver level then
+                * DevHandle filed must be non-zero. If DevHandle is zero
+                * then it means that this smid is free at driver level,
+                * so return NULL.
+                */
+               if (!mpi_request->DevHandle)
+                       return scmd;
+
                scmd = scsi_host_find_tag(ioc->shost, unique_tag);
                if (scmd) {
                        st = scsi_cmd_priv(scmd);
index 16a18d5d856f91725b33e25df042eb21bba8c20a..6e4f4931ae175f806731d2fcb1fbb4ba655cc885 100644 (file)
@@ -3203,6 +3203,8 @@ static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session,
        if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
                return -EINVAL;
        ep = iscsi_lookup_endpoint(transport_fd);
+       if (!ep)
+               return -EINVAL;
        conn = cls_conn->dd_data;
        qla_conn = conn->dd_data;
        qla_conn->qla_ep = ep->dd_data;
index 6a9040faed00c93ba5beeda77ffb5b2cbcb6c07e..3b119ca0cc0ce9ba2cfcc95cf78307a96b1d264b 100644 (file)
@@ -771,6 +771,12 @@ store_state_field(struct device *dev, struct device_attribute *attr,
 
        mutex_lock(&sdev->state_mutex);
        ret = scsi_device_set_state(sdev, state);
+       /*
+        * If the device state changes to SDEV_RUNNING, we need to run
+        * the queue to avoid I/O hang.
+        */
+       if (ret == 0 && state == SDEV_RUNNING)
+               blk_mq_run_hw_queues(sdev->request_queue, true);
        mutex_unlock(&sdev->state_mutex);
 
        return ret == 0 ? count : -EINVAL;
index 251db30d0882dc83556a688798c4f277072edefe..2b2bc4b49d78a36c737cd9e70666b900ec0fc2b2 100644 (file)
@@ -1415,11 +1415,6 @@ static void sd_release(struct gendisk *disk, fmode_t mode)
                        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);
 }
 
@@ -3076,6 +3071,9 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp,
        unsigned int opt_xfer_bytes =
                logical_to_bytes(sdp, sdkp->opt_xfer_blocks);
 
+       if (sdkp->opt_xfer_blocks == 0)
+               return false;
+
        if (sdkp->opt_xfer_blocks > dev_max) {
                sd_first_printk(KERN_WARNING, sdkp,
                                "Optimal transfer size %u logical blocks " \
@@ -3505,9 +3503,21 @@ static void scsi_disk_release(struct device *dev)
 {
        struct scsi_disk *sdkp = to_scsi_disk(dev);
        struct gendisk *disk = sdkp->disk;
-       
+       struct request_queue *q = disk->queue;
+
        ida_free(&sd_index_ida, sdkp->index);
 
+       /*
+        * 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);