aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-12-30 20:37:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-12-30 20:37:25 -0500
commitab70537c32a3245325b48774664da588904e47f2 (patch)
treefdb4447e520bd34dd8696fdd3b976075414d8555 /drivers/block
parent14a3c4ab0e58d143c7928c9eb2f2610205e13bf2 (diff)
parentbda53cd510b6777ced652ba279020bb7b414b744 (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.c41
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
12static int major, index; 11static 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
33struct virtblk_req 35struct 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,