virtio: fix memory leak on device removal

Make vp_free_vectors do the reverse of vq_request_vectors.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Michael S. Tsirkin 2009-07-23 14:57:37 +03:00 коммит произвёл Rusty Russell
Родитель 8ef562d112
Коммит ff52c3fc71
1 изменённых файлов: 15 добавлений и 13 удалений

Просмотреть файл

@ -258,7 +258,6 @@ static void vp_free_vectors(struct virtio_device *vdev)
for (i = 0; i < vp_dev->msix_used_vectors; ++i)
free_irq(vp_dev->msix_entries[i].vector, vp_dev);
vp_dev->msix_used_vectors = 0;
if (vp_dev->msix_enabled) {
/* Disable the vector used for configuration */
@ -267,9 +266,16 @@ static void vp_free_vectors(struct virtio_device *vdev)
/* Flush the write out to device */
ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
vp_dev->msix_enabled = 0;
pci_disable_msix(vp_dev->pci_dev);
vp_dev->msix_enabled = 0;
vp_dev->msix_vectors = 0;
}
vp_dev->msix_used_vectors = 0;
kfree(vp_dev->msix_names);
vp_dev->msix_names = NULL;
kfree(vp_dev->msix_entries);
vp_dev->msix_entries = NULL;
}
static int vp_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
@ -297,11 +303,11 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries,
GFP_KERNEL);
if (!vp_dev->msix_entries)
goto error_entries;
goto error;
vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names,
GFP_KERNEL);
if (!vp_dev->msix_names)
goto error_names;
goto error;
for (i = 0; i < nvectors; ++i)
vp_dev->msix_entries[i].entry = i;
@ -314,7 +320,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
err = request_irq(vp_dev->pci_dev->irq, vp_interrupt,
IRQF_SHARED, name, vp_dev);
if (err)
goto error_irq;
goto error;
vp_dev->intx_enabled = 1;
} else {
vp_dev->msix_vectors = err;
@ -328,7 +334,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
vp_config_changed, 0, vp_dev->msix_names[v],
vp_dev);
if (err)
goto error_irq;
goto error;
++vp_dev->msix_used_vectors;
iowrite16(v, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
@ -336,7 +342,7 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
v = ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
if (v == VIRTIO_MSI_NO_VECTOR) {
err = -EBUSY;
goto error_irq;
goto error;
}
}
@ -349,16 +355,12 @@ static int vp_request_vectors(struct virtio_device *vdev, unsigned max_vqs)
vp_vring_interrupt, 0, vp_dev->msix_names[v],
vp_dev);
if (err)
goto error_irq;
goto error;
++vp_dev->msix_used_vectors;
}
return 0;
error_irq:
error:
vp_free_vectors(vdev);
kfree(vp_dev->msix_names);
error_names:
kfree(vp_dev->msix_entries);
error_entries:
return err;
}