FS-Cache: Fix lock misorder in fscache_write_op()
[safe/jmp/linux-2.6] / drivers / scsi / scsi_error.c
index ad6a137..1b0060b 100644 (file)
@@ -382,9 +382,13 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
                 * who knows?  FIXME(eric)
                 */
                return SUCCESS;
+       case RESERVATION_CONFLICT:
+               /*
+                * let issuer deal with this, it could be just fine
+                */
+               return SUCCESS;
        case BUSY:
        case QUEUE_FULL:
-       case RESERVATION_CONFLICT:
        default:
                return FAILED;
        }
@@ -641,9 +645,9 @@ EXPORT_SYMBOL(scsi_eh_prep_cmnd);
 /**
  * scsi_eh_restore_cmnd  - Restore a scsi command info as part of error recory
  * @scmd:       SCSI command structure to restore
- * @ses:        saved information from a coresponding call to scsi_prep_eh_cmnd
+ * @ses:        saved information from a coresponding call to scsi_eh_prep_cmnd
  *
- * Undo any damage done by above scsi_prep_eh_cmnd().
+ * Undo any damage done by above scsi_eh_prep_cmnd().
  */
 void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
 {
@@ -721,6 +725,9 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
                case NEEDS_RETRY:
                case FAILED:
                        break;
+               case ADD_TO_MLQUEUE:
+                       rtn = NEEDS_RETRY;
+                       break;
                default:
                        rtn = FAILED;
                        break;
@@ -1441,41 +1448,48 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
        }
 }
 
+static void eh_lock_door_done(struct request *req, int uptodate)
+{
+       __blk_put_request(req->q, req);
+}
+
 /**
  * scsi_eh_lock_door - Prevent medium removal for the specified device
  * @sdev:      SCSI device to prevent medium removal
  *
  * Locking:
- *     We must be called from process context; scsi_allocate_request()
- *     may sleep.
+ *     We must be called from process context.
  *
  * Notes:
  *     We queue up an asynchronous "ALLOW MEDIUM REMOVAL" request on the
  *     head of the devices request queue, and continue.
- *
- * Bugs:
- *     scsi_allocate_request() may sleep waiting for existing requests to
- *     be processed.  However, since we haven't kicked off any request
- *     processing for this host, this may deadlock.
- *
- *     If scsi_allocate_request() fails for what ever reason, we
- *     completely forget to lock the door.
  */
 static void scsi_eh_lock_door(struct scsi_device *sdev)
 {
-       unsigned char cmnd[MAX_COMMAND_SIZE];
+       struct request *req;
+
+       /*
+        * blk_get_request with GFP_KERNEL (__GFP_WAIT) sleeps until a
+        * request becomes available
+        */
+       req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL);
 
-       cmnd[0] = ALLOW_MEDIUM_REMOVAL;
-       cmnd[1] = 0;
-       cmnd[2] = 0;
-       cmnd[3] = 0;
-       cmnd[4] = SCSI_REMOVAL_PREVENT;
-       cmnd[5] = 0;
+       req->cmd[0] = ALLOW_MEDIUM_REMOVAL;
+       req->cmd[1] = 0;
+       req->cmd[2] = 0;
+       req->cmd[3] = 0;
+       req->cmd[4] = SCSI_REMOVAL_PREVENT;
+       req->cmd[5] = 0;
 
-       scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ,
-                          5, NULL, NULL, GFP_KERNEL);
-}
+       req->cmd_len = COMMAND_SIZE(req->cmd[0]);
 
+       req->cmd_type = REQ_TYPE_BLOCK_PC;
+       req->cmd_flags |= REQ_QUIET;
+       req->timeout = 10 * HZ;
+       req->retries = 5;
+
+       blk_execute_rq_nowait(req->q, NULL, req, 1, eh_lock_door_done);
+}
 
 /**
  * scsi_restart_operations - restart io operations to the specified host.