vserver 1.9.3
[linux-2.6.git] / drivers / scsi / scsi_lib.c
index e30d3f2..ac16f21 100644 (file)
@@ -954,6 +954,22 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
        return BLKPREP_KILL;
 }
 
+static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
+                              sector_t *error_sector)
+{
+       struct scsi_device *sdev = q->queuedata;
+       struct scsi_driver *drv;
+
+       if (sdev->sdev_state != SDEV_RUNNING)
+               return -ENXIO;
+
+       drv = *(struct scsi_driver **) disk->private_data;
+       if (drv->issue_flush)
+               return drv->issue_flush(&sdev->sdev_gendev, error_sector);
+
+       return -EOPNOTSUPP;
+}
+
 static int scsi_prep_fn(struct request_queue *q, struct request *req)
 {
        struct scsi_device *sdev = q->queuedata;
@@ -1335,7 +1351,8 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
        blk_queue_max_sectors(q, shost->max_sectors);
        blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
        blk_queue_segment_boundary(q, shost->dma_boundary);
+       blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
+
        if (!shost->use_clustering)
                clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
        return q;
@@ -1555,6 +1572,34 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
        return ret;
 }
 
+int
+scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries)
+{
+       struct scsi_request *sreq;
+       char cmd[] = {
+               TEST_UNIT_READY, 0, 0, 0, 0, 0,
+       };
+       int result;
+       
+       sreq = scsi_allocate_request(sdev, GFP_KERNEL);
+       if (!sreq)
+               return -ENOMEM;
+
+               sreq->sr_data_direction = DMA_NONE;
+        scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries);
+
+       if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) &&
+           (sreq->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION &&
+           sdev->removable) {
+               sdev->changed = 1;
+               sreq->sr_result = 0;
+       }
+       result = sreq->sr_result;
+       scsi_release_request(sreq);
+       return result;
+}
+EXPORT_SYMBOL(scsi_test_unit_ready);
+
 /**
  *     scsi_device_set_state - Take the given device through the device
  *             state model.