diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-23 19:42:09 -0200 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-23 19:42:09 -0200 |
commit | 12cbfd0a3c52a52c2948c91b9e62e73c468d1572 (patch) | |
tree | 9252b3929159a83fc81ca0a48706bfa959660967 /drivers/block/virtio_blk.c | |
parent | b32e724308300a6ecead0f4895f0452a06a4291d (diff) | |
parent | cfcfc9eca2bcbd26a8e206baeb005b055dbf8e37 (diff) | |
download | linux-12cbfd0a3c52a52c2948c91b9e62e73c468d1572.tar.bz2 |
Merge tag 'v3.2-rc2' into staging/for_v3.3
* tag 'v3.2-rc2': (3068 commits)
Linux 3.2-rc2
hfs: add sanity check for file name length
fsl-rio: fix compile error
blackfin: Fixup export.h includes
Blackfin: add serial TX IRQ in individual platform resource
virtio-pci: fix use after free
ACPI / cpuidle: Remove acpi_idle_suspend (to fix suspend regression)
drm/radeon/kms/combios: fix dynamic allocation of PM clock modes
[CPUFREQ] db8500: fix build error due to undeclared i variable
bma023: Add SFI translation for this device
vrtc: change its year offset from 1960 to 1972
ce4100: fix a build error
arm/imx: fix imx6q mmc error when mounting rootfs
arm/imx: fix AUTO_ZRELADDR selection
arm/imx: fix the references to ARCH_MX3
ARM: mx51/53: set pwm clock parent to ipg_perclk
btrfs: rename the option to nospace_cache
drm/radeon/kms/pm: switch to dynamically allocating clock mode array
drm/radeon/kms: optimize r600_pm_profile_init
drm/radeon/kms/pm: add a proper pm profile init function for fusion
...
Conflicts:
drivers/media/radio/Kconfig
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r-- | drivers/block/virtio_blk.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 079c08808d8a..4d0b70adf5f7 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -3,15 +3,19 @@ #include <linux/slab.h> #include <linux/blkdev.h> #include <linux/hdreg.h> +#include <linux/module.h> #include <linux/virtio.h> #include <linux/virtio_blk.h> #include <linux/scatterlist.h> #include <linux/string_helpers.h> #include <scsi/scsi_cmnd.h> +#include <linux/idr.h> #define PART_BITS 4 -static int major, index; +static int major; +static DEFINE_IDA(vd_index_ida); + struct workqueue_struct *virtblk_wq; struct virtio_blk @@ -35,6 +39,9 @@ struct virtio_blk /* What host tells us, plus 2 for header & tailer. */ unsigned int sg_elems; + /* Ida index - used to track minor number allocations. */ + int index; + /* Scatterlist: can be too big for stack. */ struct scatterlist sg[/*sg_elems*/]; }; @@ -276,6 +283,11 @@ static int index_to_minor(int index) return index << PART_BITS; } +static int minor_to_index(int minor) +{ + return minor >> PART_BITS; +} + static ssize_t virtblk_serial_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -341,14 +353,17 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) { struct virtio_blk *vblk; struct request_queue *q; - int err; + int err, index; u64 cap; u32 v, blk_size, sg_elems, opt_io_size; u16 min_io_size; u8 physical_block_exp, alignment_offset; - if (index_to_minor(index) >= 1 << MINORBITS) - return -ENOSPC; + err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS), + GFP_KERNEL); + if (err < 0) + goto out; + index = err; /* We need to know how many segments before we allocate. */ err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, @@ -365,7 +380,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) sizeof(vblk->sg[0]) * sg_elems, GFP_KERNEL); if (!vblk) { err = -ENOMEM; - goto out; + goto out_free_index; } INIT_LIST_HEAD(&vblk->reqs); @@ -421,7 +436,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) vblk->disk->private_data = vblk; vblk->disk->fops = &virtblk_fops; vblk->disk->driverfs_dev = &vdev->dev; - index++; + vblk->index = index; /* configure queue flush support */ if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) @@ -516,6 +531,8 @@ out_free_vq: vdev->config->del_vqs(vdev); out_free_vblk: kfree(vblk); +out_free_index: + ida_simple_remove(&vd_index_ida, index); out: return err; } @@ -523,6 +540,7 @@ out: static void __devexit virtblk_remove(struct virtio_device *vdev) { struct virtio_blk *vblk = vdev->priv; + int index = vblk->index; flush_work(&vblk->config_work); @@ -538,6 +556,7 @@ static void __devexit virtblk_remove(struct virtio_device *vdev) mempool_destroy(vblk->pool); vdev->config->del_vqs(vdev); kfree(vblk); + ida_simple_remove(&vd_index_ida, index); } static const struct virtio_device_id id_table[] = { |