summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2013-01-02 15:37:17 +1030
committerBen Hutchings <ben@decadent.org.uk>2013-02-06 04:33:19 +0000
commit63dddb4936fa86057e7f94a0bd10cb8ac25bc7f3 (patch)
treeb9552faa3a880ad84b4269e4219d5554a439b14a
parent9d38cd591c7e22932c7bb8e138231c87108c7aec (diff)
virtio-blk: Don't free ida when disk is in use
commit f4953fe6c4aeada2d5cafd78aa97587a46d2d8f9 upstream. 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> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-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 de9c800fac75..166cb3683348 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -546,6 +546,7 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
{
struct virtio_blk *vblk = vdev->priv;
int index = vblk->index;
+ int refc;
/* Prevent config work handler from accessing the device. */
mutex_lock(&vblk->config_lock);
@@ -560,11 +561,15 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
flush_work(&vblk->config_work);
+ refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
put_disk(vblk->disk);
mempool_destroy(vblk->pool);
vdev->config->del_vqs(vdev);
kfree(vblk);
- ida_simple_remove(&vd_index_ida, index);
+
+ /* Only free device id if we don't have any users */
+ if (refc == 1)
+ ida_simple_remove(&vd_index_ida, index);
}
static const struct virtio_device_id id_table[] = {