scsi: fix sense_slab/bio swapping livelock
[sfrench/cifs-2.6.git] / drivers / scsi / scsi.c
index fecba05b4e7783da1c22402080c7ab0c6338504b..c78b836f59dd33bac178a41a1dfc11f3d2209ad4 100644 (file)
@@ -181,6 +181,18 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
        cmd = kmem_cache_alloc(shost->cmd_pool->cmd_slab,
                               gfp_mask | shost->cmd_pool->gfp_mask);
 
+       if (likely(cmd)) {
+               buf = kmem_cache_alloc(shost->cmd_pool->sense_slab,
+                                      gfp_mask | shost->cmd_pool->gfp_mask);
+               if (likely(buf)) {
+                       memset(cmd, 0, sizeof(*cmd));
+                       cmd->sense_buffer = buf;
+               } else {
+                       kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
+                       cmd = NULL;
+               }
+       }
+
        if (unlikely(!cmd)) {
                unsigned long flags;
 
@@ -197,16 +209,6 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask)
                        memset(cmd, 0, sizeof(*cmd));
                        cmd->sense_buffer = buf;
                }
-       } else {
-               buf = kmem_cache_alloc(shost->cmd_pool->sense_slab,
-                                      gfp_mask | shost->cmd_pool->gfp_mask);
-               if (likely(buf)) {
-                       memset(cmd, 0, sizeof(*cmd));
-                       cmd->sense_buffer = buf;
-               } else {
-                       kmem_cache_free(shost->cmd_pool->cmd_slab, cmd);
-                       cmd = NULL;
-               }
        }
 
        return cmd;
@@ -757,7 +759,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
                                "Notifying upper driver of completion "
                                "(result %x)\n", cmd->result));
 
-       good_bytes = scsi_bufflen(cmd);
+       good_bytes = scsi_bufflen(cmd) + cmd->request->extra_len;
         if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
                drv = scsi_cmd_to_driver(cmd);
                if (drv->done)