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) ...@@ -954,6 +954,22 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
return BLKPREP_KILL; 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) static int scsi_prep_fn(struct request_queue *q, struct request *req)
{ {
struct scsi_device *sdev = q->queuedata; struct scsi_device *sdev = q->queuedata;
...@@ -1335,7 +1351,8 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) ...@@ -1335,7 +1351,8 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
blk_queue_max_sectors(q, shost->max_sectors); blk_queue_max_sectors(q, shost->max_sectors);
blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
blk_queue_segment_boundary(q, shost->dma_boundary); blk_queue_segment_boundary(q, shost->dma_boundary);
blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
if (!shost->use_clustering) if (!shost->use_clustering)
clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
return q; return q;
......
...@@ -113,6 +113,7 @@ static int sd_remove(struct device *); ...@@ -113,6 +113,7 @@ static int sd_remove(struct device *);
static void sd_shutdown(struct device *dev); static void sd_shutdown(struct device *dev);
static void sd_rescan(struct device *); static void sd_rescan(struct device *);
static int sd_init_command(struct scsi_cmnd *); 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, static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
struct scsi_request *SRpnt, unsigned char *buffer); struct scsi_request *SRpnt, unsigned char *buffer);
...@@ -126,6 +127,7 @@ static struct scsi_driver sd_template = { ...@@ -126,6 +127,7 @@ static struct scsi_driver sd_template = {
}, },
.rescan = sd_rescan, .rescan = sd_rescan,
.init_command = sd_init_command, .init_command = sd_init_command,
.issue_flush = sd_issue_flush,
}; };
/* Device no to disk mapping: /* Device no to disk mapping:
...@@ -676,6 +678,62 @@ static int sd_media_changed(struct gendisk *disk) ...@@ -676,6 +678,62 @@ static int sd_media_changed(struct gendisk *disk)
return 1; 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) static void sd_rescan(struct device *dev)
{ {
struct scsi_disk *sdkp = dev_get_drvdata(dev); struct scsi_disk *sdkp = dev_get_drvdata(dev);
...@@ -1503,52 +1561,17 @@ static void scsi_disk_release(struct kref *kref) ...@@ -1503,52 +1561,17 @@ static void scsi_disk_release(struct kref *kref)
static void sd_shutdown(struct device *dev) static void sd_shutdown(struct device *dev)
{ {
struct scsi_device *sdp = to_scsi_device(dev); struct scsi_device *sdp = to_scsi_device(dev);
struct scsi_disk *sdkp; struct scsi_disk *sdkp = dev_get_drvdata(dev);
struct scsi_request *sreq;
int retries, res;
sdkp = dev_get_drvdata(dev);
if (!sdkp) if (!sdkp)
return; /* this can happen */ return; /* this can happen */
if (!scsi_device_online(sdp) || !sdkp->WCE) if (!sdkp->WCE)
return; return;
printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: ", printk(KERN_NOTICE "Synchronizing SCSI cache for disk %s: \n",
sdkp->disk->disk_name); sdkp->disk->disk_name);
sd_sync_cache(sdp);
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");
} }
/** /**
......
...@@ -13,6 +13,7 @@ struct scsi_driver { ...@@ -13,6 +13,7 @@ struct scsi_driver {
int (*init_command)(struct scsi_cmnd *); int (*init_command)(struct scsi_cmnd *);
void (*rescan)(struct device *); void (*rescan)(struct device *);
int (*issue_flush)(struct device *, sector_t *);
}; };
#define to_scsi_driver(drv) \ #define to_scsi_driver(drv) \
container_of((drv), struct scsi_driver, gendrv) 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