From: Kevin Wolf <kwolf@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com
Subject: [Qemu-devel] [PULL v2 for-2.1 14/22] virtio-blk: embed VirtQueueElement in VirtIOBlockReq
Date: Mon, 14 Jul 2014 13:43:04 +0200 [thread overview]
Message-ID: <1405338192-18850-15-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1405338192-18850-1-git-send-email-kwolf@redhat.com>
From: Stefan Hajnoczi <stefanha@redhat.com>
The memory allocation between hw/block/virtio-blk.c,
hw/block/dataplane/virtio-blk.c, and hw/virtio/dataplane/vring.c is
messy. Structs are allocated in different files than they are freed in.
This is risky and makes memory leaks easier.
Embed VirtQueueElement in VirtIOBlockReq to reduce the amount of memory
allocation we need to juggle. This also makes vring.c and virtio.c
slightly more similar.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
hw/block/dataplane/virtio-blk.c | 29 +++++++++++------------
hw/block/virtio-blk.c | 46 ++++++++++++++++++-------------------
hw/virtio/dataplane/vring.c | 17 +++++---------
include/hw/virtio/dataplane/vring.h | 2 +-
include/hw/virtio/virtio-blk.h | 6 ++++-
5 files changed, 48 insertions(+), 52 deletions(-)
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index bed9f13..227bb15 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -65,7 +65,7 @@ static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
{
stb_p(&req->in->status, status);
- vring_push(&req->dev->dataplane->vring, req->elem,
+ vring_push(&req->dev->dataplane->vring, &req->elem,
req->qiov.size + sizeof(*req->in));
notify_guest(req->dev->dataplane);
}
@@ -74,33 +74,32 @@ static void handle_notify(EventNotifier *e)
{
VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane,
host_notifier);
-
- VirtQueueElement *elem;
- VirtIOBlockReq *req;
- int ret;
- MultiReqBuffer mrb = {
- .num_writes = 0,
- };
+ VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
event_notifier_test_and_clear(&s->host_notifier);
bdrv_io_plug(s->blk->conf.bs);
for (;;) {
+ MultiReqBuffer mrb = {
+ .num_writes = 0,
+ };
+ int ret;
+
/* Disable guest->host notifies to avoid unnecessary vmexits */
vring_disable_notification(s->vdev, &s->vring);
for (;;) {
- ret = vring_pop(s->vdev, &s->vring, &elem);
+ VirtIOBlockReq *req = virtio_blk_alloc_request(vblk);
+
+ ret = vring_pop(s->vdev, &s->vring, &req->elem);
if (ret < 0) {
- assert(elem == NULL);
+ virtio_blk_free_request(req);
break; /* no more requests */
}
- trace_virtio_blk_data_plane_process_request(s, elem->out_num,
- elem->in_num, elem->index);
+ trace_virtio_blk_data_plane_process_request(s, req->elem.out_num,
+ req->elem.in_num,
+ req->elem.index);
- req = g_slice_new(VirtIOBlockReq);
- req->dev = VIRTIO_BLK(s->vdev);
- req->elem = elem;
virtio_blk_handle_request(req, &mrb);
}
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index b06a56d..02cd6b0 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -29,20 +29,18 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
-static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
+VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
{
VirtIOBlockReq *req = g_slice_new(VirtIOBlockReq);
req->dev = s;
req->qiov.size = 0;
req->next = NULL;
- req->elem = g_slice_new(VirtQueueElement);
return req;
}
-static void virtio_blk_free_request(VirtIOBlockReq *req)
+void virtio_blk_free_request(VirtIOBlockReq *req)
{
if (req) {
- g_slice_free(VirtQueueElement, req->elem);
g_slice_free(VirtIOBlockReq, req);
}
}
@@ -56,7 +54,7 @@ static void virtio_blk_complete_request(VirtIOBlockReq *req,
trace_virtio_blk_req_complete(req, status);
stb_p(&req->in->status, status);
- virtqueue_push(s->vq, req->elem, req->qiov.size + sizeof(*req->in));
+ virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
virtio_notify(vdev, s->vq);
}
@@ -121,7 +119,7 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
{
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
- if (!virtqueue_pop(s->vq, req->elem)) {
+ if (!virtqueue_pop(s->vq, &req->elem)) {
virtio_blk_free_request(req);
return NULL;
}
@@ -254,7 +252,7 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
{
int status;
- status = virtio_blk_handle_scsi_req(req->dev, req->elem);
+ status = virtio_blk_handle_scsi_req(req->dev, &req->elem);
virtio_blk_req_complete(req, status);
virtio_blk_free_request(req);
}
@@ -351,12 +349,12 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
uint32_t type;
- struct iovec *in_iov = req->elem->in_sg;
- struct iovec *iov = req->elem->out_sg;
- unsigned in_num = req->elem->in_num;
- unsigned out_num = req->elem->out_num;
+ struct iovec *in_iov = req->elem.in_sg;
+ struct iovec *iov = req->elem.out_sg;
+ unsigned in_num = req->elem.in_num;
+ unsigned out_num = req->elem.out_num;
- if (req->elem->out_num < 1 || req->elem->in_num < 1) {
+ if (req->elem.out_num < 1 || req->elem.in_num < 1) {
error_report("virtio-blk missing headers");
exit(1);
}
@@ -393,19 +391,19 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
* NB: per existing s/n string convention the string is
* terminated by '\0' only when shorter than buffer.
*/
- strncpy(req->elem->in_sg[0].iov_base,
+ strncpy(req->elem.in_sg[0].iov_base,
s->blk.serial ? s->blk.serial : "",
- MIN(req->elem->in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
+ MIN(req->elem.in_sg[0].iov_len, VIRTIO_BLK_ID_BYTES));
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
virtio_blk_free_request(req);
} else if (type & VIRTIO_BLK_T_OUT) {
- qemu_iovec_init_external(&req->qiov, &req->elem->out_sg[1],
- req->elem->out_num - 1);
+ qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
+ req->elem.out_num - 1);
virtio_blk_handle_write(req, mrb);
} else if (type == VIRTIO_BLK_T_IN || type == VIRTIO_BLK_T_BARRIER) {
/* VIRTIO_BLK_T_IN is 0, so we can't just & it. */
- qemu_iovec_init_external(&req->qiov, &req->elem->in_sg[0],
- req->elem->in_num - 1);
+ qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
+ req->elem.in_num - 1);
virtio_blk_handle_read(req);
} else {
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
@@ -629,7 +627,7 @@ static void virtio_blk_save_device(VirtIODevice *vdev, QEMUFile *f)
while (req) {
qemu_put_sbyte(f, 1);
- qemu_put_buffer(f, (unsigned char *)req->elem,
+ qemu_put_buffer(f, (unsigned char *)&req->elem,
sizeof(VirtQueueElement));
req = req->next;
}
@@ -654,15 +652,15 @@ static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,
while (qemu_get_sbyte(f)) {
VirtIOBlockReq *req = virtio_blk_alloc_request(s);
- qemu_get_buffer(f, (unsigned char *)req->elem,
+ qemu_get_buffer(f, (unsigned char *)&req->elem,
sizeof(VirtQueueElement));
req->next = s->rq;
s->rq = req;
- virtqueue_map_sg(req->elem->in_sg, req->elem->in_addr,
- req->elem->in_num, 1);
- virtqueue_map_sg(req->elem->out_sg, req->elem->out_addr,
- req->elem->out_num, 0);
+ virtqueue_map_sg(req->elem.in_sg, req->elem.in_addr,
+ req->elem.in_num, 1);
+ virtqueue_map_sg(req->elem.out_sg, req->elem.out_addr,
+ req->elem.out_num, 0);
}
return 0;
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 5d17d39..67cb2b8 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -301,14 +301,16 @@ static void vring_unmap_element(VirtQueueElement *elem)
* Stolen from linux/drivers/vhost/vhost.c.
*/
int vring_pop(VirtIODevice *vdev, Vring *vring,
- VirtQueueElement **p_elem)
+ VirtQueueElement *elem)
{
struct vring_desc desc;
unsigned int i, head, found = 0, num = vring->vr.num;
uint16_t avail_idx, last_avail_idx;
- VirtQueueElement *elem = NULL;
int ret;
+ /* Initialize elem so it can be safely unmapped */
+ elem->in_num = elem->out_num = 0;
+
/* If there was a fatal error then refuse operation */
if (vring->broken) {
ret = -EFAULT;
@@ -340,10 +342,8 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
* the index we've seen. */
head = vring->vr.avail->ring[last_avail_idx % num];
- elem = g_slice_new(VirtQueueElement);
elem->index = head;
- elem->in_num = elem->out_num = 0;
-
+
/* If their number is silly, that's an error. */
if (unlikely(head >= num)) {
error_report("Guest says index %u > %u is available", head, num);
@@ -391,7 +391,6 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
/* On success, increment avail index. */
vring->last_avail_idx++;
- *p_elem = elem;
return head;
out:
@@ -399,11 +398,7 @@ out:
if (ret == -EFAULT) {
vring->broken = true;
}
- if (elem) {
- vring_unmap_element(elem);
- g_slice_free(VirtQueueElement, elem);
- }
- *p_elem = NULL;
+ vring_unmap_element(elem);
return ret;
}
diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h
index b23edd2..af73ee2 100644
--- a/include/hw/virtio/dataplane/vring.h
+++ b/include/hw/virtio/dataplane/vring.h
@@ -53,7 +53,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n);
void vring_disable_notification(VirtIODevice *vdev, Vring *vring);
bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
-int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement **elem);
+int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem);
void vring_push(Vring *vring, VirtQueueElement *elem, int len);
#endif /* VRING_H */
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index b3080a2..afb7b8d 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -144,7 +144,7 @@ typedef struct MultiReqBuffer {
typedef struct VirtIOBlockReq {
VirtIOBlock *dev;
- VirtQueueElement *elem;
+ VirtQueueElement elem;
struct virtio_blk_inhdr *in;
struct virtio_blk_outhdr out;
QEMUIOVector qiov;
@@ -152,6 +152,10 @@ typedef struct VirtIOBlockReq {
BlockAcctCookie acct;
} VirtIOBlockReq;
+VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s);
+
+void virtio_blk_free_request(VirtIOBlockReq *req);
+
int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
VirtQueueElement *elem);
--
1.8.3.1
next prev parent reply other threads:[~2014-07-14 11:43 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-14 11:42 [Qemu-devel] [PULL v2 for-2.1 00/22] Block patches for 2.1.0-rc2 Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 01/22] block/backup: Fix hang for unaligned image size Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 02/22] block: Fix bdrv_is_allocated() return value Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 03/22] block: prefer aio_poll to qemu_aio_wait Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 04/22] block: drop aio functions that operate on the main AioContext Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 05/22] test-aio: fix GSource-based timer test Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 06/22] AioContext: speed up aio_notify Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 07/22] block: Make qiov match the request size until EOF Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 08/22] qcow2: Make qiov match request size until backing file EOF Kevin Wolf
2014-07-14 11:42 ` [Qemu-devel] [PULL v2 for-2.1 09/22] qed: " Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 10/22] block: Assert qiov length matches request length Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 11/22] virtio-blk: avoid dataplane VirtIOBlockReq early free Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 12/22] dataplane: do not free VirtQueueElement in vring_push() Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 13/22] virtio-blk: avoid g_slice_new0() for VirtIOBlockReq and VirtQueueElement Kevin Wolf
2014-07-14 11:43 ` Kevin Wolf [this message]
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 15/22] AioContext: do not rely on aio_poll(ctx, true) result to end a loop Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 16/22] tests: Fix unterminated string output visitor enum human string Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 17/22] qtest: fix vhost-user-test compilation with old GLib Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 18/22] dma-helpers: Fix too long qiov Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 19/22] virtio-blk: Factor common checks out of virtio_blk_handle_read/write() Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 20/22] virtio-blk: Bypass error action and I/O accounting on invalid r/w Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 21/22] virtio-blk: Treat read/write beyond end as invalid Kevin Wolf
2014-07-14 11:43 ` [Qemu-devel] [PULL v2 for-2.1 22/22] ide: " Kevin Wolf
2014-07-14 15:01 ` [Qemu-devel] [PULL v2 for-2.1 00/22] Block patches for 2.1.0-rc2 Peter Maydell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1405338192-18850-15-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).