aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2009-09-17 13:57:42 -0400
committerRusty Russell <rusty@rustcorp.com.au>2009-09-23 08:56:36 -0400
commitf1b0ef062602713c2c7cfa12362d5d90ed01c5f6 (patch)
tree30a130141b7c4b69ff20d134734acd40f1ee0960
parent3ca4f5ca73057a617f9444a91022d7127041970a (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>
-rw-r--r--drivers/block/virtio_blk.c30
-rw-r--r--include/linux/virtio_blk.h15
2 files changed, 40 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
214static 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
203static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, 220static 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[] = {
425static unsigned int features[] = { 445static 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/*
diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h
index 25fbabfa90d4..15cb666581d7 100644
--- a/include/linux/virtio_blk.h
+++ b/include/linux/virtio_blk.h
@@ -14,6 +14,7 @@
14#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ 14#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/
15#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ 15#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
16#define VIRTIO_BLK_F_IDENTIFY 8 /* ATA IDENTIFY supported */ 16#define VIRTIO_BLK_F_IDENTIFY 8 /* ATA IDENTIFY supported */
17#define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */
17 18
18#define VIRTIO_BLK_ID_BYTES (sizeof(__u16[256])) /* IDENTIFY DATA */ 19#define VIRTIO_BLK_ID_BYTES (sizeof(__u16[256])) /* IDENTIFY DATA */
19 20
@@ -35,6 +36,17 @@ struct virtio_blk_config {
35 __u8 identify[VIRTIO_BLK_ID_BYTES]; 36 __u8 identify[VIRTIO_BLK_ID_BYTES];
36} __attribute__((packed)); 37} __attribute__((packed));
37 38
39/*
40 * Command types
41 *
42 * Usage is a bit tricky as some bits are used as flags and some are not.
43 *
44 * Rules:
45 * VIRTIO_BLK_T_OUT may be combined with VIRTIO_BLK_T_SCSI_CMD or
46 * VIRTIO_BLK_T_BARRIER. VIRTIO_BLK_T_FLUSH is a command of its own
47 * and may not be combined with any of the other flags.
48 */
49
38/* These two define direction. */ 50/* These two define direction. */
39#define VIRTIO_BLK_T_IN 0 51#define VIRTIO_BLK_T_IN 0
40#define VIRTIO_BLK_T_OUT 1 52#define VIRTIO_BLK_T_OUT 1
@@ -42,6 +54,9 @@ struct virtio_blk_config {
42/* This bit says it's a scsi command, not an actual read or write. */ 54/* This bit says it's a scsi command, not an actual read or write. */
43#define VIRTIO_BLK_T_SCSI_CMD 2 55#define VIRTIO_BLK_T_SCSI_CMD 2
44 56
57/* Cache flush command */
58#define VIRTIO_BLK_T_FLUSH 4
59
45/* Barrier before this op. */ 60/* Barrier before this op. */
46#define VIRTIO_BLK_T_BARRIER 0x80000000 61#define VIRTIO_BLK_T_BARRIER 0x80000000
47 62