From: Paulina Szubarczyk <paulinaszubarczyk@gmail.com>
To: Stefano Stabellini <sstabellini@kernel.org>
Cc: xen-devel@lists.xenproject.org, roger.pau@citrix.com,
wei.liu2@citrix.com, ian.jackson@eu.citrix.com,
david.vrabel@citrix.com, anthony.perard@citrix.com,
qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v6 2/2] qdisk - hw/block/xen_disk: grant copy implementation
Date: Thu, 8 Sep 2016 00:00:50 +0200 [thread overview]
Message-ID: <57D08E12.4080607@gmail.com> (raw)
In-Reply-To: <alpine.DEB.2.10.1609071320350.2359@sstabellini-ThinkPad-X260>
On 09/07/2016 10:56 PM, Stefano Stabellini wrote:
> On Wed, 7 Sep 2016, Paulina Szubarczyk wrote:
>> Copy data operated on during request from/to local buffers to/from
>> the grant references.
>>
>> Before grant copy operation local buffers must be allocated what is
>> done by calling ioreq_init_copy_buffers. For the 'read' operation,
>> first, the qemu device invokes the read operation on local buffers
>> and on the completion grant copy is called and buffers are freed.
>> For the 'write' operation grant copy is performed before invoking
>> write by qemu device.
>>
>> A new value 'feature_grant_copy' is added to recognize when the
>> grant copy operation is supported by a guest.
>>
>> Signed-off-by: Paulina Szubarczyk <paulinaszubarczyk@gmail.com>
>> ---
>> Changes since v5:
>> -added checking of every interface in the configure file. Based on
>> the Roger's comment that xengnttab_map_grant_ref was added prior
>> xengnttab_grant_copy, thus do not need to be check again here
>> I dropped this check.
>>
>
> Thank you Paulina, the patch is good. Thanks for your work! Sorry for
> coming in late in the review; I have a couple of minor suggestions
> below.
>
It had not been possible without all the help I have got. I am very
grateful for it.
> In addition to Anthony's ack, it would be also nice to have Roger's ack
> on this patch.
>
>
>> configure | 55 ++++++++++++++++
>> hw/block/xen_disk.c | 157 ++++++++++++++++++++++++++++++++++++++++++--
>> include/hw/xen/xen_common.h | 14 ++++
>> 3 files changed, 221 insertions(+), 5 deletions(-)
>>
>> diff --git a/configure b/configure
>> index 4b808f9..3f44d38 100755
>> --- a/configure
>> +++ b/configure
>> @@ -1956,6 +1956,61 @@ EOF
>> /*
>> * If we have stable libs the we don't want the libxc compat
>> * layers, regardless of what CFLAGS we may have been given.
>> + *
>> + * Also, check if xengnttab_grant_copy_segment_t is defined and
>> + * grant copy operation is implemented.
>> + */
>> +#undef XC_WANT_COMPAT_EVTCHN_API
>> +#undef XC_WANT_COMPAT_GNTTAB_API
>> +#undef XC_WANT_COMPAT_MAP_FOREIGN_API
>> +#include <xenctrl.h>
>> +#include <xenstore.h>
>> +#include <xenevtchn.h>
>> +#include <xengnttab.h>
>> +#include <xenforeignmemory.h>
>> +#include <stdint.h>
>> +#include <xen/hvm/hvm_info_table.h>
>> +#if !defined(HVM_MAX_VCPUS)
>> +# error HVM_MAX_VCPUS not defined
>> +#endif
>> +int main(void) {
>> + xc_interface *xc = NULL;
>> + xenforeignmemory_handle *xfmem;
>> + xenevtchn_handle *xe;
>> + xengnttab_handle *xg;
>> + xen_domain_handle_t handle;
>> + xengnttab_grant_copy_segment_t* seg = NULL;
>> +
>> + xs_daemon_open();
>> +
>> + xc = xc_interface_open(0, 0, 0);
>> + xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
>> + xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0);
>> + xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000);
>> + xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL);
>> + xc_domain_create(xc, 0, handle, 0, NULL, NULL);
>> +
>> + xfmem = xenforeignmemory_open(0, 0);
>> + xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0);
>> +
>> + xe = xenevtchn_open(0, 0);
>> + xenevtchn_fd(xe);
>> +
>> + xg = xengnttab_open(0, 0);
>> + xengnttab_grant_copy(xg, 0, seg);
>> +
>> + return 0;
>> +}
>> +EOF
>> + compile_prog "" "$xen_libs $xen_stable_libs"
>> + then
>> + xen_ctrl_version=480
>> + xen=yes
>> + elif
>> + cat > $TMPC <<EOF &&
>> +/*
>> + * If we have stable libs the we don't want the libxc compat
>> + * layers, regardless of what CFLAGS we may have been given.
>> */
>> #undef XC_WANT_COMPAT_EVTCHN_API
>> #undef XC_WANT_COMPAT_GNTTAB_API
>> diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c
>> index 3b8ad33..3739e13 100644
>> --- a/hw/block/xen_disk.c
>> +++ b/hw/block/xen_disk.c
>> @@ -119,6 +119,9 @@ struct XenBlkDev {
>> unsigned int persistent_gnt_count;
>> unsigned int max_grants;
>>
>> + /* Grant copy */
>> + gboolean feature_grant_copy;
>> +
>> /* qemu block driver */
>> DriveInfo *dinfo;
>> BlockBackend *blk;
>> @@ -489,6 +492,108 @@ static int ioreq_map(struct ioreq *ioreq)
>> return 0;
>> }
>>
>> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 480
>
> In general I prefer to avoid this kind of #ifdef in xen_disk.c, but I
> see that Anthony suggested it for a good reason. The only alternartive I
> can think of would be to introduce two static inline functions in
> xen_common.h to set a xengnttab_grant_copy_segment_t seg. But this is
> also OK.
>
The functions take as parameters pointers to struct ioreq defined in
xen_disk.c which members are used to fill the
xengnttab_grant_copy_segment_t. There would be some overhead to move the
functions to the header.
>
>> +static void free_buffers(struct ioreq *ioreq)
>
> Please name this function ioreq_free_copy_buffers to make it clearer
> that has to do with the same buffers initialized below.
>
>
>> +{
>> + int i;
>> +
>> + for (i = 0; i < ioreq->v.niov; i++) {
>> + ioreq->page[i] = NULL;
>> + }
>> +
>> + qemu_vfree(ioreq->pages);
>> +}
>> +
>> +static int ioreq_init_copy_buffers(struct ioreq *ioreq)
>> +{
>> + int i;
>> +
>> + if (ioreq->v.niov == 0) {
>> + return 0;
>> + }
>> +
>> + ioreq->pages = qemu_memalign(XC_PAGE_SIZE, ioreq->v.niov * XC_PAGE_SIZE);
>> +
>> + for (i = 0; i < ioreq->v.niov; i++) {
>> + ioreq->page[i] = ioreq->pages + i * XC_PAGE_SIZE;
>> + ioreq->v.iov[i].iov_base = ioreq->page[i];
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int ioreq_copy(struct ioreq *ioreq)
>
> Please name this function in a way that makes it clear that it has
> something to do with grant copies. Like for example ioreq_grant_copy.
>
I will change the names of both functions and remove the blank line
pointed below.
>
>> +{
>> + xengnttab_handle *gnt = ioreq->blkdev->xendev.gnttabdev;
>> + xengnttab_grant_copy_segment_t segs[BLKIF_MAX_SEGMENTS_PER_REQUEST];
>> + int i, count, rc;
>> + int64_t file_blk = ioreq->blkdev->file_blk;
>> +
>> + if (ioreq->v.niov == 0) {
>> + return 0;
>> + }
>> +
>> + count = ioreq->v.niov;
>> +
>> + for (i = 0; i < count; i++) {
>> +
>> + if (ioreq->req.operation == BLKIF_OP_READ) {
>> + segs[i].flags = GNTCOPY_dest_gref;
>> + segs[i].dest.foreign.ref = ioreq->refs[i];
>> + segs[i].dest.foreign.domid = ioreq->domids[i];
>> + segs[i].dest.foreign.offset = ioreq->req.seg[i].first_sect * file_blk;
>> + segs[i].source.virt = ioreq->v.iov[i].iov_base;
>> + } else {
>> + segs[i].flags = GNTCOPY_source_gref;
>> + segs[i].source.foreign.ref = ioreq->refs[i];
>> + segs[i].source.foreign.domid = ioreq->domids[i];
>> + segs[i].source.foreign.offset = ioreq->req.seg[i].first_sect * file_blk;
>> + segs[i].dest.virt = ioreq->v.iov[i].iov_base;
>> + }
>> + segs[i].len = (ioreq->req.seg[i].last_sect
>> + - ioreq->req.seg[i].first_sect + 1) * file_blk;
>> +
>> + }
>> +
>> + rc = xengnttab_grant_copy(gnt, count, segs);
>> +
>> + if (rc) {
>> + xen_be_printf(&ioreq->blkdev->xendev, 0,
>> + "failed to copy data %d\n", rc);
>> + ioreq->aio_errors++;
>> + return -1;
>> + }
>> +
>> + for (i = 0; i < count; i++) {
>> + if (segs[i].status != GNTST_okay) {
>> + xen_be_printf(&ioreq->blkdev->xendev, 3,
>> + "failed to copy data %d for gref %d, domid %d\n",
>> + segs[i].status, ioreq->refs[i], ioreq->domids[i]);
>> + ioreq->aio_errors++;
>> + rc = -1;
>> + }
>> + }
>> +
>> + return rc;
>> +}
>> +#else
>> +static void free_buffers(struct ioreq *ioreq)
>> +{
>> + abort();
>> +}
>> +
>> +static int ioreq_init_copy_buffers(struct ioreq *ioreq)
>> +{
>> + abort();
>> +}
>> +
>> +static int ioreq_copy(struct ioreq *ioreq)
>> +{
>> + abort();
>> +}
>> +#endif
>> +
>> static int ioreq_runio_qemu_aio(struct ioreq *ioreq);
>>
>> static void qemu_aio_complete(void *opaque, int ret)
>> @@ -511,8 +616,31 @@ static void qemu_aio_complete(void *opaque, int ret)
>> return;
>> }
>>
>> + if (ioreq->blkdev->feature_grant_copy) {
>> + switch (ioreq->req.operation) {
>> + case BLKIF_OP_READ:
>> + /* in case of failure ioreq->aio_errors is increased */
>> + if (ret == 0) {
>> + ioreq_copy(ioreq);
>> + }
>> + free_buffers(ioreq);
>> + break;
>> + case BLKIF_OP_WRITE:
>> + case BLKIF_OP_FLUSH_DISKCACHE:
>> + if (!ioreq->req.nr_segments) {
>> + break;
>> + }
>> + free_buffers(ioreq);
>> + break;
>> + default:
>> + break;
>> + }
>> + }
>> +
>> ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
>> - ioreq_unmap(ioreq);
>> + if (!ioreq->blkdev->feature_grant_copy) {
>> + ioreq_unmap(ioreq);
>> + }
>> ioreq_finish(ioreq);
>> switch (ioreq->req.operation) {
>> case BLKIF_OP_WRITE:
>> @@ -538,8 +666,20 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
>> {
>> struct XenBlkDev *blkdev = ioreq->blkdev;
>>
>> - if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) {
>> - goto err_no_map;
>> + if (ioreq->blkdev->feature_grant_copy) {
>> + ioreq_init_copy_buffers(ioreq);
>> + if (ioreq->req.nr_segments && (ioreq->req.operation == BLKIF_OP_WRITE ||
>> + ioreq->req.operation == BLKIF_OP_FLUSH_DISKCACHE)) {
>> + if (ioreq_copy(ioreq)) {
>> + free_buffers(ioreq);
>> + goto err;
>> + }
>> + }
>> +
>
> Please remove blank this line (it looks a bit odd)
>
>
>> + } else {
>> + if (ioreq->req.nr_segments && ioreq_map(ioreq)) {
>> + goto err;
>> + }
>> }
>>
>> ioreq->aio_inflight++;
>> @@ -582,6 +722,9 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
>> }
>> default:
>> /* unknown operation (shouldn't happen -- parse catches this) */
>> + if (!ioreq->blkdev->feature_grant_copy) {
>> + ioreq_unmap(ioreq);
>> + }
>
> Why are you adding this? Is it a bug fix? If so, please explain in the
> commit message.
>
It is not a bug fix. In the ioreq_runio_qemu_aio there were two error
labels 'err_no_map' and 'err' each of them used once. So before the
patch the labels are looking this way:
err:
ioreq_unmap(ioreq);
err_no_map:
ioreq_finish(ioreq);
ioreq->status = BLKIF_RSP_ERROR;
return -1;
I removed the 'err_no_map' label and from the 'err' section I removed
the ioreq_unmap. The 'err' label was previously used in that default
section of the switch because the grant_map is called regardless the
ioreq->req.operation.
In the patch, there is no need for any special behavior for grant_copy,
because buffers were not allocated in this case, so there is only jump
to 'err'.
An advantage of this change is one unified error path for both grant
operations.
>
>> goto err;
>> }
>>
>> @@ -590,8 +733,6 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
>> return 0;
>>
>> err:
>> - ioreq_unmap(ioreq);
>> -err_no_map:
>> ioreq_finish(ioreq);
>> ioreq->status = BLKIF_RSP_ERROR;
>> return -1;
>> @@ -1032,6 +1173,12 @@ static int blk_connect(struct XenDevice *xendev)
>>
>> xen_be_bind_evtchn(&blkdev->xendev);
>>
>> + blkdev->feature_grant_copy =
>> + (xengnttab_grant_copy(blkdev->xendev.gnttabdev, 0, NULL) == 0);
>> +
>> + xen_be_printf(&blkdev->xendev, 3, "grant copy operation %s\n",
>> + blkdev->feature_grant_copy ? "enabled" : "disabled");
>> +
>> xen_be_printf(&blkdev->xendev, 1, "ok: proto %s, ring-ref %d, "
>> "remote port %d, local port %d\n",
>> blkdev->xendev.protocol, blkdev->ring_ref,
>> diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
>> index bd39287..8e1580d 100644
>> --- a/include/hw/xen/xen_common.h
>> +++ b/include/hw/xen/xen_common.h
>> @@ -424,4 +424,18 @@ static inline int xen_domain_create(xc_interface *xc, uint32_t ssidref,
>> #endif
>> #endif
>>
>> +/* Xen before 4.8 */
>> +
>> +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 480
>> +
>> +
>> +typedef void *xengnttab_grant_copy_segment_t;
>> +
>> +static inline int xengnttab_grant_copy(xengnttab_handle *xgt, uint32_t count,
>> + xengnttab_grant_copy_segment_t *segs)
>> +{
>> + return -ENOSYS;
>> +}
>> +#endif
>> +
>> #endif /* QEMU_HW_XEN_COMMON_H */
>> --
>> 1.9.1
>>
Paulina
next prev parent reply other threads:[~2016-09-07 22:01 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-07 10:40 [Qemu-devel] [PATCH v6 0/2] qemu-qdisk: Implementation of grant copy operation Paulina Szubarczyk
2016-09-07 10:40 ` Paulina Szubarczyk
2016-09-07 10:40 ` [Qemu-devel] [PATCH v6 1/2] libs/gnttab: introduce grant copy interface Paulina Szubarczyk
2016-09-07 10:40 ` Paulina Szubarczyk
2016-09-07 10:41 ` [Qemu-devel] [PATCH v6 2/2] qdisk - hw/block/xen_disk: grant copy implementation Paulina Szubarczyk
2016-09-07 10:41 ` Paulina Szubarczyk
2016-09-07 17:05 ` [Qemu-devel] " Anthony PERARD
2016-09-07 17:05 ` Anthony PERARD
2016-09-07 20:56 ` Stefano Stabellini
2016-09-07 20:56 ` [Qemu-devel] " Stefano Stabellini
2016-09-07 22:00 ` Paulina Szubarczyk [this message]
2016-09-08 18:40 ` Stefano Stabellini
2016-09-08 18:40 ` [Qemu-devel] " Stefano Stabellini
2016-09-09 12:32 ` Paulina Szubarczyk
2016-09-09 12:32 ` Paulina Szubarczyk
2016-09-07 22:00 ` Paulina Szubarczyk
2016-09-12 16:06 ` [Qemu-devel] " Roger Pau Monné
2016-09-12 16:06 ` Roger Pau Monné
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=57D08E12.4080607@gmail.com \
--to=paulinaszubarczyk@gmail.com \
--cc=anthony.perard@citrix.com \
--cc=david.vrabel@citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=qemu-devel@nongnu.org \
--cc=roger.pau@citrix.com \
--cc=sstabellini@kernel.org \
--cc=wei.liu2@citrix.com \
--cc=xen-devel@lists.xenproject.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.