diff options
| author | Michael S. Tsirkin <mst@redhat.com> | 2011-10-31 03:05:36 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2011-10-31 03:05:36 -0400 |
| commit | a0eda62552eba4e1f92d5354bb65c68fb6b45f87 (patch) | |
| tree | 53c4069ef7be8e54e0bce7c82c0f7316f08390e6 /drivers | |
| parent | c4853efec665134b2e6fc9c13447323240980351 (diff) | |
virtio-blk: use ida to allocate disk index
Based on a patch by Mark Wu <dwu@redhat.com>
Current index allocation in virtio-blk is based on a monotonically
increasing variable "index". This means we'll run out of numbers
after a while. It also could cause confusion about the disk
name in the case of hot-plugging disks.
Change virtio-blk to use ida to allocate index, instead.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/block/virtio_blk.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 079c08808d8a..e7a5750a93d9 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -8,10 +8,13 @@ | |||
| 8 | #include <linux/scatterlist.h> | 8 | #include <linux/scatterlist.h> |
| 9 | #include <linux/string_helpers.h> | 9 | #include <linux/string_helpers.h> |
| 10 | #include <scsi/scsi_cmnd.h> | 10 | #include <scsi/scsi_cmnd.h> |
| 11 | #include <linux/idr.h> | ||
| 11 | 12 | ||
| 12 | #define PART_BITS 4 | 13 | #define PART_BITS 4 |
| 13 | 14 | ||
| 14 | static int major, index; | 15 | static int major; |
| 16 | static DEFINE_IDA(vd_index_ida); | ||
| 17 | |||
| 15 | struct workqueue_struct *virtblk_wq; | 18 | struct workqueue_struct *virtblk_wq; |
| 16 | 19 | ||
| 17 | struct virtio_blk | 20 | struct virtio_blk |
| @@ -35,6 +38,9 @@ struct virtio_blk | |||
| 35 | /* What host tells us, plus 2 for header & tailer. */ | 38 | /* What host tells us, plus 2 for header & tailer. */ |
| 36 | unsigned int sg_elems; | 39 | unsigned int sg_elems; |
| 37 | 40 | ||
| 41 | /* Ida index - used to track minor number allocations. */ | ||
| 42 | int index; | ||
| 43 | |||
| 38 | /* Scatterlist: can be too big for stack. */ | 44 | /* Scatterlist: can be too big for stack. */ |
| 39 | struct scatterlist sg[/*sg_elems*/]; | 45 | struct scatterlist sg[/*sg_elems*/]; |
| 40 | }; | 46 | }; |
| @@ -276,6 +282,11 @@ static int index_to_minor(int index) | |||
| 276 | return index << PART_BITS; | 282 | return index << PART_BITS; |
| 277 | } | 283 | } |
| 278 | 284 | ||
| 285 | static int minor_to_index(int minor) | ||
| 286 | { | ||
| 287 | return minor >> PART_BITS; | ||
| 288 | } | ||
| 289 | |||
| 279 | static ssize_t virtblk_serial_show(struct device *dev, | 290 | static ssize_t virtblk_serial_show(struct device *dev, |
| 280 | struct device_attribute *attr, char *buf) | 291 | struct device_attribute *attr, char *buf) |
| 281 | { | 292 | { |
| @@ -341,14 +352,17 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
| 341 | { | 352 | { |
| 342 | struct virtio_blk *vblk; | 353 | struct virtio_blk *vblk; |
| 343 | struct request_queue *q; | 354 | struct request_queue *q; |
| 344 | int err; | 355 | int err, index; |
| 345 | u64 cap; | 356 | u64 cap; |
| 346 | u32 v, blk_size, sg_elems, opt_io_size; | 357 | u32 v, blk_size, sg_elems, opt_io_size; |
| 347 | u16 min_io_size; | 358 | u16 min_io_size; |
| 348 | u8 physical_block_exp, alignment_offset; | 359 | u8 physical_block_exp, alignment_offset; |
| 349 | 360 | ||
| 350 | if (index_to_minor(index) >= 1 << MINORBITS) | 361 | err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS), |
| 351 | return -ENOSPC; | 362 | GFP_KERNEL); |
| 363 | if (err < 0) | ||
| 364 | goto out; | ||
| 365 | index = err; | ||
| 352 | 366 | ||
| 353 | /* We need to know how many segments before we allocate. */ | 367 | /* We need to know how many segments before we allocate. */ |
| 354 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, | 368 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, |
| @@ -365,7 +379,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
| 365 | sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL); | 379 | sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL); |
| 366 | if (!vblk) { | 380 | if (!vblk) { |
| 367 | err = -ENOMEM; | 381 | err = -ENOMEM; |
| 368 | goto out; | 382 | goto out_free_index; |
| 369 | } | 383 | } |
| 370 | 384 | ||
| 371 | INIT_LIST_HEAD(&vblk->reqs); | 385 | INIT_LIST_HEAD(&vblk->reqs); |
| @@ -421,7 +435,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
| 421 | vblk->disk->private_data = vblk; | 435 | vblk->disk->private_data = vblk; |
| 422 | vblk->disk->fops = &virtblk_fops; | 436 | vblk->disk->fops = &virtblk_fops; |
| 423 | vblk->disk->driverfs_dev = &vdev->dev; | 437 | vblk->disk->driverfs_dev = &vdev->dev; |
| 424 | index++; | 438 | vblk->index = index; |
| 425 | 439 | ||
| 426 | /* configure queue flush support */ | 440 | /* configure queue flush support */ |
| 427 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) | 441 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) |
| @@ -516,6 +530,8 @@ out_free_vq: | |||
| 516 | vdev->config->del_vqs(vdev); | 530 | vdev->config->del_vqs(vdev); |
| 517 | out_free_vblk: | 531 | out_free_vblk: |
| 518 | kfree(vblk); | 532 | kfree(vblk); |
| 533 | out_free_index: | ||
| 534 | ida_simple_remove(&vd_index_ida, index); | ||
| 519 | out: | 535 | out: |
| 520 | return err; | 536 | return err; |
| 521 | } | 537 | } |
| @@ -523,6 +539,7 @@ out: | |||
| 523 | static void __devexit virtblk_remove(struct virtio_device *vdev) | 539 | static void __devexit virtblk_remove(struct virtio_device *vdev) |
| 524 | { | 540 | { |
| 525 | struct virtio_blk *vblk = vdev->priv; | 541 | struct virtio_blk *vblk = vdev->priv; |
| 542 | int index = vblk->index; | ||
| 526 | 543 | ||
| 527 | flush_work(&vblk->config_work); | 544 | flush_work(&vblk->config_work); |
| 528 | 545 | ||
| @@ -538,6 +555,7 @@ static void __devexit virtblk_remove(struct virtio_device *vdev) | |||
| 538 | mempool_destroy(vblk->pool); | 555 | mempool_destroy(vblk->pool); |
| 539 | vdev->config->del_vqs(vdev); | 556 | vdev->config->del_vqs(vdev); |
| 540 | kfree(vblk); | 557 | kfree(vblk); |
| 558 | ida_simple_remove(&vd_index_ida, index); | ||
| 541 | } | 559 | } |
| 542 | 560 | ||
| 543 | static const struct virtio_device_id id_table[] = { | 561 | static const struct virtio_device_id id_table[] = { |
