scsi: Suppress a kernel warning in case the prep function returns BLKPREP_DEFER
[sfrench/cifs-2.6.git] / drivers / scsi / scsi_lib.c
index f6097b89d5d381229cc0be0a9753c908de5caa47..ad3ea24f08859fb167e7297c2cacef81d646fb00 100644 (file)
@@ -44,6 +44,8 @@ static struct kmem_cache *scsi_sense_cache;
 static struct kmem_cache *scsi_sense_isadma_cache;
 static DEFINE_MUTEX(scsi_sense_cache_mutex);
 
+static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd);
+
 static inline struct kmem_cache *
 scsi_select_sense_cache(bool unchecked_isa_dma)
 {
@@ -140,6 +142,12 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
 {
        struct scsi_device *sdev = cmd->device;
 
+       if (cmd->request->rq_flags & RQF_DONTPREP) {
+               cmd->request->rq_flags &= ~RQF_DONTPREP;
+               scsi_mq_uninit_cmd(cmd);
+       } else {
+               WARN_ON_ONCE(true);
+       }
        blk_mq_requeue_request(cmd->request, true);
        put_device(&sdev->sdev_gendev);
 }
@@ -627,7 +635,7 @@ static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd)
 static bool scsi_end_request(struct request *req, blk_status_t error,
                unsigned int bytes, unsigned int bidi_bytes)
 {
-       struct scsi_cmnd *cmd = req->special;
+       struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
        struct scsi_device *sdev = cmd->device;
        struct request_queue *q = sdev->request_queue;
 
@@ -642,6 +650,11 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
        if (blk_queue_add_random(q))
                add_disk_randomness(req->rq_disk);
 
+       if (!blk_rq_is_scsi(req)) {
+               WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
+               cmd->flags &= ~SCMD_INITIALIZED;
+       }
+
        if (req->mq_ctx) {
                /*
                 * In the MQ case the command gets freed by __blk_mq_end_request,
@@ -977,8 +990,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                 * A new command will be prepared and issued.
                 */
                if (q->mq_ops) {
-                       cmd->request->rq_flags &= ~RQF_DONTPREP;
-                       scsi_mq_uninit_cmd(cmd);
                        scsi_mq_requeue_cmd(cmd);
                } else {
                        scsi_release_buffers(cmd);
@@ -1107,15 +1118,23 @@ err_exit:
 EXPORT_SYMBOL(scsi_init_io);
 
 /**
- * scsi_initialize_rq - initialize struct scsi_cmnd.req
+ * scsi_initialize_rq - initialize struct scsi_cmnd partially
+ * @rq: Request associated with the SCSI command to be initialized.
  *
- * Called from inside blk_get_request().
+ * This function initializes the members of struct scsi_cmnd that must be
+ * initialized before request processing starts and that won't be
+ * reinitialized if a SCSI command is requeued.
+ *
+ * Called from inside blk_get_request() for pass-through requests and from
+ * inside scsi_init_command() for filesystem requests.
  */
 void scsi_initialize_rq(struct request *rq)
 {
        struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
        scsi_req_init(&cmd->req);
+       cmd->jiffies_at_alloc = jiffies;
+       cmd->retries = 0;
 }
 EXPORT_SYMBOL(scsi_initialize_rq);
 
@@ -1153,8 +1172,18 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
 {
        void *buf = cmd->sense_buffer;
        void *prot = cmd->prot_sdb;
-       unsigned int unchecked_isa_dma = cmd->flags & SCMD_UNCHECKED_ISA_DMA;
+       struct request *rq = blk_mq_rq_from_pdu(cmd);
+       unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS;
+       unsigned long jiffies_at_alloc;
+       int retries;
+
+       if (!blk_rq_is_scsi(rq) && !(flags & SCMD_INITIALIZED)) {
+               flags |= SCMD_INITIALIZED;
+               scsi_initialize_rq(rq);
+       }
 
+       jiffies_at_alloc = cmd->jiffies_at_alloc;
+       retries = cmd->retries;
        /* zero out the cmd, except for the embedded scsi_request */
        memset((char *)cmd + sizeof(cmd->req), 0,
                sizeof(*cmd) - sizeof(cmd->req) + dev->host->hostt->cmd_size);
@@ -1162,16 +1191,17 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd)
        cmd->device = dev;
        cmd->sense_buffer = buf;
        cmd->prot_sdb = prot;
-       cmd->flags = unchecked_isa_dma;
+       cmd->flags = flags;
        INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler);
-       cmd->jiffies_at_alloc = jiffies;
+       cmd->jiffies_at_alloc = jiffies_at_alloc;
+       cmd->retries = retries;
 
        scsi_add_cmd_to_list(cmd);
 }
 
 static int scsi_setup_scsi_cmnd(struct scsi_device *sdev, struct request *req)
 {
-       struct scsi_cmnd *cmd = req->special;
+       struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
 
        /*
         * Passthrough requests may transfer data, in which case they must
@@ -1202,7 +1232,7 @@ static int scsi_setup_scsi_cmnd(struct scsi_device *sdev, struct request *req)
  */
 static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 {
-       struct scsi_cmnd *cmd = req->special;
+       struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
 
        if (unlikely(sdev->handler && sdev->handler->prep_fn)) {
                int ret = sdev->handler->prep_fn(sdev, req);
@@ -1217,7 +1247,7 @@ static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
 
 static int scsi_setup_cmnd(struct scsi_device *sdev, struct request *req)
 {
-       struct scsi_cmnd *cmd = req->special;
+       struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
 
        if (!blk_rq_bytes(req))
                cmd->sc_data_direction = DMA_NONE;
@@ -1354,7 +1384,7 @@ out:
 
 static void scsi_unprep_fn(struct request_queue *q, struct request *req)
 {
-       scsi_uninit_cmd(req->special);
+       scsi_uninit_cmd(blk_mq_rq_to_pdu(req));
 }
 
 /*
@@ -1545,7 +1575,7 @@ static int scsi_lld_busy(struct request_queue *q)
  */
 static void scsi_kill_request(struct request *req, struct request_queue *q)
 {
-       struct scsi_cmnd *cmd = req->special;
+       struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);
        struct scsi_device *sdev;
        struct scsi_target *starget;
        struct Scsi_Host *shost;
@@ -1576,7 +1606,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
 
 static void scsi_softirq_done(struct request *rq)
 {
-       struct scsi_cmnd *cmd = rq->special;
+       struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
        unsigned long wait_for = (cmd->allowed + 1) * rq->timeout;
        int disposition;
 
@@ -1764,8 +1794,8 @@ static void scsi_request_fn(struct request_queue *q)
                        blk_start_request(req);
 
                spin_unlock_irq(q->queue_lock);
-               cmd = req->special;
-               if (unlikely(cmd == NULL)) {
+               cmd = blk_mq_rq_to_pdu(req);
+               if (cmd != req->special) {
                        printk(KERN_CRIT "impossible request in %s.\n"
                                         "please mail a stack trace to "
                                         "linux-scsi@vger.kernel.org\n",
@@ -2001,8 +2031,8 @@ static enum blk_eh_timer_return scsi_timeout(struct request *req,
        return scsi_times_out(req);
 }
 
-static int scsi_init_request(struct blk_mq_tag_set *set, struct request *rq,
-               unsigned int hctx_idx, unsigned int numa_node)
+static int scsi_mq_init_request(struct blk_mq_tag_set *set, struct request *rq,
+                               unsigned int hctx_idx, unsigned int numa_node)
 {
        struct Scsi_Host *shost = set->driver_data;
        const bool unchecked_isa_dma = shost->unchecked_isa_dma;
@@ -2026,8 +2056,8 @@ static int scsi_init_request(struct blk_mq_tag_set *set, struct request *rq,
        return 0;
 }
 
-static void scsi_exit_request(struct blk_mq_tag_set *set, struct request *rq,
-               unsigned int hctx_idx)
+static void scsi_mq_exit_request(struct blk_mq_tag_set *set, struct request *rq,
+                                unsigned int hctx_idx)
 {
        struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
@@ -2104,7 +2134,8 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
 }
 EXPORT_SYMBOL_GPL(__scsi_init_queue);
 
-static int scsi_init_rq(struct request_queue *q, struct request *rq, gfp_t gfp)
+static int scsi_old_init_rq(struct request_queue *q, struct request *rq,
+                           gfp_t gfp)
 {
        struct Scsi_Host *shost = q->rq_alloc_data;
        const bool unchecked_isa_dma = shost->unchecked_isa_dma;
@@ -2134,7 +2165,7 @@ fail:
        return -ENOMEM;
 }
 
-static void scsi_exit_rq(struct request_queue *q, struct request *rq)
+static void scsi_old_exit_rq(struct request_queue *q, struct request *rq)
 {
        struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
@@ -2144,7 +2175,7 @@ static void scsi_exit_rq(struct request_queue *q, struct request *rq)
                               cmd->sense_buffer);
 }
 
-struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
+struct request_queue *scsi_old_alloc_queue(struct scsi_device *sdev)
 {
        struct Scsi_Host *shost = sdev->host;
        struct request_queue *q;
@@ -2155,8 +2186,8 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
        q->cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size;
        q->rq_alloc_data = shost;
        q->request_fn = scsi_request_fn;
-       q->init_rq_fn = scsi_init_rq;
-       q->exit_rq_fn = scsi_exit_rq;
+       q->init_rq_fn = scsi_old_init_rq;
+       q->exit_rq_fn = scsi_old_exit_rq;
        q->initialize_rq_fn = scsi_initialize_rq;
 
        if (blk_init_allocated_queue(q) < 0) {
@@ -2180,8 +2211,8 @@ static const struct blk_mq_ops scsi_mq_ops = {
 #ifdef CONFIG_BLK_DEBUG_FS
        .show_rq        = scsi_show_rq,
 #endif
-       .init_request   = scsi_init_request,
-       .exit_request   = scsi_exit_request,
+       .init_request   = scsi_mq_init_request,
+       .exit_request   = scsi_mq_exit_request,
        .initialize_rq_fn = scsi_initialize_rq,
        .map_queues     = scsi_map_queues,
 };
@@ -2547,7 +2578,7 @@ EXPORT_SYMBOL(scsi_test_unit_ready);
  *     @sdev:  scsi device to change the state of.
  *     @state: state to change to.
  *
- *     Returns zero if unsuccessful or an error if the requested 
+ *     Returns zero if successful or an error if the requested
  *     transition is illegal.
  */
 int
@@ -2654,6 +2685,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
 
        }
        sdev->sdev_state = state;
+       sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state");
        return 0;
 
  illegal:
@@ -3073,19 +3105,26 @@ int scsi_internal_device_unblock_nowait(struct scsi_device *sdev,
         * Try to transition the scsi device to SDEV_RUNNING or one of the
         * offlined states and goose the device queue if successful.
         */
-       if ((sdev->sdev_state == SDEV_BLOCK) ||
-           (sdev->sdev_state == SDEV_TRANSPORT_OFFLINE))
+       switch (sdev->sdev_state) {
+       case SDEV_BLOCK:
+       case SDEV_TRANSPORT_OFFLINE:
                sdev->sdev_state = new_state;
-       else if (sdev->sdev_state == SDEV_CREATED_BLOCK) {
+               sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state");
+               break;
+       case SDEV_CREATED_BLOCK:
                if (new_state == SDEV_TRANSPORT_OFFLINE ||
                    new_state == SDEV_OFFLINE)
                        sdev->sdev_state = new_state;
                else
                        sdev->sdev_state = SDEV_CREATED;
-       } else if (sdev->sdev_state != SDEV_CANCEL &&
-                sdev->sdev_state != SDEV_OFFLINE)
+               sysfs_notify(&sdev->sdev_gendev.kobj, NULL, "state");
+               break;
+       case SDEV_CANCEL:
+       case SDEV_OFFLINE:
+               break;
+       default:
                return -EINVAL;
-
+       }
        scsi_start_queue(sdev);
 
        return 0;
@@ -3262,8 +3301,8 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
 {
        u8 cur_id_type = 0xff;
        u8 cur_id_size = 0;
-       unsigned char *d, *cur_id_str;
-       unsigned char __rcu *vpd_pg83;
+       const unsigned char *d, *cur_id_str;
+       const struct scsi_vpd *vpd_pg83;
        int id_size = -EINVAL;
 
        rcu_read_lock();
@@ -3294,8 +3333,8 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len)
        }
 
        memset(id, 0, id_len);
-       d = vpd_pg83 + 4;
-       while (d < vpd_pg83 + sdev->vpd_pg83_len) {
+       d = vpd_pg83->data + 4;
+       while (d < vpd_pg83->data + vpd_pg83->len) {
                /* Skip designators not referring to the LUN */
                if ((d[1] & 0x30) != 0x00)
                        goto next_desig;
@@ -3411,8 +3450,8 @@ EXPORT_SYMBOL(scsi_vpd_lun_id);
  */
 int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
 {
-       unsigned char *d;
-       unsigned char __rcu *vpd_pg83;
+       const unsigned char *d;
+       const struct scsi_vpd *vpd_pg83;
        int group_id = -EAGAIN, rel_port = -1;
 
        rcu_read_lock();
@@ -3422,8 +3461,8 @@ int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
                return -ENXIO;
        }
 
-       d = sdev->vpd_pg83 + 4;
-       while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
+       d = vpd_pg83->data + 4;
+       while (d < vpd_pg83->data + vpd_pg83->len) {
                switch (d[1] & 0xf) {
                case 0x4:
                        /* Relative target port */