Commit 91173b0c authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds

[PATCH] disk barriers: scsi

scsi bits
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5e9dbcaa
......@@ -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,6 +1351,7 @@ 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);
......
......@@ -113,6 +113,7 @@ static int sd_remove(struct device *);
static void sd_shutdown(struct device *dev);
static void sd_rescan(struct device *);
static int sd_init_command(struct scsi_cmnd *);
static int sd_issue_flush(struct device *, sector_t *);
static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
struct scsi_request *SRpnt, unsigned char *buffer);
......@@ -126,6 +127,7 @@ static struct scsi_driver sd_template = {
},
.rescan = sd_rescan,
.init_command = sd_init_command,
.issue_flush = sd_issue_flush,
};
/* Device no to disk mapping:
......@@ -676,6 +678,62 @@ static int sd_media_changed(struct gendisk *disk)
return 1;
}
static int sd_sync_cache(struct scsi_device *sdp)
{
struct scsi_request *sreq;
int retries, res;
if (!scsi_device_online(sdp))
return -ENODEV;
sreq = scsi_allocate_request(sdp, GFP_KERNEL);
if (!sreq) {
printk("FAILED\n No memory for request\n");
return -ENOMEM;
}
sreq->sr_data_direction = DMA_NONE;
for (retries = 3; retries > 0; --retries) {
unsigned char cmd[10] = { 0 };
cmd[0] = SYNCHRONIZE_CACHE;
/*
* Leave the rest of the command zero to indicate
* flush everything.
*/
scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
if (sreq->sr_result == 0)
break;
}
res = sreq->sr_result;
if (res) {
printk(KERN_WARNING "FAILED\n status = %x, message = %02x, "
"host = %d, driver = %02x\n ",
status_byte(res), msg_byte(res),
host_byte(res), driver_byte(res));
if (driver_byte(res) & DRIVER_SENSE)
scsi_print_req_sense("sd", sreq);
}
scsi_release_request(sreq);
return res;
}
static int sd_issue_flush(struct device *dev, sector_t *error_sector)
{
struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp = dev_get_drvdata(dev);
if (!sdkp)
return -ENODEV;
if (!sdkp->WCE)
return 0;
return sd_sync_cache(sdp);
}
static void sd_rescan(struct device *dev)
{
struct scsi_disk *sdkp = dev_get_drvdata(dev);
......@@ -1503,52 +1561,17 @@ static void scsi_disk_release(struct kref *kref)
static void sd_shutdown(struct device *dev)
{
struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp;
struct scsi_request *sreq;
int retries, res;
struct scsi_disk *sdkp = dev_get_drvdata(dev);
sdkp = dev_get_drvdata(dev);
if (!sdkp)
return; /* this can happen */
if (!scsi_device_online(sdp) || !sdkp->WCE)
if (!sdkp->WCE)
return;
printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ",
printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
sdkp->disk->disk_name);
sreq = scsi_allocate_request(sdp, GFP_KERNEL);
if (!sreq) {
printk("FAILED\n No memory for request\n");
return;
}
sreq->sr_data_direction = DMA_NONE;
for (retries = 3; retries > 0; --retries) {
unsigned char cmd[10] = { 0 };
cmd[0] = SYNCHRONIZE_CACHE;
/*
* Leave the rest of the command zero to indicate
* flush everything.
*/
scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES);
if (sreq->sr_result == 0)
break;
}
res = sreq->sr_result;
if (res) {
printk(KERN_WARNING "FAILED\n status = %x, message = %02x, "
"host = %d, driver = %02x\n ",
status_byte(res), msg_byte(res),
host_byte(res), driver_byte(res));
if (driver_byte(res) & DRIVER_SENSE)
scsi_print_req_sense("sd", sreq);
}
scsi_release_request(sreq);
printk("\n");
sd_sync_cache(sdp);
}
/**
......
......@@ -13,6 +13,7 @@ struct scsi_driver {
int (*init_command)(struct scsi_cmnd *);
void (*rescan)(struct device *);
int (*issue_flush)(struct device *, sector_t *);
};
#define to_scsi_driver(drv) \
container_of((drv), struct scsi_driver, gendrv)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment