* [PATCH for-5.0] xen-block: Fix double qlist remove
@ 2020-04-02 13:08 Anthony PERARD
2020-04-02 14:27 ` Paul Durrant
0 siblings, 1 reply; 6+ messages in thread
From: Anthony PERARD @ 2020-04-02 13:08 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Stefano Stabellini, qemu-block, Paul Durrant,
qemu-stable, Max Reitz, Stefan Hajnoczi, Anthony PERARD,
xen-devel
Commit a31ca6801c02 ("qemu/queue.h: clear linked list pointers on
remove") revealed that a request was removed twice from a list, once
in xen_block_finish_request() and a second time in
xen_block_release_request() when both function are called from
xen_block_complete_aio(). But also, the `requests_inflight' counter is
decreased twice, and thus became negative.
This is a bug that was introduced in bfd0d6366043, where a `finished'
list was removed.
This patch simply re-add the `finish' parameter of
xen_block_release_request() so that we can distinguish when we need to
remove a request from the inflight list and when not.
Fixes: bfd0d6366043 ("xen-block: improve response latency")
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
hw/block/dataplane/xen-block.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index 288a87a814ad..6cc089fc561f 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -123,15 +123,19 @@ static void xen_block_finish_request(XenBlockRequest *request)
dataplane->requests_inflight--;
}
-static void xen_block_release_request(XenBlockRequest *request)
+static void xen_block_release_request(XenBlockRequest *request, bool finish)
{
XenBlockDataPlane *dataplane = request->dataplane;
- QLIST_REMOVE(request, list);
+ if (!finish) {
+ QLIST_REMOVE(request, list);
+ }
reset_request(request);
request->dataplane = dataplane;
QLIST_INSERT_HEAD(&dataplane->freelist, request, list);
- dataplane->requests_inflight--;
+ if (!finish) {
+ dataplane->requests_inflight--;
+ }
}
/*
@@ -316,7 +320,7 @@ static void xen_block_complete_aio(void *opaque, int ret)
error_report_err(local_err);
}
}
- xen_block_release_request(request);
+ xen_block_release_request(request, true);
if (dataplane->more_work) {
qemu_bh_schedule(dataplane->bh);
@@ -585,7 +589,7 @@ static bool xen_block_handle_requests(XenBlockDataPlane *dataplane)
error_report_err(local_err);
}
}
- xen_block_release_request(request);
+ xen_block_release_request(request, false);
continue;
}
--
Anthony PERARD
^ permalink raw reply related [flat|nested] 6+ messages in thread
* RE: [PATCH for-5.0] xen-block: Fix double qlist remove
2020-04-02 13:08 [PATCH for-5.0] xen-block: Fix double qlist remove Anthony PERARD
@ 2020-04-02 14:27 ` Paul Durrant
2020-04-06 10:59 ` Anthony PERARD
0 siblings, 1 reply; 6+ messages in thread
From: Paul Durrant @ 2020-04-02 14:27 UTC (permalink / raw)
To: 'Anthony PERARD', qemu-devel
Cc: 'Kevin Wolf', 'Stefano Stabellini',
qemu-block, qemu-stable, 'Max Reitz',
'Stefan Hajnoczi',
xen-devel
> -----Original Message-----
> From: Anthony PERARD <anthony.perard@citrix.com>
> Sent: 02 April 2020 14:08
> To: qemu-devel@nongnu.org
> Cc: qemu-stable@nongnu.org; Anthony PERARD <anthony.perard@citrix.com>; Stefano Stabellini
> <sstabellini@kernel.org>; Paul Durrant <paul@xen.org>; Stefan Hajnoczi <stefanha@redhat.com>; Kevin
> Wolf <kwolf@redhat.com>; Max Reitz <mreitz@redhat.com>; xen-devel@lists.xenproject.org; qemu-
> block@nongnu.org
> Subject: [PATCH for-5.0] xen-block: Fix double qlist remove
>
> Commit a31ca6801c02 ("qemu/queue.h: clear linked list pointers on
> remove") revealed that a request was removed twice from a list, once
> in xen_block_finish_request() and a second time in
> xen_block_release_request() when both function are called from
> xen_block_complete_aio(). But also, the `requests_inflight' counter is
> decreased twice, and thus became negative.
>
> This is a bug that was introduced in bfd0d6366043, where a `finished'
> list was removed.
>
> This patch simply re-add the `finish' parameter of
> xen_block_release_request() so that we can distinguish when we need to
> remove a request from the inflight list and when not.
>
> Fixes: bfd0d6366043 ("xen-block: improve response latency")
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
It looks to me like it would just be more straightforward to simply drop the QLIST_REMOVE and requests_inflight-- from
xen_block_release_request() and simply insist that xen_block_finish_request() is called in all cases (which I think means adding one
extra call to it in xen_block_handle_requests()).
Paul
> ---
> hw/block/dataplane/xen-block.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
>
> diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
> index 288a87a814ad..6cc089fc561f 100644
> --- a/hw/block/dataplane/xen-block.c
> +++ b/hw/block/dataplane/xen-block.c
> @@ -123,15 +123,19 @@ static void xen_block_finish_request(XenBlockRequest *request)
> dataplane->requests_inflight--;
> }
>
> -static void xen_block_release_request(XenBlockRequest *request)
> +static void xen_block_release_request(XenBlockRequest *request, bool finish)
> {
> XenBlockDataPlane *dataplane = request->dataplane;
>
> - QLIST_REMOVE(request, list);
> + if (!finish) {
> + QLIST_REMOVE(request, list);
> + }
> reset_request(request);
> request->dataplane = dataplane;
> QLIST_INSERT_HEAD(&dataplane->freelist, request, list);
> - dataplane->requests_inflight--;
> + if (!finish) {
> + dataplane->requests_inflight--;
> + }
> }
>
> /*
> @@ -316,7 +320,7 @@ static void xen_block_complete_aio(void *opaque, int ret)
> error_report_err(local_err);
> }
> }
> - xen_block_release_request(request);
> + xen_block_release_request(request, true);
>
> if (dataplane->more_work) {
> qemu_bh_schedule(dataplane->bh);
> @@ -585,7 +589,7 @@ static bool xen_block_handle_requests(XenBlockDataPlane *dataplane)
> error_report_err(local_err);
> }
> }
> - xen_block_release_request(request);
> + xen_block_release_request(request, false);
> continue;
> }
>
> --
> Anthony PERARD
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH for-5.0] xen-block: Fix double qlist remove
2020-04-02 14:27 ` Paul Durrant
@ 2020-04-06 10:59 ` Anthony PERARD
2020-04-06 14:02 ` [PATCH v2 for-5.0] xen-block: Fix double qlist remove and request leak Anthony PERARD
0 siblings, 1 reply; 6+ messages in thread
From: Anthony PERARD @ 2020-04-06 10:59 UTC (permalink / raw)
To: paul
Cc: 'Kevin Wolf', 'Stefano Stabellini',
qemu-block, qemu-stable, qemu-devel, 'Max Reitz',
'Stefan Hajnoczi',
xen-devel
On Thu, Apr 02, 2020 at 03:27:22PM +0100, Paul Durrant wrote:
> > -----Original Message-----
> > From: Anthony PERARD <anthony.perard@citrix.com>
> > Sent: 02 April 2020 14:08
> > To: qemu-devel@nongnu.org
> > Cc: qemu-stable@nongnu.org; Anthony PERARD <anthony.perard@citrix.com>; Stefano Stabellini
> > <sstabellini@kernel.org>; Paul Durrant <paul@xen.org>; Stefan Hajnoczi <stefanha@redhat.com>; Kevin
> > Wolf <kwolf@redhat.com>; Max Reitz <mreitz@redhat.com>; xen-devel@lists.xenproject.org; qemu-
> > block@nongnu.org
> > Subject: [PATCH for-5.0] xen-block: Fix double qlist remove
> >
> > Commit a31ca6801c02 ("qemu/queue.h: clear linked list pointers on
> > remove") revealed that a request was removed twice from a list, once
> > in xen_block_finish_request() and a second time in
> > xen_block_release_request() when both function are called from
> > xen_block_complete_aio(). But also, the `requests_inflight' counter is
> > decreased twice, and thus became negative.
> >
> > This is a bug that was introduced in bfd0d6366043, where a `finished'
> > list was removed.
> >
> > This patch simply re-add the `finish' parameter of
> > xen_block_release_request() so that we can distinguish when we need to
> > remove a request from the inflight list and when not.
> >
> > Fixes: bfd0d6366043 ("xen-block: improve response latency")
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
>
> It looks to me like it would just be more straightforward to simply drop the QLIST_REMOVE and requests_inflight-- from
> xen_block_release_request() and simply insist that xen_block_finish_request() is called in all cases (which I think means adding one
> extra call to it in xen_block_handle_requests()).
I'm thinking of going further than that. I've notice another bug, in
case of error in xen_block_do_aio(), xen_block_finish_request() is
called without ever calling send_response() or release_request(). I
think that mean a leak of request.
So, I'm thinking of creating a function that would do finish_request(),
send_response(), release_request(), has I believe those operations needs
to be done together anyway.
I'll rework the patch.
--
Anthony PERARD
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 for-5.0] xen-block: Fix double qlist remove and request leak
2020-04-06 10:59 ` Anthony PERARD
@ 2020-04-06 14:02 ` Anthony PERARD
2020-04-06 14:34 ` Paul Durrant
2020-04-07 11:50 ` Max Reitz
0 siblings, 2 replies; 6+ messages in thread
From: Anthony PERARD @ 2020-04-06 14:02 UTC (permalink / raw)
To: qemu-devel
Cc: Kevin Wolf, Stefano Stabellini, qemu-block, Paul Durrant,
qemu-stable, Max Reitz, Stefan Hajnoczi, Anthony PERARD,
xen-devel
Commit a31ca6801c02 ("qemu/queue.h: clear linked list pointers on
remove") revealed that a request was removed twice from a list, once
in xen_block_finish_request() and a second time in
xen_block_release_request() when both function are called from
xen_block_complete_aio(). But also, the `requests_inflight' counter is
decreased twice, and thus became negative.
This is a bug that was introduced in bfd0d6366043, where a `finished'
list was removed.
That commit also introduced a leak of request in xen_block_do_aio().
That function calls xen_block_finish_request() but the request is
never released after that.
To fix both issue, we do two changes:
- we squash finish_request() and release_request() together as we want
to remove a request from 'inflight' list to add it to 'freelist'.
- before releasing a request, we need to let now the result to the
other end, thus we should call xen_block_send_response() before
releasing a request.
The first change fix the double QLIST_REMOVE() as we remove the extra
call. The second change makes the leak go away because if we want to
call finish_request(), we need to call a function that do all of
finish, send response, and release.
Fixes: bfd0d6366043 ("xen-block: improve response latency")
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
---
hw/block/dataplane/xen-block.c | 48 ++++++++++++----------------------
1 file changed, 16 insertions(+), 32 deletions(-)
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index 288a87a814ad..5f8f15778ba5 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -64,6 +64,8 @@ struct XenBlockDataPlane {
AioContext *ctx;
};
+static int xen_block_send_response(XenBlockRequest *request);
+
static void reset_request(XenBlockRequest *request)
{
memset(&request->req, 0, sizeof(request->req));
@@ -115,23 +117,26 @@ static XenBlockRequest *xen_block_start_request(XenBlockDataPlane *dataplane)
return request;
}
-static void xen_block_finish_request(XenBlockRequest *request)
+static void xen_block_complete_request(XenBlockRequest *request)
{
XenBlockDataPlane *dataplane = request->dataplane;
- QLIST_REMOVE(request, list);
- dataplane->requests_inflight--;
-}
+ if (xen_block_send_response(request)) {
+ Error *local_err = NULL;
-static void xen_block_release_request(XenBlockRequest *request)
-{
- XenBlockDataPlane *dataplane = request->dataplane;
+ xen_device_notify_event_channel(dataplane->xendev,
+ dataplane->event_channel,
+ &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ }
+ }
QLIST_REMOVE(request, list);
+ dataplane->requests_inflight--;
reset_request(request);
request->dataplane = dataplane;
QLIST_INSERT_HEAD(&dataplane->freelist, request, list);
- dataplane->requests_inflight--;
}
/*
@@ -246,7 +251,6 @@ static int xen_block_copy_request(XenBlockRequest *request)
}
static int xen_block_do_aio(XenBlockRequest *request);
-static int xen_block_send_response(XenBlockRequest *request);
static void xen_block_complete_aio(void *opaque, int ret)
{
@@ -286,7 +290,6 @@ static void xen_block_complete_aio(void *opaque, int ret)
}
request->status = request->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
- xen_block_finish_request(request);
switch (request->req.operation) {
case BLKIF_OP_WRITE:
@@ -306,17 +309,8 @@ static void xen_block_complete_aio(void *opaque, int ret)
default:
break;
}
- if (xen_block_send_response(request)) {
- Error *local_err = NULL;
- xen_device_notify_event_channel(dataplane->xendev,
- dataplane->event_channel,
- &local_err);
- if (local_err) {
- error_report_err(local_err);
- }
- }
- xen_block_release_request(request);
+ xen_block_complete_request(request);
if (dataplane->more_work) {
qemu_bh_schedule(dataplane->bh);
@@ -420,8 +414,8 @@ static int xen_block_do_aio(XenBlockRequest *request)
return 0;
err:
- xen_block_finish_request(request);
request->status = BLKIF_RSP_ERROR;
+ xen_block_complete_request(request);
return -1;
}
@@ -575,17 +569,7 @@ static bool xen_block_handle_requests(XenBlockDataPlane *dataplane)
break;
};
- if (xen_block_send_response(request)) {
- Error *local_err = NULL;
-
- xen_device_notify_event_channel(dataplane->xendev,
- dataplane->event_channel,
- &local_err);
- if (local_err) {
- error_report_err(local_err);
- }
- }
- xen_block_release_request(request);
+ xen_block_complete_request(request);
continue;
}
--
Anthony PERARD
^ permalink raw reply related [flat|nested] 6+ messages in thread
* RE: [PATCH v2 for-5.0] xen-block: Fix double qlist remove and request leak
2020-04-06 14:02 ` [PATCH v2 for-5.0] xen-block: Fix double qlist remove and request leak Anthony PERARD
@ 2020-04-06 14:34 ` Paul Durrant
2020-04-07 11:50 ` Max Reitz
1 sibling, 0 replies; 6+ messages in thread
From: Paul Durrant @ 2020-04-06 14:34 UTC (permalink / raw)
To: 'Anthony PERARD', qemu-devel
Cc: 'Kevin Wolf', 'Stefano Stabellini',
qemu-block, qemu-stable, 'Max Reitz',
'Stefan Hajnoczi',
xen-devel
> -----Original Message-----
> From: Anthony PERARD <anthony.perard@citrix.com>
> Sent: 06 April 2020 15:02
> To: qemu-devel@nongnu.org
> Cc: qemu-stable@nongnu.org; Anthony PERARD <anthony.perard@citrix.com>; Stefano Stabellini
> <sstabellini@kernel.org>; Paul Durrant <paul@xen.org>; Stefan Hajnoczi <stefanha@redhat.com>; Kevin
> Wolf <kwolf@redhat.com>; Max Reitz <mreitz@redhat.com>; xen-devel@lists.xenproject.org; qemu-
> block@nongnu.org
> Subject: [PATCH v2 for-5.0] xen-block: Fix double qlist remove and request leak
>
> Commit a31ca6801c02 ("qemu/queue.h: clear linked list pointers on
> remove") revealed that a request was removed twice from a list, once
> in xen_block_finish_request() and a second time in
> xen_block_release_request() when both function are called from
> xen_block_complete_aio(). But also, the `requests_inflight' counter is
> decreased twice, and thus became negative.
>
> This is a bug that was introduced in bfd0d6366043
NIT: I guess you should quote the patch title here as well.
> , where a `finished'
> list was removed.
>
> That commit also introduced a leak of request in xen_block_do_aio().
> That function calls xen_block_finish_request() but the request is
> never released after that.
>
> To fix both issue, we do two changes:
> - we squash finish_request() and release_request() together as we want
> to remove a request from 'inflight' list to add it to 'freelist'.
> - before releasing a request, we need to let now the result to the
> other end,
"we need to let the other end know the result"
> thus we should call xen_block_send_response() before
> releasing a request.
>
> The first change fix the double QLIST_REMOVE() as we remove the extra
s/fix/fixes
> call. The second change makes the leak go away because if we want to
> call finish_request(), we need to call a function that do all of
s/do/does
> finish, send response, and release.
>
> Fixes: bfd0d6366043 ("xen-block: improve response latency")
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
The code looks ok, so with the cosmetic fixes...
Reviewed-by: Paul Durrant <paul@xen.org>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 for-5.0] xen-block: Fix double qlist remove and request leak
2020-04-06 14:02 ` [PATCH v2 for-5.0] xen-block: Fix double qlist remove and request leak Anthony PERARD
2020-04-06 14:34 ` Paul Durrant
@ 2020-04-07 11:50 ` Max Reitz
1 sibling, 0 replies; 6+ messages in thread
From: Max Reitz @ 2020-04-07 11:50 UTC (permalink / raw)
To: Anthony PERARD, qemu-devel
Cc: Kevin Wolf, Stefano Stabellini, qemu-block, Paul Durrant,
qemu-stable, Stefan Hajnoczi, xen-devel
[-- Attachment #1.1: Type: text/plain, Size: 1804 bytes --]
On 06.04.20 16:02, Anthony PERARD wrote:
> Commit a31ca6801c02 ("qemu/queue.h: clear linked list pointers on
> remove") revealed that a request was removed twice from a list, once
> in xen_block_finish_request() and a second time in
> xen_block_release_request() when both function are called from
> xen_block_complete_aio(). But also, the `requests_inflight' counter is
> decreased twice, and thus became negative.
>
> This is a bug that was introduced in bfd0d6366043, where a `finished'
> list was removed.
>
> That commit also introduced a leak of request in xen_block_do_aio().
> That function calls xen_block_finish_request() but the request is
> never released after that.
>
> To fix both issue, we do two changes:
> - we squash finish_request() and release_request() together as we want
> to remove a request from 'inflight' list to add it to 'freelist'.
> - before releasing a request, we need to let now the result to the
> other end, thus we should call xen_block_send_response() before
> releasing a request.
>
> The first change fix the double QLIST_REMOVE() as we remove the extra
> call. The second change makes the leak go away because if we want to
> call finish_request(), we need to call a function that do all of
> finish, send response, and release.
>
> Fixes: bfd0d6366043 ("xen-block: improve response latency")
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
> hw/block/dataplane/xen-block.c | 48 ++++++++++++----------------------
> 1 file changed, 16 insertions(+), 32 deletions(-)
I’m going to send a pull request today anyway, so I hope you won’t mind
and let me take this patch to my branch (with Paul’s suggestions
incorporated):
https://git.xanclic.moe/XanClic/qemu/commits/branch/block
Max
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-04-07 11:51 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-02 13:08 [PATCH for-5.0] xen-block: Fix double qlist remove Anthony PERARD
2020-04-02 14:27 ` Paul Durrant
2020-04-06 10:59 ` Anthony PERARD
2020-04-06 14:02 ` [PATCH v2 for-5.0] xen-block: Fix double qlist remove and request leak Anthony PERARD
2020-04-06 14:34 ` Paul Durrant
2020-04-07 11:50 ` Max Reitz
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.