diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2008-01-31 09:53:53 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 07:50:10 -0500 |
commit | 4f3bf19c6e8164b441faaee476e734b4f612a78d (patch) | |
tree | 27d2c75ef0ce7e02fcf09d08ce20b0fe51e20362 /drivers/block/virtio_blk.c | |
parent | 135da0b037984c0284acdf40aaf4f7f31eb5cbd0 (diff) |
virtio_blk: Dont waste major numbers
Rusty,
currently virtio_blk uses one major number per device. While this works
quite well on most systems it is wasteful and will exhaust major numbers
on larger installations.
This patch allocates a major number on init and will use 16 minor numbers
for each disk. That will allow ~64k virtio_blk disks.
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
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 | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index d2fe679519e4..559c322c4ffa 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -7,8 +7,11 @@ | |||
7 | #include <linux/scatterlist.h> | 7 | #include <linux/scatterlist.h> |
8 | 8 | ||
9 | #define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) | 9 | #define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) |
10 | #define PART_BITS 4 | ||
10 | 11 | ||
11 | static unsigned char virtblk_index = 'a'; | 12 | static unsigned char virtblk_index = 'a'; |
13 | static int major, minor; | ||
14 | |||
12 | struct virtio_blk | 15 | struct virtio_blk |
13 | { | 16 | { |
14 | spinlock_t lock; | 17 | spinlock_t lock; |
@@ -171,10 +174,13 @@ static struct block_device_operations virtblk_fops = { | |||
171 | static int virtblk_probe(struct virtio_device *vdev) | 174 | static int virtblk_probe(struct virtio_device *vdev) |
172 | { | 175 | { |
173 | struct virtio_blk *vblk; | 176 | struct virtio_blk *vblk; |
174 | int err, major; | 177 | int err; |
175 | u64 cap; | 178 | u64 cap; |
176 | u32 v; | 179 | u32 v; |
177 | 180 | ||
181 | if (minor >= 1 << MINORBITS) | ||
182 | return -ENOSPC; | ||
183 | |||
178 | vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL); | 184 | vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL); |
179 | if (!vblk) { | 185 | if (!vblk) { |
180 | err = -ENOMEM; | 186 | err = -ENOMEM; |
@@ -198,17 +204,11 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
198 | goto out_free_vq; | 204 | goto out_free_vq; |
199 | } | 205 | } |
200 | 206 | ||
201 | major = register_blkdev(0, "virtblk"); | ||
202 | if (major < 0) { | ||
203 | err = major; | ||
204 | goto out_mempool; | ||
205 | } | ||
206 | |||
207 | /* FIXME: How many partitions? How long is a piece of string? */ | 207 | /* FIXME: How many partitions? How long is a piece of string? */ |
208 | vblk->disk = alloc_disk(1 << 4); | 208 | vblk->disk = alloc_disk(1 << PART_BITS); |
209 | if (!vblk->disk) { | 209 | if (!vblk->disk) { |
210 | err = -ENOMEM; | 210 | err = -ENOMEM; |
211 | goto out_unregister_blkdev; | 211 | goto out_mempool; |
212 | } | 212 | } |
213 | 213 | ||
214 | vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); | 214 | vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); |
@@ -219,10 +219,12 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
219 | 219 | ||
220 | sprintf(vblk->disk->disk_name, "vd%c", virtblk_index++); | 220 | sprintf(vblk->disk->disk_name, "vd%c", virtblk_index++); |
221 | vblk->disk->major = major; | 221 | vblk->disk->major = major; |
222 | vblk->disk->first_minor = 0; | 222 | vblk->disk->first_minor = minor; |
223 | vblk->disk->private_data = vblk; | 223 | vblk->disk->private_data = vblk; |
224 | vblk->disk->fops = &virtblk_fops; | 224 | vblk->disk->fops = &virtblk_fops; |
225 | 225 | ||
226 | minor += 1 << PART_BITS; | ||
227 | |||
226 | /* If barriers are supported, tell block layer that queue is ordered */ | 228 | /* If barriers are supported, tell block layer that queue is ordered */ |
227 | if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER)) | 229 | if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER)) |
228 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 230 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
@@ -258,8 +260,6 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
258 | 260 | ||
259 | out_put_disk: | 261 | out_put_disk: |
260 | put_disk(vblk->disk); | 262 | put_disk(vblk->disk); |
261 | out_unregister_blkdev: | ||
262 | unregister_blkdev(major, "virtblk"); | ||
263 | out_mempool: | 263 | out_mempool: |
264 | mempool_destroy(vblk->pool); | 264 | mempool_destroy(vblk->pool); |
265 | out_free_vq: | 265 | out_free_vq: |
@@ -304,11 +304,15 @@ static struct virtio_driver virtio_blk = { | |||
304 | 304 | ||
305 | static int __init init(void) | 305 | static int __init init(void) |
306 | { | 306 | { |
307 | major = register_blkdev(0, "virtblk"); | ||
308 | if (major < 0) | ||
309 | return major; | ||
307 | return register_virtio_driver(&virtio_blk); | 310 | return register_virtio_driver(&virtio_blk); |
308 | } | 311 | } |
309 | 312 | ||
310 | static void __exit fini(void) | 313 | static void __exit fini(void) |
311 | { | 314 | { |
315 | unregister_blkdev(major, "virtblk"); | ||
312 | unregister_virtio_driver(&virtio_blk); | 316 | unregister_virtio_driver(&virtio_blk); |
313 | } | 317 | } |
314 | module_init(init); | 318 | module_init(init); |