Skip to contentSkip to conversation

virtio: fix memory leak on device removal

PATCH In review Michael S. Tsirkin 2 participants 16 messages Jul 21, 2009 – Jul 23, 2009 1 message not in the archive

Subsystems (2)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Michael S. Tsirkin

author maintainer
#1 lore raw

PATCH 1/2 virtio: fix memory leak on device removal

Free up msi vector tables.

---
 drivers/virtio/virtio_pci.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/virtio/virtio_pci.c +3 -0
index 193c8f0..dab3c86 100644
@@ -489,12 +489,15 @@ static void vp_del_vq(struct virtqueue *vq)
 /* the config->del_vqs() implementation */
 static void vp_del_vqs(struct virtio_device *vdev)
 {
+	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	struct virtqueue *vq, *n;
 
 	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
 		vp_del_vq(vq);
 
 	vp_free_vectors(vdev);
+	kfree(vp_dev->msix_names);
+	kfree(vp_dev->msix_entries);
 }
 
 /* the config->find_vqs() implementation */
Signature · 1 line
1.6.2.5
author maintainer
#2 lore raw

PATCH 1/2 virtio: fix memory leak on device removal

In reply to a message not in the archive

Free up msi vector tables.

---
 drivers/virtio/virtio_pci.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/virtio/virtio_pci.c +3 -0
index 193c8f0..dab3c86 100644
@@ -489,12 +489,15 @@ static void vp_del_vq(struct virtqueue *vq)
 /* the config->del_vqs() implementation */
 static void vp_del_vqs(struct virtio_device *vdev)
 {
+	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	struct virtqueue *vq, *n;
 
 	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
 		vp_del_vq(vq);
 
 	vp_free_vectors(vdev);
+	kfree(vp_dev->msix_names);
+	kfree(vp_dev->msix_entries);
 }
 
 /* the config->find_vqs() implementation */
Signature · 1 line
1.6.2.5
author maintainer
#3 lore raw

Free up msi vector tables.

---

Resending with corrected To list. Sorry about the churn.

 drivers/virtio/virtio_pci.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/virtio/virtio_pci.c +3 -0
index 193c8f0..dab3c86 100644
@@ -489,12 +489,15 @@ static void vp_del_vq(struct virtqueue *vq)
 /* the config->del_vqs() implementation */
 static void vp_del_vqs(struct virtio_device *vdev)
 {
+	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	struct virtqueue *vq, *n;
 
 	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
 		vp_del_vq(vq);
 
 	vp_free_vectors(vdev);
+	kfree(vp_dev->msix_names);
+	kfree(vp_dev->msix_entries);
 }
 
 /* the config->find_vqs() implementation */
Signature · 1 line
1.6.2.5
author maintainer
#4 lore raw
In reply to Michael S. Tsirkin

Free up msi vector tables.

---

Resending with corrected To list. Sorry about the churn.

 drivers/virtio/virtio_pci.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
drivers/virtio/virtio_pci.c +3 -0
index 193c8f0..dab3c86 100644
@@ -489,12 +489,15 @@ static void vp_del_vq(struct virtqueue *vq)
 /* the config->del_vqs() implementation */
 static void vp_del_vqs(struct virtio_device *vdev)
 {
+	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	struct virtqueue *vq, *n;
 
 	list_for_each_entry_safe(vq, n, &vdev->vqs, list)
 		vp_del_vq(vq);
 
 	vp_free_vectors(vdev);
+	kfree(vp_dev->msix_names);
+	kfree(vp_dev->msix_entries);
 }
 
 /* the config->find_vqs() implementation */
Signature · 1 line
1.6.2.5
#5 lore raw
In reply to Michael S. Tsirkin
Quoted 1 line · Michael S. Tsirkin

Free up msi vector tables.

Michael, this papers over the bug, but doesn't actually fix the problem.

The problem is that vp_free_vectors() does not do the reverse of vp_request_vectors. If the author (you) can't get it right, what hope the rest of us?

Indeed, if you look harder, you'll see another leak caused by this problem, which your patch *didn't* fix.

Thanks,
Rusty.

#6 lore raw
In reply to Michael S. Tsirkin
Quoted 1 line · Michael S. Tsirkin

Free up msi vector tables.

Michael, this papers over the bug, but doesn't actually fix the problem.

The problem is that vp_free_vectors() does not do the reverse of vp_request_vectors. If the author (you) can't get it right, what hope the rest of us?

Indeed, if you look harder, you'll see another leak caused by this problem, which your patch *didn't* fix.

Thanks,
Rusty.

author maintainer
#7 lore raw
Quoted 8 lines · Rusty Russell
Quoted 1 line · Michael S. Tsirkin

Free up msi vector tables.

Michael, this papers over the bug, but doesn't actually fix the problem.

The problem is that vp_free_vectors() does not do the reverse of vp_request_vectors. If the author (you) can't get it right, what hope the rest of us?

I agree. This code belongs in free_vectors.
And might as well reset the pointers to make the reversal complete.

