diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:37:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:37:25 -0500 |
commit | ab70537c32a3245325b48774664da588904e47f2 (patch) | |
tree | fdb4447e520bd34dd8696fdd3b976075414d8555 /drivers/block | |
parent | 14a3c4ab0e58d143c7928c9eb2f2610205e13bf2 (diff) | |
parent | bda53cd510b6777ced652ba279020bb7b414b744 (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: struct device - replace bus_id with dev_name()
lguest: move the initial guest page table creation code to the host
kvm-s390: implement config_changed for virtio on s390
virtio_console: support console resizing
virtio: add PCI device release() function
virtio_blk: fix type warning
virtio: block: dynamic maximum segments
virtio: set max_segment_size and max_sectors to infinite.
virtio: avoid implicit use of Linux page size in balloon interface
virtio: hand virtio ring alignment as argument to vring_new_virtqueue
virtio: use KVM_S390_VIRTIO_RING_ALIGN instead of relying on pagesize
virtio: use LGUEST_VRING_ALIGN instead of relying on pagesize
virtio: Don't use PAGE_SIZE for vring alignment in virtio_pci.
virtio: rename 'pagesize' arg to vring_init/vring_size
virtio: Don't use PAGE_SIZE in virtio_pci.c
virtio: struct device - replace bus_id with dev_name(), dev_set_name()
virtio-pci queue allocation not page-aligned
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/virtio_blk.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index f151592ecf73..5d34764c8a87 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -6,7 +6,6 @@ | |||
6 | #include <linux/virtio_blk.h> | 6 | #include <linux/virtio_blk.h> |
7 | #include <linux/scatterlist.h> | 7 | #include <linux/scatterlist.h> |
8 | 8 | ||
9 | #define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) | ||
10 | #define PART_BITS 4 | 9 | #define PART_BITS 4 |
11 | 10 | ||
12 | static int major, index; | 11 | static int major, index; |
@@ -26,8 +25,11 @@ struct virtio_blk | |||
26 | 25 | ||
27 | mempool_t *pool; | 26 | mempool_t *pool; |
28 | 27 | ||
28 | /* What host tells us, plus 2 for header & tailer. */ | ||
29 | unsigned int sg_elems; | ||
30 | |||
29 | /* Scatterlist: can be too big for stack. */ | 31 | /* Scatterlist: can be too big for stack. */ |
30 | struct scatterlist sg[VIRTIO_MAX_SG]; | 32 | struct scatterlist sg[/*sg_elems*/]; |
31 | }; | 33 | }; |
32 | 34 | ||
33 | struct virtblk_req | 35 | struct virtblk_req |
@@ -97,8 +99,6 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
97 | if (blk_barrier_rq(vbr->req)) | 99 | if (blk_barrier_rq(vbr->req)) |
98 | vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; | 100 | vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; |
99 | 101 | ||
100 | /* This init could be done at vblk creation time */ | ||
101 | sg_init_table(vblk->sg, VIRTIO_MAX_SG); | ||
102 | sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); | 102 | sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); |
103 | num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); | 103 | num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); |
104 | sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status)); | 104 | sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status)); |
@@ -130,7 +130,7 @@ static void do_virtblk_request(struct request_queue *q) | |||
130 | 130 | ||
131 | while ((req = elv_next_request(q)) != NULL) { | 131 | while ((req = elv_next_request(q)) != NULL) { |
132 | vblk = req->rq_disk->private_data; | 132 | vblk = req->rq_disk->private_data; |
133 | BUG_ON(req->nr_phys_segments > ARRAY_SIZE(vblk->sg)); | 133 | BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); |
134 | 134 | ||
135 | /* If this request fails, stop queue and wait for something to | 135 | /* If this request fails, stop queue and wait for something to |
136 | finish to restart it. */ | 136 | finish to restart it. */ |
@@ -196,12 +196,22 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
196 | int err; | 196 | int err; |
197 | u64 cap; | 197 | u64 cap; |
198 | u32 v; | 198 | u32 v; |
199 | u32 blk_size; | 199 | u32 blk_size, sg_elems; |
200 | 200 | ||
201 | if (index_to_minor(index) >= 1 << MINORBITS) | 201 | if (index_to_minor(index) >= 1 << MINORBITS) |
202 | return -ENOSPC; | 202 | return -ENOSPC; |
203 | 203 | ||
204 | vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL); | 204 | /* We need to know how many segments before we allocate. */ |
205 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, | ||
206 | offsetof(struct virtio_blk_config, seg_max), | ||
207 | &sg_elems); | ||
208 | if (err) | ||
209 | sg_elems = 1; | ||
210 | |||
211 | /* We need an extra sg elements at head and tail. */ | ||
212 | sg_elems += 2; | ||
213 | vdev->priv = vblk = kmalloc(sizeof(*vblk) + | ||
214 | sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL); | ||
205 | if (!vblk) { | 215 | if (!vblk) { |
206 | err = -ENOMEM; | 216 | err = -ENOMEM; |
207 | goto out; | 217 | goto out; |
@@ -210,6 +220,8 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
210 | INIT_LIST_HEAD(&vblk->reqs); | 220 | INIT_LIST_HEAD(&vblk->reqs); |
211 | spin_lock_init(&vblk->lock); | 221 | spin_lock_init(&vblk->lock); |
212 | vblk->vdev = vdev; | 222 | vblk->vdev = vdev; |
223 | vblk->sg_elems = sg_elems; | ||
224 | sg_init_table(vblk->sg, vblk->sg_elems); | ||
213 | 225 | ||
214 | /* We expect one virtqueue, for output. */ | 226 | /* We expect one virtqueue, for output. */ |
215 | vblk->vq = vdev->config->find_vq(vdev, 0, blk_done); | 227 | vblk->vq = vdev->config->find_vq(vdev, 0, blk_done); |
@@ -279,6 +291,13 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
279 | } | 291 | } |
280 | set_capacity(vblk->disk, cap); | 292 | set_capacity(vblk->disk, cap); |
281 | 293 | ||
294 | /* We can handle whatever the host told us to handle. */ | ||
295 | blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); | ||
296 | blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); | ||
297 | |||
298 | /* No real sector limit. */ | ||
299 | blk_queue_max_sectors(vblk->disk->queue, -1U); | ||
300 | |||
282 | /* Host can optionally specify maximum segment size and number of | 301 | /* Host can optionally specify maximum segment size and number of |
283 | * segments. */ | 302 | * segments. */ |
284 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX, | 303 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX, |
@@ -286,12 +305,8 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
286 | &v); | 305 | &v); |
287 | if (!err) | 306 | if (!err) |
288 | blk_queue_max_segment_size(vblk->disk->queue, v); | 307 | blk_queue_max_segment_size(vblk->disk->queue, v); |
289 | 308 | else | |
290 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, | 309 | blk_queue_max_segment_size(vblk->disk->queue, -1U); |
291 | offsetof(struct virtio_blk_config, seg_max), | ||
292 | &v); | ||
293 | if (!err) | ||
294 | blk_queue_max_hw_segments(vblk->disk->queue, v); | ||
295 | 310 | ||
296 | /* Host can optionally specify the block size of the device */ | 311 | /* Host can optionally specify the block size of the device */ |
297 | err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, | 312 | err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, |