diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2008-01-31 15:53:53 +0100 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-02-04 23:50:10 +1100 |
commit | 4f3bf19c6e8164b441faaee476e734b4f612a78d (patch) | |
tree | 27d2c75ef0ce7e02fcf09d08ce20b0fe51e20362 | |
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>
-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 d2fe679519e..559c322c4ff 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -7,8 +7,11 @@ #include <linux/scatterlist.h> #define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) +#define PART_BITS 4 static unsigned char virtblk_index = 'a'; +static int major, minor; + struct virtio_blk { spinlock_t lock; @@ -171,10 +174,13 @@ static struct block_device_operations virtblk_fops = { static int virtblk_probe(struct virtio_device *vdev) { struct virtio_blk *vblk; - int err, major; + int err; u64 cap; u32 v; + if (minor >= 1 << MINORBITS) + return -ENOSPC; + vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL); if (!vblk) { err = -ENOMEM; @@ -198,17 +204,11 @@ static int virtblk_probe(struct virtio_device *vdev) goto out_free_vq; } - major = register_blkdev(0, "virtblk"); - if (major < 0) { - err = major; - goto out_mempool; - } - /* FIXME: How many partitions? How long is a piece of string? */ - vblk->disk = alloc_disk(1 << 4); + vblk->disk = alloc_disk(1 << PART_BITS); if (!vblk->disk) { err = -ENOMEM; - goto out_unregister_blkdev; + goto out_mempool; } vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); @@ -219,10 +219,12 @@ static int virtblk_probe(struct virtio_device *vdev) sprintf(vblk->disk->disk_name, "vd%c", virtblk_index++); vblk->disk->major = major; - vblk->disk->first_minor = 0; + vblk->disk->first_minor = minor; vblk->disk->private_data = vblk; vblk->disk->fops = &virtblk_fops; + minor += 1 << PART_BITS; + /* If barriers are supported, tell block layer that queue is ordered */ if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER)) blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); @@ -258,8 +260,6 @@ static int virtblk_probe(struct virtio_device *vdev) out_put_disk: put_disk(vblk->disk); -out_unregister_blkdev: - unregister_blkdev(major, "virtblk"); out_mempool: mempool_destroy(vblk->pool); out_free_vq: @@ -304,11 +304,15 @@ static struct virtio_driver virtio_blk = { static int __init init(void) { + major = register_blkdev(0, "virtblk"); + if (major < 0) + return major; return register_virtio_driver(&virtio_blk); } static void __exit fini(void) { + unregister_blkdev(major, "virtblk"); unregister_virtio_driver(&virtio_blk); } module_init(init); |