Quoted 2 lines

Indeed, if you look harder, you'll see another leak caused by this problem, which your patch *didn't* fix.

Couldn't spot it yet. I'll send out a fixed patch, see if I got everything covered.

Quoted 6 lines

Thanks,
Rusty.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

author maintainer
#8 lore raw
In reply to Rusty Russell
Quoted 8 lines · Rusty Russell
Quoted 1 line · Michael S. Tsirkin

Free up msi vector tables.

Michael, this papers over the bug, but doesn't actually fix the problem.

The problem is that vp_free_vectors() does not do the reverse of vp_request_vectors. If the author (you) can't get it right, what hope the rest of us?

I agree. This code belongs in free_vectors.
And might as well reset the pointers to make the reversal complete.

Quoted 2 lines

Indeed, if you look harder, you'll see another leak caused by this problem, which your patch *didn't* fix.

Couldn't spot it yet. I'll send out a fixed patch, see if I got everything covered.

Quoted 6 lines

Thanks,
Rusty.
--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

author maintainer
#9 lore raw

PATCH 2/2 virtio: fix double free_irq

In reply to a message not in the archive

Decrement used vectors counter when removing the vq so that vp_free_vectors does not try to free the vector again.

---
 drivers/virtio/virtio_pci.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)
drivers/virtio/virtio_pci.c +3 -1
index dab3c86..9dcc368 100644
@@ -466,8 +466,10 @@ static void vp_del_vq(struct virtqueue *vq)
 
 	iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
 
