26ba25
From cb9a84154c755daf0c9361346302ad41a1804ecc Mon Sep 17 00:00:00 2001
26ba25
From: Peter Xu <peterx@redhat.com>
26ba25
Date: Thu, 8 Nov 2018 06:29:32 +0000
26ba25
Subject: [PATCH 04/35] qemu-error: introduce {error|warn}_report_once
26ba25
MIME-Version: 1.0
26ba25
Content-Type: text/plain; charset=UTF-8
26ba25
Content-Transfer-Encoding: 8bit
26ba25
26ba25
RH-Author: Peter Xu <peterx@redhat.com>
26ba25
Message-id: <20181108062938.21143-2-peterx@redhat.com>
26ba25
Patchwork-id: 82959
26ba25
O-Subject: [RHEL-8 qemu-kvm PATCH 1/7] qemu-error: introduce {error|warn}_report_once
26ba25
Bugzilla: 1625173
26ba25
RH-Acked-by: Auger Eric <eric.auger@redhat.com>
26ba25
RH-Acked-by: Michael S. Tsirkin <mst@redhat.com>
26ba25
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
26ba25
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
26ba25
26ba25
Bugzilla: 1625173
26ba25
26ba25
There are many error_report()s that can be used in frequently called
26ba25
functions, especially on IO paths.  That can be unideal in that
26ba25
malicious guest can try to trigger the error tons of time which might
26ba25
use up the log space on the host (e.g., libvirt can capture the stderr
26ba25
of QEMU and put it persistently onto disk).  In VT-d emulation code, we
26ba25
have trace_vtd_error() tracer.  AFAIU all those places can be replaced
26ba25
by something like error_report() but trace points are mostly used to
26ba25
avoid the DDOS attack that mentioned above.  However using trace points
26ba25
mean that errors are not dumped if trace not enabled.
26ba25
26ba25
It's not a big deal in most modern server managements since we have
26ba25
things like logrotate to maintain the logs and make sure the quota is
26ba25
expected.  However it'll still be nice that we just provide another way
26ba25
to restrict message generations.  In most cases, this kind of
26ba25
error_report()s will only provide valid information on the first message
26ba25
sent, and all the rest of similar messages will be mostly talking about
26ba25
the same thing.  This patch introduces *_report_once() helpers to allow
26ba25
a message to be dumped only once during one QEMU process's life cycle.
26ba25
It will make sure: (1) it's on by deffault, so we can even get something
26ba25
without turning the trace on and reproducing, and (2) it won't be
26ba25
affected by DDOS attack.
26ba25
26ba25
To implement it, I stole the printk_once() macro from Linux.
26ba25
26ba25
CC: Eric Blake <eblake@redhat.com>
26ba25
CC: Markus Armbruster <armbru@redhat.com>
26ba25
Signed-off-by: Peter Xu <peterx@redhat.com>
26ba25
Message-Id: <20180815095328.32414-2-peterx@redhat.com>
26ba25
Reviewed-by: Markus Armbruster <armbru@redhat.com>
26ba25
[Whitespace adjusted, comments improved]
26ba25
Signed-off-by: Markus Armbruster <armbru@redhat.com>
26ba25
(cherry picked from commit bc6a69dd4bfa41ae56235dcbb9a28a56e12a7dc6)
26ba25
Signed-off-by: Peter Xu <peterx@redhat.com>
26ba25
26ba25
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
26ba25
---
26ba25
 include/qemu/error-report.h | 32 ++++++++++++++++++++++++++++++++
26ba25
 1 file changed, 32 insertions(+)
26ba25
26ba25
diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h
26ba25
index e1c8ae1..72fab2b 100644
26ba25
--- a/include/qemu/error-report.h
26ba25
+++ b/include/qemu/error-report.h
26ba25
@@ -44,6 +44,38 @@ void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
26ba25
 void warn_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
26ba25
 void info_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
26ba25
 
26ba25
+/*
26ba25
+ * Similar to error_report(), except it prints the message just once.
26ba25
+ * Return true when it prints, false otherwise.
26ba25
+ */
26ba25
+#define error_report_once(fmt, ...)             \
26ba25
+    ({                                          \
26ba25
+        static bool print_once_;                \
26ba25
+        bool ret_print_once_ = !print_once_;    \
26ba25
+                                                \
26ba25
+        if (!print_once_) {                     \
26ba25
+            print_once_ = true;                 \
26ba25
+            error_report(fmt, ##__VA_ARGS__);   \
26ba25
+        }                                       \
26ba25
+        unlikely(ret_print_once_);              \
26ba25
+    })
26ba25
+
26ba25
+/*
26ba25
+ * Similar to warn_report(), except it prints the message just once.
26ba25
+ * Return true when it prints, false otherwise.
26ba25
+ */
26ba25
+#define warn_report_once(fmt, ...)              \
26ba25
+    ({                                          \
26ba25
+        static bool print_once_;                \
26ba25
+        bool ret_print_once_ = !print_once_;    \
26ba25
+                                                \
26ba25
+        if (!print_once_) {                     \
26ba25
+            print_once_ = true;                 \
26ba25
+            warn_report(fmt, ##__VA_ARGS__);    \
26ba25
+        }                                       \
26ba25
+        unlikely(ret_print_once_);              \
26ba25
+    })
26ba25
+
26ba25
 const char *error_get_progname(void);
26ba25
 extern bool enable_timestamp_msg;
26ba25
 
26ba25
-- 
26ba25
1.8.3.1
26ba25