diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 12:23:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 12:23:45 -0400 |
commit | 1f0918d03ff4b5c94540c71ce889672abdbc2f4a (patch) | |
tree | ecee710444fb3405da55933501e339e10e4ac880 /drivers/block/virtio_blk.c | |
parent | 4266c97a3ef4604561a22212eb0eab8a3c338971 (diff) | |
parent | ca60a42c9be41c07ebcc2ec8c43dd1be53f147bf (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus:
lguest: don't force VIRTIO_F_NOTIFY_ON_EMPTY
lguest: cleanup for map_switcher()
lguest: use PGDIR_SHIFT for PAE code to allow different PAGE_OFFSET
lguest: use set_pte/set_pmd uniformly for real page table entries
lguest: move panic notifier registration to its expected place.
virtio_blk: add support for cache flush
virtio: add virtio IDs file
virtio: get rid of redundant VIRTIO_ID_9P definition
virtio: make add_buf return capacity remaining
virtio_pci: minor MSI-X cleanups
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r-- | drivers/block/virtio_blk.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index aa89fe45237d..43f19389647a 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/blkdev.h> | 3 | #include <linux/blkdev.h> |
4 | #include <linux/hdreg.h> | 4 | #include <linux/hdreg.h> |
5 | #include <linux/virtio.h> | 5 | #include <linux/virtio.h> |
6 | #include <linux/virtio_ids.h> | ||
6 | #include <linux/virtio_blk.h> | 7 | #include <linux/virtio_blk.h> |
7 | #include <linux/scatterlist.h> | 8 | #include <linux/scatterlist.h> |
8 | 9 | ||
@@ -91,15 +92,26 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
91 | return false; | 92 | return false; |
92 | 93 | ||
93 | vbr->req = req; | 94 | vbr->req = req; |
94 | if (blk_fs_request(vbr->req)) { | 95 | switch (req->cmd_type) { |
96 | case REQ_TYPE_FS: | ||
95 | vbr->out_hdr.type = 0; | 97 | vbr->out_hdr.type = 0; |
96 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); | 98 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); |
97 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 99 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
98 | } else if (blk_pc_request(vbr->req)) { | 100 | break; |
101 | case REQ_TYPE_BLOCK_PC: | ||
99 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; | 102 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; |
100 | vbr->out_hdr.sector = 0; | 103 | vbr->out_hdr.sector = 0; |
101 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 104 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
102 | } 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: | ||
103 | /* We don't put anything else in the queue. */ | 115 | /* We don't put anything else in the queue. */ |
104 | BUG(); | 116 | BUG(); |
105 | } | 117 | } |
@@ -139,7 +151,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
139 | } | 151 | } |
140 | } | 152 | } |
141 | 153 | ||
142 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) { | 154 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr) < 0) { |
143 | mempool_free(vbr, vblk->pool); | 155 | mempool_free(vbr, vblk->pool); |
144 | return false; | 156 | return false; |
145 | } | 157 | } |
@@ -199,6 +211,12 @@ out: | |||
199 | return err; | 211 | return err; |
200 | } | 212 | } |
201 | 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 | |||
202 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | 220 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, |
203 | unsigned cmd, unsigned long data) | 221 | unsigned cmd, unsigned long data) |
204 | { | 222 | { |
@@ -337,7 +355,10 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
337 | index++; | 355 | index++; |
338 | 356 | ||
339 | /* If barriers are supported, tell block layer that queue is ordered */ | 357 | /* If barriers are supported, tell block layer that queue is ordered */ |
340 | 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)) | ||
341 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 362 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
342 | 363 | ||
343 | /* 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 */ |
@@ -424,7 +445,7 @@ static struct virtio_device_id id_table[] = { | |||
424 | static unsigned int features[] = { | 445 | static unsigned int features[] = { |
425 | 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, |
426 | 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, |
427 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY | 448 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY, VIRTIO_BLK_F_FLUSH |
428 | }; | 449 | }; |
429 | 450 | ||
430 | /* | 451 | /* |