-	if (info->vector != VIRTIO_MSI_NO_VECTOR)
+	if (info->vector != VIRTIO_MSI_NO_VECTOR) {
 		free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+		--vp_dev->msix_used_vectors;
+	}
 
 	if (vp_dev->msix_enabled) {
 		iowrite16(VIRTIO_MSI_NO_VECTOR,
Signature · 1 line
1.6.2.5
author maintainer
#10 lore raw

PATCH 2/2 virtio: fix double free_irq

In reply to a message not in the archive

Decrement used vectors counter when removing the vq so that vp_free_vectors does not try to free the vector again.

---
 drivers/virtio/virtio_pci.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)
drivers/virtio/virtio_pci.c +3 -1
index dab3c86..9dcc368 100644
@@ -466,8 +466,10 @@ static void vp_del_vq(struct virtqueue *vq)
 
 	iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
 
-	if (info->vector != VIRTIO_MSI_NO_VECTOR)
+	if (info->vector != VIRTIO_MSI_NO_VECTOR) {
 		free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+		--vp_dev->msix_used_vectors;
+	}
 
 	if (vp_dev->msix_enabled) {
 		iowrite16(VIRTIO_MSI_NO_VECTOR,
Signature · 1 line
1.6.2.5
#11 lore raw

Re: [PATCH 2/2] virtio: fix double free_irq

drivers/virtio/virtio_pci.c static void vp_del_vq(struct virtqueue *vq) · line 472

Quoted 6 lines · Michael S. Tsirkin
drivers/virtio/virtio_pci.c +3 -1
-	if (info->vector != VIRTIO_MSI_NO_VECTOR)
+	if (info->vector != VIRTIO_MSI_NO_VECTOR) {
 		free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+		--vp_dev->msix_used_vectors;
+	}

This only works because the only current caller of vp_del_vq is vp_del_vqs, so msix_used_vectors will be 0 after all the queues have been freed.

Make up your mind. Either find_vq allocates and del_vq frees, or it's find_vqs and del_vqs. I suggest the former, and setting the value VIRTIO_MSI_NO_VECTOR to indicate it's already freed. I think with some cleanups, that loop in vp_free_vectors might go away, too.

Rusty.

#12 lore raw

Re: [PATCH 2/2] virtio: fix double free_irq

In reply to Michael S. Tsirkin

drivers/virtio/virtio_pci.c static void vp_del_vq(struct virtqueue *vq) · line 472

Quoted 6 lines · Michael S. Tsirkin
drivers/virtio/virtio_pci.c +3 -1
-	if (info->vector != VIRTIO_MSI_NO_VECTOR)
+	if (info->vector != VIRTIO_MSI_NO_VECTOR) {
 		free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+		--vp_dev->msix_used_vectors;
+	}

This only works because the only current caller of vp_del_vq is vp_del_vqs, so msix_used_vectors will be 0 after all the queues have been freed.

Make up your mind. Either find_vq allocates and del_vq frees, or it's find_vqs and del_vqs. I suggest the former, and setting the value VIRTIO_MSI_NO_VECTOR to indicate it's already freed. I think with some cleanups, that loop in vp_free_vectors might go away, too.

Rusty.

author maintainer
#13 lore raw

Re: [PATCH 2/2] virtio: fix double free_irq

Quoted 9 lines · Rusty Russell

drivers/virtio/virtio_pci.c static void vp_del_vq(struct virtqueue *vq) · line 472

Quoted 6 lines · Michael S. Tsirkin
drivers/virtio/virtio_pci.c +3 -1
-	if (info->vector != VIRTIO_MSI_NO_VECTOR)
+	if (info->vector != VIRTIO_MSI_NO_VECTOR) {
 		free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+		--vp_dev->msix_used_vectors;
+	}

This only works because the only current caller of vp_del_vq is vp_del_vqs,

Right

Quoted 1 line

so msix_used_vectors will be 0 after all the queues have been freed.

Not 0, actually, we have vectors for control and possibly a shared vector for all vqs.

Quoted 6 lines

Make up your mind. Either find_vq allocates and del_vq frees, or it's find_vqs and del_vqs. I suggest the former, and setting the value VIRTIO_MSI_NO_VECTOR to indicate it's already freed. I think with some cleanups, that loop in vp_free_vectors might go away, too.

Rusty.

IOW, msix_used_vectors counter will be for control and shared vector for all vqs, excluding per-vq vectors.
Makes sense. I'll put out a patch.

Signature · 1 line
MST
author maintainer
#14 lore raw

Re: [PATCH 2/2] virtio: fix double free_irq

In reply to Rusty Russell
Quoted 9 lines · Rusty Russell

drivers/virtio/virtio_pci.c static void vp_del_vq(struct virtqueue *vq) · line 472

Quoted 6 lines · Michael S. Tsirkin
drivers/virtio/virtio_pci.c +3 -1
-	if (info->vector != VIRTIO_MSI_NO_VECTOR)
+	if (info->vector != VIRTIO_MSI_NO_VECTOR) {
 		free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+		--vp_dev->msix_used_vectors;
+	}

This only works because the only current caller of vp_del_vq is vp_del_vqs,

Right

Quoted 1 line

so msix_used_vectors will be 0 after all the queues have been freed.

Not 0, actually, we have vectors for control and possibly a shared vector for all vqs.

Quoted 6 lines

Make up your mind. Either find_vq allocates and del_vq frees, or it's find_vqs and del_vqs. I suggest the former, and setting the value VIRTIO_MSI_NO_VECTOR to indicate it's already freed. I think with some cleanups, that loop in vp_free_vectors might go away, too.

Rusty.

IOW, msix_used_vectors counter will be for control and shared vector for all vqs, excluding per-vq vectors.
Makes sense. I'll put out a patch.

Signature · 1 line
MST
author maintainer
#15 lore raw

Re: [PATCH 2/2] virtio: fix double free_irq

In reply to Rusty Russell
Quoted 11 lines · Rusty Russell

drivers/virtio/virtio_pci.c static void vp_del_vq(struct virtqueue *vq) · line 472

Quoted 6 lines · Michael S. Tsirkin
drivers/virtio/virtio_pci.c +3 -1
-	if (info->vector != VIRTIO_MSI_NO_VECTOR)
+	if (info->vector != VIRTIO_MSI_NO_VECTOR) {
 		free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+		--vp_dev->msix_used_vectors;
+	}

This only works because the only current caller of vp_del_vq is vp_del_vqs, so msix_used_vectors will be 0 after all the queues have been freed.

Quoted 3 lines

Make up your mind. Either find_vq allocates and del_vq frees, or it's find_vqs and del_vqs. I suggest the former, and setting the value VIRTIO_MSI_NO_VECTOR to indicate it's already freed.

Hmm, there's nowhere to set this value: del_vq does kfree on info. But I think I see a solution. Cleaned up patch RSN.

Quoted 1 line

I think with some cleanups, that loop in vp_free_vectors might go away, too.

Hmm, I don't see how, yet.
It's there to free the common vectors: config and shared vq vector.

Quoted 7 lines

Rusty.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

author maintainer
#16 lore raw

Re: [PATCH 2/2] virtio: fix double free_irq

In reply to Rusty Russell
Quoted 11 lines · Rusty Russell

drivers/virtio/virtio_pci.c static void vp_del_vq(struct virtqueue *vq) · line 472

Quoted 6 lines · Michael S. Tsirkin
drivers/virtio/virtio_pci.c +3 -1
-	if (info->vector != VIRTIO_MSI_NO_VECTOR)
+	if (info->vector != VIRTIO_MSI_NO_VECTOR) {
 		free_irq(vp_dev->msix_entries[info->vector].vector, vq);
+		--vp_dev->msix_used_vectors;
+	}

This only works because the only current caller of vp_del_vq is vp_del_vqs, so msix_used_vectors will be 0 after all the queues have been freed.

Quoted 3 lines

Make up your mind. Either find_vq allocates and del_vq frees, or it's find_vqs and del_vqs. I suggest the former, and setting the value VIRTIO_MSI_NO_VECTOR to indicate it's already freed.

Hmm, there's nowhere to set this value: del_vq does kfree on info. But I think I see a solution. Cleaned up patch RSN.

Quoted 1 line

I think with some cleanups, that loop in vp_free_vectors might go away, too.

Hmm, I don't see how, yet.
It's there to free the common vectors: config and shared vq vector.

Quoted 7 lines

Rusty.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html