diff options
author | Christoph Hellwig <hch@lst.de> | 2009-09-17 13:57:42 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2009-09-23 08:56:36 -0400 |
commit | f1b0ef062602713c2c7cfa12362d5d90ed01c5f6 (patch) | |
tree | 30a130141b7c4b69ff20d134734acd40f1ee0960 /drivers/block/virtio_blk.c | |
parent | 3ca4f5ca73057a617f9444a91022d7127041970a (diff) |
virtio_blk: add support for cache flush
Recent qemu has added a VIRTIO_BLK_F_FLUSH flag to advertise that the
virtual disk has a volatile write cache that needs to be flushed. In case
we see this feature implement tell the Linux block layer about the fact
and use the new VIRTIO_BLK_T_FLUSH to flush the cache when required. This
allows for an correct and simple implementation of write barriers.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r-- | drivers/block/virtio_blk.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 73de7532fcf5..3d5fe97569c7 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -92,15 +92,26 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
92 | return false; | 92 | return false; |
93 | 93 | ||
94 | vbr->req = req; | 94 | vbr->req = req; |
95 | if (blk_fs_request(vbr->req)) { | 95 | switch (req->cmd_type) { |
96 | case REQ_TYPE_FS: | ||
96 | vbr->out_hdr.type = 0; | 97 | vbr->out_hdr.type = 0; |
97 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); | 98 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); |
98 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 99 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
99 | } else if (blk_pc_request(vbr->req)) { | 100 | break; |
101 | case REQ_TYPE_BLOCK_PC: | ||
100 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; | 102 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; |
101 | vbr->out_hdr.sector = 0; | 103 | vbr->out_hdr.sector = 0; |
102 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 104 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
103 | } else { | 105 | break; |
106 | case REQ_TYPE_LINUX_BLOCK: | ||
107 | if (req->cmd[0] == REQ_LB_OP_FLUSH) { | ||
108 | vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; | ||
109 | vbr->out_hdr.sector = 0; | ||
110 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | ||
111 | break; | ||
112 | } | ||
113 | /*FALLTHRU*/ | ||
114 | default: | ||
104 | /* We don't put anything else in the queue. */ | 115 | /* We don't put anything else in the queue. */ |
105 | BUG(); | 116 | BUG(); |
106 | } | 117 | } |
@@ -200,6 +211,12 @@ out: | |||
200 | return err; | 211 | return err; |
201 | } | 212 | } |
202 | 213 | ||
214 | static void virtblk_prepare_flush(struct request_queue *q, struct request *req) | ||
215 | { | ||
216 | req->cmd_type = REQ_TYPE_LINUX_BLOCK; | ||
217 | req->cmd[0] = REQ_LB_OP_FLUSH; | ||
218 | } | ||
219 | |||
203 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | 220 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, |
204 | unsigned cmd, unsigned long data) | 221 | unsigned cmd, unsigned long data) |
205 | { | 222 | { |
@@ -338,7 +355,10 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
338 | index++; | 355 | index++; |
339 | 356 | ||
340 | /* If barriers are supported, tell block layer that queue is ordered */ | 357 | /* If barriers are supported, tell block layer that queue is ordered */ |
341 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | 358 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) |
359 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_DRAIN_FLUSH, | ||
360 | virtblk_prepare_flush); | ||
361 | else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | ||
342 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 362 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
343 | 363 | ||
344 | /* If disk is read-only in the host, the guest should obey */ | 364 | /* If disk is read-only in the host, the guest should obey */ |
@@ -425,7 +445,7 @@ static struct virtio_device_id id_table[] = { | |||
425 | static unsigned int features[] = { | 445 | static unsigned int features[] = { |
426 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | 446 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, |
427 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, | 447 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, |
428 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY | 448 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY, VIRTIO_BLK_F_FLUSH |
429 | }; | 449 | }; |
430 | 450 | ||
431 | /* | 451 | /* |