* [Qemu-devel] [PATCH v3 0/2] block/curl: Don't lose original error when a connection fails.
@ 2015-07-08 12:50 Richard W.M. Jones
2015-07-08 12:50 ` [Qemu-devel] [PATCH v3 1/2] Add a simple mechanism to protect against error message floods Richard W.M. Jones
2015-07-08 12:50 ` [Qemu-devel] [PATCH v3 2/2] block/curl: Don't lose original error when a connection fails Richard W.M. Jones
0 siblings, 2 replies; 5+ messages in thread
From: Richard W.M. Jones @ 2015-07-08 12:50 UTC (permalink / raw)
To: armbru; +Cc: kwolf, jcody, qemu-devel, qemu-block, agraf
Since v2:
This adds a generalized anti-flooding mechanism, and then uses it to
ensure that curl errors wouldn't flood the log files.
Rich.
^ permalink raw reply [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v3 1/2] Add a simple mechanism to protect against error message floods.
2015-07-08 12:50 [Qemu-devel] [PATCH v3 0/2] block/curl: Don't lose original error when a connection fails Richard W.M. Jones
@ 2015-07-08 12:50 ` Richard W.M. Jones
2015-07-08 13:26 ` Kevin Wolf
2015-07-08 12:50 ` [Qemu-devel] [PATCH v3 2/2] block/curl: Don't lose original error when a connection fails Richard W.M. Jones
1 sibling, 1 reply; 5+ messages in thread
From: Richard W.M. Jones @ 2015-07-08 12:50 UTC (permalink / raw)
To: armbru; +Cc: kwolf, jcody, qemu-devel, qemu-block, agraf
You can now write code like this:
FLOOD_COUNTER(errcount, 100);
...
NO_FLOOD(errcount,
error_report("oops, something bad happened"),
error_report("further errors suppressed"));
which would print the "oops, ..." error message up to 100 times,
followed by the "further errors suppressed" message once, and then
nothing else.
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
---
include/qemu/no-flood.h | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
create mode 100644 include/qemu/no-flood.h
diff --git a/include/qemu/no-flood.h b/include/qemu/no-flood.h
new file mode 100644
index 0000000..90a24da
--- /dev/null
+++ b/include/qemu/no-flood.h
@@ -0,0 +1,34 @@
+/*
+ * Suppress error floods.
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * Author: Richard W.M. Jones <rjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef __QEMU_NO_FLOOD_H
+#define __QEMU_NO_FLOOD_H 1
+
+#include "qemu/atomic.h"
+
+/* Suggested initial value is 100 */
+#define FLOOD_COUNTER(counter_name, initial) \
+ static int counter_name = (initial)
+
+#define NO_FLOOD(counter_name, code, suppress_message) \
+ do { \
+ int t_##counter_name = atomic_fetch_add(&counter_name, 0); \
+ if (t_##counter_name > 0) { \
+ code; \
+ if (t_##counter_name == 1) { \
+ suppress_message; \
+ } \
+ atomic_dec(&counter_name); \
+ } \
+} while (0)
+
+#endif
--
2.3.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v3 2/2] block/curl: Don't lose original error when a connection fails.
2015-07-08 12:50 [Qemu-devel] [PATCH v3 0/2] block/curl: Don't lose original error when a connection fails Richard W.M. Jones
2015-07-08 12:50 ` [Qemu-devel] [PATCH v3 1/2] Add a simple mechanism to protect against error message floods Richard W.M. Jones
@ 2015-07-08 12:50 ` Richard W.M. Jones
1 sibling, 0 replies; 5+ messages in thread
From: Richard W.M. Jones @ 2015-07-08 12:50 UTC (permalink / raw)
To: armbru; +Cc: kwolf, jcody, qemu-devel, qemu-block, agraf
Currently if qemu is connected to a curl source (eg. web server), and
the web server fails / times out / dies, you always see a bogus EIO
"Input/output error".
For example, choose a large file located on any local webserver which
you control:
$ qemu-img convert -p http://example.com/large.iso /tmp/test
Once it starts copying the file, stop the webserver and you will see
qemu-img fail with:
qemu-img: error while reading sector 61440: Input/output error
This patch does two things: Firstly print the actual error from curl
so it doesn't get lost. Secondly, change EIO to EPROTO. EPROTO is a
POSIX.1 compatible errno which more accurately reflects that there was
a protocol error, rather than some kind of hardware failure.
After this patch is applied, the error changes to:
$ qemu-img convert -p http://example.com/large.iso /tmp/test
qemu-img: curl: transfer closed with 469989 bytes remaining to read
qemu-img: error while reading sector 16384: Protocol error
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/curl.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/block/curl.c b/block/curl.c
index 3a2b63e..b72d505 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -22,6 +22,8 @@
* THE SOFTWARE.
*/
#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "qemu/no-flood.h"
#include "block/block_int.h"
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qstring.h"
@@ -298,6 +300,15 @@ static void curl_multi_check_completion(BDRVCURLState *s)
/* ACBs for successful messages get completed in curl_read_cb */
if (msg->data.result != CURLE_OK) {
int i;
+ FLOOD_COUNTER(errcount, 100);
+
+ /* Don't lose the original error message from curl, since
+ * it contains extra data.
+ */
+ NO_FLOOD(errcount,
+ error_report("curl: %s", state->errmsg),
+ error_report("curl: further errors suppressed"));
+
for (i = 0; i < CURL_NUM_ACB; i++) {
CURLAIOCB *acb = state->acb[i];
@@ -305,7 +316,7 @@ static void curl_multi_check_completion(BDRVCURLState *s)
continue;
}
- acb->common.cb(acb->common.opaque, -EIO);
+ acb->common.cb(acb->common.opaque, -EPROTO);
qemu_aio_unref(acb);
state->acb[i] = NULL;
}
--
2.3.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH v3 1/2] Add a simple mechanism to protect against error message floods.
2015-07-08 12:50 ` [Qemu-devel] [PATCH v3 1/2] Add a simple mechanism to protect against error message floods Richard W.M. Jones
@ 2015-07-08 13:26 ` Kevin Wolf
2015-07-08 13:38 ` Paolo Bonzini
0 siblings, 1 reply; 5+ messages in thread
From: Kevin Wolf @ 2015-07-08 13:26 UTC (permalink / raw)
To: Richard W.M. Jones; +Cc: agraf, jcody, armbru, qemu-block, qemu-devel
Am 08.07.2015 um 14:50 hat Richard W.M. Jones geschrieben:
> You can now write code like this:
>
> FLOOD_COUNTER(errcount, 100);
> ...
> NO_FLOOD(errcount,
> error_report("oops, something bad happened"),
> error_report("further errors suppressed"));
>
> which would print the "oops, ..." error message up to 100 times,
> followed by the "further errors suppressed" message once, and then
> nothing else.
>
> Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
> ---
> include/qemu/no-flood.h | 34 ++++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
> create mode 100644 include/qemu/no-flood.h
>
> diff --git a/include/qemu/no-flood.h b/include/qemu/no-flood.h
> new file mode 100644
> index 0000000..90a24da
> --- /dev/null
> +++ b/include/qemu/no-flood.h
> @@ -0,0 +1,34 @@
> +/*
> + * Suppress error floods.
> + *
> + * Copyright (C) 2015 Red Hat, Inc.
> + *
> + * Author: Richard W.M. Jones <rjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#ifndef __QEMU_NO_FLOOD_H
> +#define __QEMU_NO_FLOOD_H 1
> +
> +#include "qemu/atomic.h"
> +
> +/* Suggested initial value is 100 */
> +#define FLOOD_COUNTER(counter_name, initial) \
> + static int counter_name = (initial)
> +
> +#define NO_FLOOD(counter_name, code, suppress_message) \
> + do { \
> + int t_##counter_name = atomic_fetch_add(&counter_name, 0); \
> + if (t_##counter_name > 0) { \
> + code; \
> + if (t_##counter_name == 1) { \
> + suppress_message; \
> + } \
> + atomic_dec(&counter_name); \
> + } \
> +} while (0)
> +
> +#endif
I don't think that you actually achieve thread safety with the atomic
operations you use here. The counter may change between your check and
the atomic_dec().
It doesn't matter for curl because we don't get concurrency there
anyway, but it might confuse others if it looks as if it was thread safe
when it fact it isn't.
So I'd suggest that if you have an easy fix for thread safety, do it,
but otherwise don't bother and just remove the atomics.
Other than that, I like this series.
Kevin
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH v3 1/2] Add a simple mechanism to protect against error message floods.
2015-07-08 13:26 ` Kevin Wolf
@ 2015-07-08 13:38 ` Paolo Bonzini
0 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2015-07-08 13:38 UTC (permalink / raw)
To: Kevin Wolf, Richard W.M. Jones; +Cc: qemu-devel, agraf, qemu-block, armbru
On 08/07/2015 15:26, Kevin Wolf wrote:
>> +/* Suggested initial value is 100 */
>> +#define FLOOD_COUNTER(counter_name, initial) \
>> + static int counter_name = (initial)
No "static" here.
>> +#define NO_FLOOD(counter_name, code, suppress_message) \
>> + do { \
>> + int t_##counter_name = atomic_fetch_add(&counter_name, 0); \
>> + if (t_##counter_name > 0) { \
>> + code; \
>> + if (t_##counter_name == 1) { \
>> + suppress_message; \
>> + } \
>> + atomic_dec(&counter_name); \
>> + } \
>> +} while (0)
What you want is a cmpxchg loop like:
int old;
do
old = atomic_read(&counter_name);
while (old > 0 && atomic_cmpxchg(&counter_name, old, old - 1) != old);
if (old > 0) {
code;
if (old == 1) {
suppress_message;
}
}
but I would wrap it with a simple API like
void error_report_limited(int *counter, const char *s, ...);
void error_report_err_limited(int *counter, Error *err);
instead of your complex NO_FLOOD macro.
Paolo
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-07-08 13:38 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-07-08 12:50 [Qemu-devel] [PATCH v3 0/2] block/curl: Don't lose original error when a connection fails Richard W.M. Jones
2015-07-08 12:50 ` [Qemu-devel] [PATCH v3 1/2] Add a simple mechanism to protect against error message floods Richard W.M. Jones
2015-07-08 13:26 ` Kevin Wolf
2015-07-08 13:38 ` Paolo Bonzini
2015-07-08 12:50 ` [Qemu-devel] [PATCH v3 2/2] block/curl: Don't lose original error when a connection fails Richard W.M. Jones
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).