diff mbox

[2/3] s390/virtio-ccw: Fix setup_vq error handling.

Message ID 1359124457-51126-3-git-send-email-borntraeger@de.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Christian Borntraeger Jan. 25, 2013, 2:34 p.m. UTC
virtio_ccw_setup_vq() failed to unwind correctly on errors. In
particular, it failed to delete the virtqueue on errors, leading to
list corruption when virtio_ccw_del_vqs() iterated over a virtqueue
that had not been added to the vcdev's list.

Fix this with redoing the error unwinding in virtio_ccw_setup_vq(),
using a single path for all errors.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 drivers/s390/kvm/virtio_ccw.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

Comments

Christian Borntraeger Jan. 25, 2013, 2:35 p.m. UTC | #1
On 25/01/13 15:34, Christian Borntraeger wrote:
> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>

Sorry, I messed up the From.
Should I resend or can you change the author to "Cornelia Huck <cornelia.huck@de.ibm.com>"

Christian

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

Patch

diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c
index 2edd94a..3217dfe 100644
--- a/drivers/s390/kvm/virtio_ccw.c
+++ b/drivers/s390/kvm/virtio_ccw.c
@@ -244,9 +244,9 @@  static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
 {
 	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
 	int err;
-	struct virtqueue *vq;
+	struct virtqueue *vq = NULL;
 	struct virtio_ccw_vq_info *info;
-	unsigned long size;
+	unsigned long size = 0; /* silence the compiler */
 	unsigned long flags;
 
 	/* Allocate queue. */
@@ -279,11 +279,8 @@  static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
 		/* For now, we fail if we can't get the requested size. */
 		dev_warn(&vcdev->cdev->dev, "no vq\n");
 		err = -ENOMEM;
-		free_pages_exact(info->queue, size);
 		goto out_err;
 	}
-	info->vq = vq;
-	vq->priv = info;
 
 	/* Register it with the host. */
 	info->info_block->queue = (__u64)info->queue;
@@ -297,12 +294,12 @@  static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
 	err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i);
 	if (err) {
 		dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n");
-		free_pages_exact(info->queue, size);
-		info->vq = NULL;
-		vq->priv = NULL;
 		goto out_err;
 	}
 
+	info->vq = vq;
+	vq->priv = info;
+
 	/* Save it to our list. */
 	spin_lock_irqsave(&vcdev->lock, flags);
 	list_add(&info->node, &vcdev->virtqueues);
@@ -311,8 +308,13 @@  static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
 	return vq;
 
 out_err:
-	if (info)
+	if (vq)
+		vring_del_virtqueue(vq);
+	if (info) {
+		if (info->queue)
+			free_pages_exact(info->queue, size);
 		kfree(info->info_block);
+	}
 	kfree(info);
 	return ERR_PTR(err);
 }