aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/virtio_blk.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2013-01-02 00:07:17 -0500
committerRusty Russell <rusty@rustcorp.com.au>2013-01-02 00:07:58 -0500
commitf4953fe6c4aeada2d5cafd78aa97587a46d2d8f9 (patch)
tree25dea7884cb125d2c0f76a38938eb624c94ec228 /drivers/block/virtio_blk.c
parenta7f2a366f62319dfebf8d4dfe8b211f631c78457 (diff)
virtio-blk: Don't free ida when disk is in use
When a file system is mounted on a virtio-blk disk, we then remove it and then reattach it, the reattached disk gets the same disk name and ids as the hot removed one. This leads to very nasty effects - mostly rendering the newly attached device completely unusable. Trying what happens when I do the same thing with a USB device, I saw that the sd node simply doesn't get free'd when a device gets forcefully removed. Imitate the same behavior for vd devices. This way broken vd devices simply are never free'd and newly attached ones keep working just fine. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Cc: stable@kernel.org
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r--drivers/block/virtio_blk.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 0bdde8fba397..07a18e238483 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -889,6 +889,7 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
889{ 889{
890 struct virtio_blk *vblk = vdev->priv; 890 struct virtio_blk *vblk = vdev->priv;
891 int index = vblk->index; 891 int index = vblk->index;
892 int refc;
892 893
893 /* Prevent config work handler from accessing the device. */ 894 /* Prevent config work handler from accessing the device. */
894 mutex_lock(&vblk->config_lock); 895 mutex_lock(&vblk->config_lock);
@@ -903,11 +904,15 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
903 904
904 flush_work(&vblk->config_work); 905 flush_work(&vblk->config_work);
905 906
907 refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
906 put_disk(vblk->disk); 908 put_disk(vblk->disk);
907 mempool_destroy(vblk->pool); 909 mempool_destroy(vblk->pool);
908 vdev->config->del_vqs(vdev); 910 vdev->config->del_vqs(vdev);
909 kfree(vblk); 911 kfree(vblk);
910 ida_simple_remove(&vd_index_ida, index); 912
913 /* Only free device id if we don't have any users */
914 if (refc == 1)
915 ida_simple_remove(&vd_index_ida, index);
911} 916}
912 917
913#ifdef CONFIG_PM 918#ifdef CONFIG_PM