diff --git a/SOURCES/kvm-error-Document-Error-API-usage-rules.patch b/SOURCES/kvm-error-Document-Error-API-usage-rules.patch
new file mode 100644
index 0000000..026b81a
--- /dev/null
+++ b/SOURCES/kvm-error-Document-Error-API-usage-rules.patch
@@ -0,0 +1,156 @@
+From d931195ef5cccd6a4e6fceeba37809b1712c97ad Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:40:55 -0500
+Subject: [PATCH 04/10] error: Document Error API usage rules
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-5-marcandre.lureau@redhat.com>
+Patchwork-id: 100523
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 04/10] error: Document Error API usage rules
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Markus Armbruster <armbru@redhat.com>
+
+This merely codifies existing practice, with one exception: the rule
+advising against returning void, where existing practice is mixed.
+
+When the Error API was created, we adopted the (unwritten) rule to
+return void when the function returns no useful value on success,
+unlike GError, which recommends to return true on success and false on
+error then.
+
+When a function returns a distinct error value, say false, a checked
+call that passes the error up looks like
+
+    if (!frobnicate(..., errp)) {
+        handle the error...
+    }
+
+When it returns void, we need
+
+    Error *err = NULL;
+
+    frobnicate(..., &err);
+    if (err) {
+        handle the error...
+        error_propagate(errp, err);
+    }
+
+Not only is this more verbose, it also creates an Error object even
+when @errp is null, &error_abort or &error_fatal.
+
+People got tired of the additional boilerplate, and started to ignore
+the unwritten rule.  The result is confusion among developers about
+the preferred usage.
+
+Make the rule advising against returning void official by putting it
+in writing.  This will hopefully reduce confusion.
+
+Update the examples accordingly.
+
+The remainder of this series will update a substantial amount of code
+to honor the rule.
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+Message-Id: <20200707160613.848843-4-armbru@redhat.com>
+
+(cherry picked from commit e3fe3988d7851cac30abffae06d2f555ff7bee62)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ include/qapi/error.h | 52 +++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 46 insertions(+), 6 deletions(-)
+
+diff --git a/include/qapi/error.h b/include/qapi/error.h
+index 3351fe76368..08d48e74836 100644
+--- a/include/qapi/error.h
++++ b/include/qapi/error.h
+@@ -15,6 +15,33 @@
+ /*
+  * Error reporting system loosely patterned after Glib's GError.
+  *
++ * = Rules =
++ *
++ * - Functions that use Error to report errors have an Error **errp
++ *   parameter.  It should be the last parameter, except for functions
++ *   taking variable arguments.
++ *
++ * - You may pass NULL to not receive the error, &error_abort to abort
++ *   on error, &error_fatal to exit(1) on error, or a pointer to a
++ *   variable containing NULL to receive the error.
++ *
++ * - Separation of concerns: the function is responsible for detecting
++ *   errors and failing cleanly; handling the error is its caller's
++ *   job.  Since the value of @errp is about handling the error, the
++ *   function should not examine it.
++ *
++ * - On success, the function should not touch *errp.  On failure, it
++ *   should set a new error, e.g. with error_setg(errp, ...), or
++ *   propagate an existing one, e.g. with error_propagate(errp, ...).
++ *
++ * - Whenever practical, also return a value that indicates success /
++ *   failure.  This can make the error checking more concise, and can
++ *   avoid useless error object creation and destruction.  Note that
++ *   we still have many functions returning void.  We recommend
++ *   • bool-valued functions return true on success / false on failure,
++ *   • pointer-valued functions return non-null / null pointer, and
++ *   • integer-valued functions return non-negative / negative.
++ *
+  * = Creating errors =
+  *
+  * Create an error:
+@@ -95,14 +122,13 @@
+  * Create a new error and pass it to the caller:
+  *     error_setg(errp, "situation normal, all fouled up");
+  *
+- * Call a function and receive an error from it:
+- *     Error *err = NULL;
+- *     foo(arg, &err);
+- *     if (err) {
++ * Call a function, receive an error from it, and pass it to the caller
++ * - when the function returns a value that indicates failure, say
++ *   false:
++ *     if (!foo(arg, errp)) {
+  *         handle the error...
+  *     }
+- *
+- * Receive an error and pass it on to the caller:
++ * - when it does not, say because it is a void function:
+  *     Error *err = NULL;
+  *     foo(arg, &err);
+  *     if (err) {
+@@ -120,6 +146,20 @@
+  *     foo(arg, errp);
+  * for readability.
+  *
++ * Receive an error, and handle it locally
++ * - when the function returns a value that indicates failure, say
++ *   false:
++ *     Error *err = NULL;
++ *     if (!foo(arg, &err)) {
++ *         handle the error...
++ *     }
++ * - when it does not, say because it is a void function:
++ *     Error *err = NULL;
++ *     foo(arg, &err);
++ *     if (err) {
++ *         handle the error...
++ *     }
++ *
+  * Receive and accumulate multiple errors (first one wins):
+  *     Error *err = NULL, *local_err = NULL;
+  *     foo(arg, &err);
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-error-Fix-examples-in-error.h-s-big-comment.patch b/SOURCES/kvm-error-Fix-examples-in-error.h-s-big-comment.patch
new file mode 100644
index 0000000..62720d5
--- /dev/null
+++ b/SOURCES/kvm-error-Fix-examples-in-error.h-s-big-comment.patch
@@ -0,0 +1,87 @@
+From 393a5e9b24947f90cd116c4fb1b2ff4ee200f0df Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:40:53 -0500
+Subject: [PATCH 02/10] error: Fix examples in error.h's big comment
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-3-marcandre.lureau@redhat.com>
+Patchwork-id: 100521
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 02/10] error: Fix examples in error.h's big comment
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Markus Armbruster <armbru@redhat.com>
+
+Mark a bad example more clearly.  Fix the error_propagate_prepend()
+example.  Add a missing declaration and a second error pileup example.
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+Message-Id: <20200707160613.848843-2-armbru@redhat.com>
+
+(cherry picked from commit 47ff5ac81e8bb3096500de7b132051691d533d36)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ include/qapi/error.h | 16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/include/qapi/error.h b/include/qapi/error.h
+index 3f95141a01a..83c38f9a188 100644
+--- a/include/qapi/error.h
++++ b/include/qapi/error.h
+@@ -24,7 +24,7 @@
+  *                       "charm, top, bottom.\n");
+  *
+  * Do *not* contract this to
+- *     error_setg(&err, "invalid quark\n"
++ *     error_setg(&err, "invalid quark\n" // WRONG!
+  *                "Valid quarks are up, down, strange, charm, top, bottom.");
+  *
+  * Report an error to the current monitor if we have one, else stderr:
+@@ -52,7 +52,8 @@
+  * where Error **errp is a parameter, by convention the last one.
+  *
+  * Pass an existing error to the caller with the message modified:
+- *     error_propagate_prepend(errp, err);
++ *     error_propagate_prepend(errp, err,
++ *                             "Could not frobnicate '%s': ", name);
+  *
+  * Avoid
+  *     error_propagate(errp, err);
+@@ -108,12 +109,23 @@
+  *     }
+  *
+  * Do *not* "optimize" this to
++ *     Error *err = NULL;
+  *     foo(arg, &err);
+  *     bar(arg, &err); // WRONG!
+  *     if (err) {
+  *         handle the error...
+  *     }
+  * because this may pass a non-null err to bar().
++ *
++ * Likewise, do *not*
++ *     Error *err = NULL;
++ *     if (cond1) {
++ *         error_setg(&err, ...);
++ *     }
++ *     if (cond2) {
++ *         error_setg(&err, ...); // WRONG!
++ *     }
++ * because this may pass a non-null err to error_setg().
+  */
+ 
+ #ifndef ERROR_H
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-error-Improve-error.h-s-big-comment.patch b/SOURCES/kvm-error-Improve-error.h-s-big-comment.patch
new file mode 100644
index 0000000..aa5797d
--- /dev/null
+++ b/SOURCES/kvm-error-Improve-error.h-s-big-comment.patch
@@ -0,0 +1,148 @@
+From b41fc6d57fae80ac2a431bca22862985f003fe88 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:40:54 -0500
+Subject: [PATCH 03/10] error: Improve error.h's big comment
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-4-marcandre.lureau@redhat.com>
+Patchwork-id: 100522
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 03/10] error: Improve error.h's big comment
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Markus Armbruster <armbru@redhat.com>
+
+Add headlines to the big comment.
+
+Explain examples for NULL, &error_abort and &error_fatal argument
+better.
+
+Tweak rationale for error_propagate_prepend().
+
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Message-Id: <20200707160613.848843-3-armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+
+(cherry picked from commit 9aac7d486cc792191c25c30851f501624b0c2751)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ include/qapi/error.h | 51 +++++++++++++++++++++++++++++++-------------
+ 1 file changed, 36 insertions(+), 15 deletions(-)
+
+diff --git a/include/qapi/error.h b/include/qapi/error.h
+index 83c38f9a188..3351fe76368 100644
+--- a/include/qapi/error.h
++++ b/include/qapi/error.h
+@@ -15,6 +15,8 @@
+ /*
+  * Error reporting system loosely patterned after Glib's GError.
+  *
++ * = Creating errors =
++ *
+  * Create an error:
+  *     error_setg(&err, "situation normal, all fouled up");
+  *
+@@ -27,6 +29,8 @@
+  *     error_setg(&err, "invalid quark\n" // WRONG!
+  *                "Valid quarks are up, down, strange, charm, top, bottom.");
+  *
++ * = Reporting and destroying errors =
++ *
+  * Report an error to the current monitor if we have one, else stderr:
+  *     error_report_err(err);
+  * This frees the error object.
+@@ -40,6 +44,30 @@
+  *     error_free(err);
+  * Note that this loses hints added with error_append_hint().
+  *
++ * Call a function ignoring errors:
++ *     foo(arg, NULL);
++ * This is more concise than
++ *     Error *err = NULL;
++ *     foo(arg, &err);
++ *     error_free(err); // don't do this
++ *
++ * Call a function aborting on errors:
++ *     foo(arg, &error_abort);
++ * This is more concise and fails more nicely than
++ *     Error *err = NULL;
++ *     foo(arg, &err);
++ *     assert(!err); // don't do this
++ *
++ * Call a function treating errors as fatal:
++ *     foo(arg, &error_fatal);
++ * This is more concise than
++ *     Error *err = NULL;
++ *     foo(arg, &err);
++ *     if (err) { // don't do this
++ *         error_report_err(err);
++ *         exit(1);
++ *     }
++ *
+  * Handle an error without reporting it (just for completeness):
+  *     error_free(err);
+  *
+@@ -47,6 +75,11 @@
+  * reporting it (primarily useful in testsuites):
+  *     error_free_or_abort(&err);
+  *
++ * = Passing errors around =
++ *
++ * Errors get passed to the caller through the conventional @errp
++ * parameter.
++ *
+  * Pass an existing error to the caller:
+  *     error_propagate(errp, err);
+  * where Error **errp is a parameter, by convention the last one.
+@@ -54,11 +87,10 @@
+  * Pass an existing error to the caller with the message modified:
+  *     error_propagate_prepend(errp, err,
+  *                             "Could not frobnicate '%s': ", name);
+- *
+- * Avoid
+- *     error_propagate(errp, err);
++ * This is more concise than
++ *     error_propagate(errp, err); // don't do this
+  *     error_prepend(errp, "Could not frobnicate '%s': ", name);
+- * because this fails to prepend when @errp is &error_fatal.
++ * and works even when @errp is &error_fatal.
+  *
+  * Create a new error and pass it to the caller:
+  *     error_setg(errp, "situation normal, all fouled up");
+@@ -70,15 +102,6 @@
+  *         handle the error...
+  *     }
+  *
+- * Call a function ignoring errors:
+- *     foo(arg, NULL);
+- *
+- * Call a function aborting on errors:
+- *     foo(arg, &error_abort);
+- *
+- * Call a function treating errors as fatal:
+- *     foo(arg, &error_fatal);
+- *
+  * Receive an error and pass it on to the caller:
+  *     Error *err = NULL;
+  *     foo(arg, &err);
+@@ -86,8 +109,6 @@
+  *         handle the error...
+  *         error_propagate(errp, err);
+  *     }
+- * where Error **errp is a parameter, by convention the last one.
+- *
+  * Do *not* "optimize" this to
+  *     foo(arg, errp);
+  *     if (*errp) { // WRONG!
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-error-New-macro-ERRP_GUARD.patch b/SOURCES/kvm-error-New-macro-ERRP_GUARD.patch
new file mode 100644
index 0000000..bfcece6
--- /dev/null
+++ b/SOURCES/kvm-error-New-macro-ERRP_GUARD.patch
@@ -0,0 +1,307 @@
+From f6ac3d6bab961c31060d722af23beeb50ce5bdde Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:40:56 -0500
+Subject: [PATCH 05/10] error: New macro ERRP_GUARD()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-6-marcandre.lureau@redhat.com>
+Patchwork-id: 100524
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 05/10] error: New macro ERRP_GUARD()
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+
+Introduce a new ERRP_GUARD() macro, to be used at start of functions
+with an errp OUT parameter.
+
+It has three goals:
+
+1. Fix issue with error_fatal and error_prepend/error_append_hint: the
+user can't see this additional information, because exit() happens in
+error_setg earlier than information is added. [Reported by Greg Kurz]
+
+2. Fix issue with error_abort and error_propagate: when we wrap
+error_abort by local_err+error_propagate, the resulting coredump will
+refer to error_propagate and not to the place where error happened.
+(the macro itself doesn't fix the issue, but it allows us to [3.] drop
+the local_err+error_propagate pattern, which will definitely fix the
+issue) [Reported by Kevin Wolf]
+
+3. Drop local_err+error_propagate pattern, which is used to workaround
+void functions with errp parameter, when caller wants to know resulting
+status. (Note: actually these functions could be merely updated to
+return int error code).
+
+To achieve these goals, later patches will add invocations
+of this macro at the start of functions with either use
+error_prepend/error_append_hint (solving 1) or which use
+local_err+error_propagate to check errors, switching those
+functions to use *errp instead (solving 2 and 3).
+
+Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
+Reviewed-by: Paul Durrant <paul@xen.org>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+[Merge comments properly with recent commit "error: Document Error API
+usage rules", and edit for clarity.  Put ERRP_AUTO_PROPAGATE() before
+its helpers, and touch up style.  Tweak commit message.]
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+Message-Id: <20200707165037.1026246-2-armbru@redhat.com>
+
+(cherry picked from commit ae7c80a7bd73685437bf6ba9d7c26098351f4166)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ include/qapi/error.h | 158 +++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 139 insertions(+), 19 deletions(-)
+
+diff --git a/include/qapi/error.h b/include/qapi/error.h
+index 08d48e74836..e658790acfc 100644
+--- a/include/qapi/error.h
++++ b/include/qapi/error.h
+@@ -30,6 +30,10 @@
+  *   job.  Since the value of @errp is about handling the error, the
+  *   function should not examine it.
+  *
++ * - The function may pass @errp to functions it calls to pass on
++ *   their errors to its caller.  If it dereferences @errp to check
++ *   for errors, it must use ERRP_GUARD().
++ *
+  * - On success, the function should not touch *errp.  On failure, it
+  *   should set a new error, e.g. with error_setg(errp, ...), or
+  *   propagate an existing one, e.g. with error_propagate(errp, ...).
+@@ -45,15 +49,17 @@
+  * = Creating errors =
+  *
+  * Create an error:
+- *     error_setg(&err, "situation normal, all fouled up");
++ *     error_setg(errp, "situation normal, all fouled up");
++ * where @errp points to the location to receive the error.
+  *
+  * Create an error and add additional explanation:
+- *     error_setg(&err, "invalid quark");
+- *     error_append_hint(&err, "Valid quarks are up, down, strange, "
++ *     error_setg(errp, "invalid quark");
++ *     error_append_hint(errp, "Valid quarks are up, down, strange, "
+  *                       "charm, top, bottom.\n");
++ * This may require use of ERRP_GUARD(); more on that below.
+  *
+  * Do *not* contract this to
+- *     error_setg(&err, "invalid quark\n" // WRONG!
++ *     error_setg(errp, "invalid quark\n" // WRONG!
+  *                "Valid quarks are up, down, strange, charm, top, bottom.");
+  *
+  * = Reporting and destroying errors =
+@@ -107,18 +113,6 @@
+  * Errors get passed to the caller through the conventional @errp
+  * parameter.
+  *
+- * Pass an existing error to the caller:
+- *     error_propagate(errp, err);
+- * where Error **errp is a parameter, by convention the last one.
+- *
+- * Pass an existing error to the caller with the message modified:
+- *     error_propagate_prepend(errp, err,
+- *                             "Could not frobnicate '%s': ", name);
+- * This is more concise than
+- *     error_propagate(errp, err); // don't do this
+- *     error_prepend(errp, "Could not frobnicate '%s': ", name);
+- * and works even when @errp is &error_fatal.
+- *
+  * Create a new error and pass it to the caller:
+  *     error_setg(errp, "situation normal, all fouled up");
+  *
+@@ -129,18 +123,26 @@
+  *         handle the error...
+  *     }
+  * - when it does not, say because it is a void function:
++ *     ERRP_GUARD();
++ *     foo(arg, errp);
++ *     if (*errp) {
++ *         handle the error...
++ *     }
++ * More on ERRP_GUARD() below.
++ *
++ * Code predating ERRP_GUARD() still exists, and looks like this:
+  *     Error *err = NULL;
+  *     foo(arg, &err);
+  *     if (err) {
+  *         handle the error...
+- *         error_propagate(errp, err);
++ *         error_propagate(errp, err); // deprecated
+  *     }
+- * Do *not* "optimize" this to
++ * Avoid in new code.  Do *not* "optimize" it to
+  *     foo(arg, errp);
+  *     if (*errp) { // WRONG!
+  *         handle the error...
+  *     }
+- * because errp may be NULL!
++ * because errp may be NULL without the ERRP_GUARD() guard.
+  *
+  * But when all you do with the error is pass it on, please use
+  *     foo(arg, errp);
+@@ -160,6 +162,19 @@
+  *         handle the error...
+  *     }
+  *
++ * Pass an existing error to the caller:
++ *     error_propagate(errp, err);
++ * This is rarely needed.  When @err is a local variable, use of
++ * ERRP_GUARD() commonly results in more readable code.
++ *
++ * Pass an existing error to the caller with the message modified:
++ *     error_propagate_prepend(errp, err,
++ *                             "Could not frobnicate '%s': ", name);
++ * This is more concise than
++ *     error_propagate(errp, err); // don't do this
++ *     error_prepend(errp, "Could not frobnicate '%s': ", name);
++ * and works even when @errp is &error_fatal.
++ *
+  * Receive and accumulate multiple errors (first one wins):
+  *     Error *err = NULL, *local_err = NULL;
+  *     foo(arg, &err);
+@@ -187,6 +202,69 @@
+  *         error_setg(&err, ...); // WRONG!
+  *     }
+  * because this may pass a non-null err to error_setg().
++ *
++ * = Why, when and how to use ERRP_GUARD() =
++ *
++ * Without ERRP_GUARD(), use of the @errp parameter is restricted:
++ * - It must not be dereferenced, because it may be null.
++ * - It should not be passed to error_prepend() or
++ *   error_append_hint(), because that doesn't work with &error_fatal.
++ * ERRP_GUARD() lifts these restrictions.
++ *
++ * To use ERRP_GUARD(), add it right at the beginning of the function.
++ * @errp can then be used without worrying about the argument being
++ * NULL or &error_fatal.
++ *
++ * Using it when it's not needed is safe, but please avoid cluttering
++ * the source with useless code.
++ *
++ * = Converting to ERRP_GUARD() =
++ *
++ * To convert a function to use ERRP_GUARD():
++ *
++ * 0. If the Error ** parameter is not named @errp, rename it to
++ *    @errp.
++ *
++ * 1. Add an ERRP_GUARD() invocation, by convention right at the
++ *    beginning of the function.  This makes @errp safe to use.
++ *
++ * 2. Replace &err by errp, and err by *errp.  Delete local variable
++ *    @err.
++ *
++ * 3. Delete error_propagate(errp, *errp), replace
++ *    error_propagate_prepend(errp, *errp, ...) by error_prepend(errp, ...)
++ *
++ * 4. Ensure @errp is valid at return: when you destroy *errp, set
++ *    errp = NULL.
++ *
++ * Example:
++ *
++ *     bool fn(..., Error **errp)
++ *     {
++ *         Error *err = NULL;
++ *
++ *         foo(arg, &err);
++ *         if (err) {
++ *             handle the error...
++ *             error_propagate(errp, err);
++ *             return false;
++ *         }
++ *         ...
++ *     }
++ *
++ * becomes
++ *
++ *     bool fn(..., Error **errp)
++ *     {
++ *         ERRP_GUARD();
++ *
++ *         foo(arg, errp);
++ *         if (*errp) {
++ *             handle the error...
++ *             return false;
++ *         }
++ *         ...
++ *     }
+  */
+ 
+ #ifndef ERROR_H
+@@ -287,6 +365,7 @@ void error_setg_win32_internal(Error **errp,
+  * the error object.
+  * Else, move the error object from @local_err to *@dst_errp.
+  * On return, @local_err is invalid.
++ * Please use ERRP_GUARD() instead when possible.
+  * Please don't error_propagate(&error_fatal, ...), use
+  * error_report_err() and exit(), because that's more obvious.
+  */
+@@ -298,6 +377,7 @@ void error_propagate(Error **dst_errp, Error *local_err);
+  * Behaves like
+  *     error_prepend(&local_err, fmt, ...);
+  *     error_propagate(dst_errp, local_err);
++ * Please use ERRP_GUARD() and error_prepend() instead when possible.
+  */
+ void error_propagate_prepend(Error **dst_errp, Error *local_err,
+                              const char *fmt, ...);
+@@ -395,6 +475,46 @@ void error_set_internal(Error **errp,
+                         ErrorClass err_class, const char *fmt, ...)
+     GCC_FMT_ATTR(6, 7);
+ 
++/*
++ * Make @errp parameter easier to use regardless of argument value
++ *
++ * This macro is for use right at the beginning of a function that
++ * takes an Error **errp parameter to pass errors to its caller.  The
++ * parameter must be named @errp.
++ *
++ * It must be used when the function dereferences @errp or passes
++ * @errp to error_prepend(), error_vprepend(), or error_append_hint().
++ * It is safe to use even when it's not needed, but please avoid
++ * cluttering the source with useless code.
++ *
++ * If @errp is NULL or &error_fatal, rewrite it to point to a local
++ * Error variable, which will be automatically propagated to the
++ * original @errp on function exit.
++ *
++ * Note: &error_abort is not rewritten, because that would move the
++ * abort from the place where the error is created to the place where
++ * it's propagated.
++ */
++#define ERRP_GUARD()                                            \
++    g_auto(ErrorPropagator) _auto_errp_prop = {.errp = errp};   \
++    do {                                                        \
++        if (!errp || errp == &error_fatal) {                    \
++            errp = &_auto_errp_prop.local_err;                  \
++        }                                                       \
++    } while (0)
++
++typedef struct ErrorPropagator {
++    Error *local_err;
++    Error **errp;
++} ErrorPropagator;
++
++static inline void error_propagator_cleanup(ErrorPropagator *prop)
++{
++    error_propagate(prop->errp, prop->local_err);
++}
++
++G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, error_propagator_cleanup);
++
+ /*
+  * Special error destination to abort on error.
+  * See error_setg() and error_propagate() for details.
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qapi-enable-use-of-g_autoptr-with-QAPI-types.patch b/SOURCES/kvm-qapi-enable-use-of-g_autoptr-with-QAPI-types.patch
new file mode 100644
index 0000000..e925459
--- /dev/null
+++ b/SOURCES/kvm-qapi-enable-use-of-g_autoptr-with-QAPI-types.patch
@@ -0,0 +1,239 @@
+From 08e7c4a3d0e739b8ff0f236d12e51dc394ec5b88 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:40:52 -0500
+Subject: [PATCH 01/10] qapi: enable use of g_autoptr with QAPI types
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-2-marcandre.lureau@redhat.com>
+Patchwork-id: 100520
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 01/10] qapi: enable use of g_autoptr with QAPI types
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Daniel P. Berrangé <berrange@redhat.com>
+
+Currently QAPI generates a type and function for free'ing it:
+
+  typedef struct QCryptoBlockCreateOptions QCryptoBlockCreateOptions;
+  void qapi_free_QCryptoBlockCreateOptions(QCryptoBlockCreateOptions *obj);
+
+This is used in the traditional manner:
+
+  QCryptoBlockCreateOptions *opts = NULL;
+
+  opts = g_new0(QCryptoBlockCreateOptions, 1);
+
+  ....do stuff with opts...
+
+  qapi_free_QCryptoBlockCreateOptions(opts);
+
+Since bumping the min glib to 2.48, QEMU has incrementally adopted the
+use of g_auto/g_autoptr. This allows the compiler to run a function to
+free a variable when it goes out of scope, the benefit being the
+compiler can guarantee it is freed in all possible code ptahs.
+
+This benefit is applicable to QAPI types too, and given the seriously
+long method names for some qapi_free_XXXX() functions, is much less
+typing. This change thus makes the code generator emit:
+
+ G_DEFINE_AUTOPTR_CLEANUP_FUNC(QCryptoBlockCreateOptions,
+                              qapi_free_QCryptoBlockCreateOptions)
+
+The above code example now becomes
+
+  g_autoptr(QCryptoBlockCreateOptions) opts = NULL;
+
+  opts = g_new0(QCryptoBlockCreateOptions, 1);
+
+  ....do stuff with opts...
+
+Note, if the local pointer needs to live beyond the scope holding the
+variable, then g_steal_pointer can be used. This is useful to return the
+pointer to the caller in the success codepath, while letting it be freed
+in all error codepaths.
+
+  return g_steal_pointer(&opts);
+
+The crypto/block.h header needs updating to avoid symbol clash now that
+the g_autoptr support is a standard QAPI feature.
+
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+Message-Id: <20200723153845.2934357-1-berrange@redhat.com>
+Reviewed-by: Markus Armbruster <armbru@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+
+(cherry picked from commit 221db5daf6b3666f1c8e4ca06ae45892e99a112f)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ docs/devel/qapi-code-gen.txt       |  2 ++
+ scripts/qapi/types.py              |  1 +
+ tests/test-qobject-input-visitor.c | 23 +++++++----------------
+ 3 files changed, 10 insertions(+), 16 deletions(-)
+
+diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
+index 45c93a43cc3..ca59c695fac 100644
+--- a/docs/devel/qapi-code-gen.txt
++++ b/docs/devel/qapi-code-gen.txt
+@@ -1278,6 +1278,7 @@ Example:
+     };
+ 
+     void qapi_free_UserDefOne(UserDefOne *obj);
++    G_DEFINE_AUTOPTR_CLEANUP_FUNC(UserDefOne, qapi_free_UserDefOne)
+ 
+     struct UserDefOneList {
+         UserDefOneList *next;
+@@ -1285,6 +1286,7 @@ Example:
+     };
+ 
+     void qapi_free_UserDefOneList(UserDefOneList *obj);
++    G_DEFINE_AUTOPTR_CLEANUP_FUNC(UserDefOneList, qapi_free_UserDefOneList)
+ 
+     struct q_obj_my_command_arg {
+         UserDefOneList *arg1;
+diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
+index d8751daa049..c3be141dc90 100644
+--- a/scripts/qapi/types.py
++++ b/scripts/qapi/types.py
+@@ -213,6 +213,7 @@ def gen_type_cleanup_decl(name):
+     ret = mcgen('''
+ 
+ void qapi_free_%(c_name)s(%(c_name)s *obj);
++G_DEFINE_AUTOPTR_CLEANUP_FUNC(%(c_name)s, qapi_free_%(c_name)s)
+ ''',
+                 c_name=c_name(name))
+     return ret
+diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
+index 6bacabf0632..e41b91a2a6f 100644
+--- a/tests/test-qobject-input-visitor.c
++++ b/tests/test-qobject-input-visitor.c
+@@ -417,7 +417,7 @@ static void test_visitor_in_struct(TestInputVisitorData *data,
+ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
+                                           const void *unused)
+ {
+-    UserDefTwo *udp = NULL;
++    g_autoptr(UserDefTwo) udp = NULL;
+     Visitor *v;
+ 
+     v = visitor_input_test_init(data, "{ 'string0': 'string0', "
+@@ -433,8 +433,6 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
+     g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
+     g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
+     g_assert(udp->dict1->has_dict3 == false);
+-
+-    qapi_free_UserDefTwo(udp);
+ }
+ 
+ static void test_visitor_in_list(TestInputVisitorData *data,
+@@ -546,7 +544,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data,
+                                        const void *unused)
+ {
+     Visitor *v;
+-    UserDefFlatUnion *tmp;
++    g_autoptr(UserDefFlatUnion) tmp = NULL;
+     UserDefUnionBase *base;
+ 
+     v = visitor_input_test_init(data,
+@@ -563,8 +561,6 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data,
+ 
+     base = qapi_UserDefFlatUnion_base(tmp);
+     g_assert(&base->enum1 == &tmp->enum1);
+-
+-    qapi_free_UserDefFlatUnion(tmp);
+ }
+ 
+ static void test_visitor_in_alternate(TestInputVisitorData *data,
+@@ -690,7 +686,7 @@ static void test_list_union_integer_helper(TestInputVisitorData *data,
+                                            const void *unused,
+                                            UserDefListUnionKind kind)
+ {
+-    UserDefListUnion *cvalue = NULL;
++    g_autoptr(UserDefListUnion) cvalue = NULL;
+     Visitor *v;
+     GString *gstr_list = g_string_new("");
+     GString *gstr_union = g_string_new("");
+@@ -782,7 +778,6 @@ static void test_list_union_integer_helper(TestInputVisitorData *data,
+ 
+     g_string_free(gstr_union, true);
+     g_string_free(gstr_list, true);
+-    qapi_free_UserDefListUnion(cvalue);
+ }
+ 
+ static void test_visitor_in_list_union_int(TestInputVisitorData *data,
+@@ -851,7 +846,7 @@ static void test_visitor_in_list_union_uint64(TestInputVisitorData *data,
+ static void test_visitor_in_list_union_bool(TestInputVisitorData *data,
+                                             const void *unused)
+ {
+-    UserDefListUnion *cvalue = NULL;
++    g_autoptr(UserDefListUnion) cvalue = NULL;
+     boolList *elem = NULL;
+     Visitor *v;
+     GString *gstr_list = g_string_new("");
+@@ -879,13 +874,12 @@ static void test_visitor_in_list_union_bool(TestInputVisitorData *data,
+ 
+     g_string_free(gstr_union, true);
+     g_string_free(gstr_list, true);
+-    qapi_free_UserDefListUnion(cvalue);
+ }
+ 
+ static void test_visitor_in_list_union_string(TestInputVisitorData *data,
+                                               const void *unused)
+ {
+-    UserDefListUnion *cvalue = NULL;
++    g_autoptr(UserDefListUnion) cvalue = NULL;
+     strList *elem = NULL;
+     Visitor *v;
+     GString *gstr_list = g_string_new("");
+@@ -914,7 +908,6 @@ static void test_visitor_in_list_union_string(TestInputVisitorData *data,
+ 
+     g_string_free(gstr_union, true);
+     g_string_free(gstr_list, true);
+-    qapi_free_UserDefListUnion(cvalue);
+ }
+ 
+ #define DOUBLE_STR_MAX 16
+@@ -922,7 +915,7 @@ static void test_visitor_in_list_union_string(TestInputVisitorData *data,
+ static void test_visitor_in_list_union_number(TestInputVisitorData *data,
+                                               const void *unused)
+ {
+-    UserDefListUnion *cvalue = NULL;
++    g_autoptr(UserDefListUnion) cvalue = NULL;
+     numberList *elem = NULL;
+     Visitor *v;
+     GString *gstr_list = g_string_new("");
+@@ -957,7 +950,6 @@ static void test_visitor_in_list_union_number(TestInputVisitorData *data,
+ 
+     g_string_free(gstr_union, true);
+     g_string_free(gstr_list, true);
+-    qapi_free_UserDefListUnion(cvalue);
+ }
+ 
+ static void input_visitor_test_add(const char *testpath,
+@@ -1253,7 +1245,7 @@ static void test_visitor_in_fail_alternate(TestInputVisitorData *data,
+ static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
+                                               const QLitObject *qlit)
+ {
+-    SchemaInfoList *schema = NULL;
++    g_autoptr(SchemaInfoList) schema = NULL;
+     QObject *obj = qobject_from_qlit(qlit);
+     Visitor *v;
+ 
+@@ -1262,7 +1254,6 @@ static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
+     visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
+     g_assert(schema);
+ 
+-    qapi_free_SchemaInfoList(schema);
+     qobject_unref(obj);
+     visit_free(v);
+ }
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qga-add-command-guest-get-disks.patch b/SOURCES/kvm-qga-add-command-guest-get-disks.patch
new file mode 100644
index 0000000..89218f9
--- /dev/null
+++ b/SOURCES/kvm-qga-add-command-guest-get-disks.patch
@@ -0,0 +1,117 @@
+From 9ed672656f15a47bdc0f9af0f96e55132ad5c0cf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:40:57 -0500
+Subject: [PATCH 06/10] qga: add command guest-get-disks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-7-marcandre.lureau@redhat.com>
+Patchwork-id: 100525
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 06/10] qga: add command guest-get-disks
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Tomáš Golembiovský <tgolembi@redhat.com>
+
+Add API and stubs for new guest-get-disks command.
+
+The command guest-get-fsinfo can be used to list information about disks
+and partitions but it is limited only to mounted disks with filesystem.
+This new command should allow listing information about disks of the VM
+regardles whether they are mounted or not. This can be usefull for
+management applications for mapping virtualized devices or pass-through
+devices to device names in the guest OS.
+
+Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com>
+Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Michael Roth <michael.roth@amd.com>
+
+(cherry-picked from commit c27ea3f9ef7c7f29e55bde91879f8514abce9c38)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ qga/commands-posix.c |  6 ++++++
+ qga/commands-win32.c |  6 ++++++
+ qga/qapi-schema.json | 31 +++++++++++++++++++++++++++++++
+ 3 files changed, 43 insertions(+)
+
+diff --git a/qga/commands-posix.c b/qga/commands-posix.c
+index 1c1a165daed..9b690f3cceb 100644
+--- a/qga/commands-posix.c
++++ b/qga/commands-posix.c
+@@ -2978,3 +2978,9 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp)
+ 
+     return info;
+ }
++
++GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
++{
++    error_setg(errp, QERR_UNSUPPORTED);
++    return NULL;
++}
+diff --git a/qga/commands-win32.c b/qga/commands-win32.c
+index 55ba5b263af..be63fa2b208 100644
+--- a/qga/commands-win32.c
++++ b/qga/commands-win32.c
+@@ -2234,3 +2234,9 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp)
+ 
+     return info;
+ }
++
++GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
++{
++    error_setg(errp, QERR_UNSUPPORTED);
++    return NULL;
++}
+diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
+index fb4605cc19c..22df375c92f 100644
+--- a/qga/qapi-schema.json
++++ b/qga/qapi-schema.json
+@@ -852,6 +852,37 @@
+            'bus': 'int', 'target': 'int', 'unit': 'int',
+            '*serial': 'str', '*dev': 'str'} }
+ 
++##
++# @GuestDiskInfo:
++#
++# @name: device node (Linux) or device UNC (Windows)
++# @partition: whether this is a partition or disk
++# @dependents: list of dependent devices; e.g. for LVs of the LVM this will
++#              hold the list of PVs, for LUKS encrypted volume this will
++#              contain the disk where the volume is placed.     (Linux)
++# @address: disk address information (only for non-virtual devices)
++# @alias: optional alias assigned to the disk, on Linux this is a name assigned
++#         by device mapper
++#
++# Since 5.2
++##
++{ 'struct': 'GuestDiskInfo',
++  'data': {'name': 'str', 'partition': 'bool', 'dependents': ['str'],
++           '*address': 'GuestDiskAddress', '*alias': 'str'} }
++
++##
++# @guest-get-disks:
++#
++# Returns: The list of disks in the guest. For Windows these are only the
++#          physical disks. On Linux these are all root block devices of
++#          non-zero size including e.g. removable devices, loop devices,
++#          NBD, etc.
++#
++# Since: 5.2
++##
++{ 'command': 'guest-get-disks',
++  'returns': ['GuestDiskInfo'] }
++
+ ##
+ # @GuestFilesystemInfo:
+ #
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qga-add-implementation-of-guest-get-disks-for-Linux.patch b/SOURCES/kvm-qga-add-implementation-of-guest-get-disks-for-Linux.patch
new file mode 100644
index 0000000..2b3cee5
--- /dev/null
+++ b/SOURCES/kvm-qga-add-implementation-of-guest-get-disks-for-Linux.patch
@@ -0,0 +1,431 @@
+From 7be40868e976b12107a0111dcd5ee5fe77e9df61 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:40:58 -0500
+Subject: [PATCH 07/10] qga: add implementation of guest-get-disks for Linux
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-8-marcandre.lureau@redhat.com>
+Patchwork-id: 100526
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 07/10] qga: add implementation of guest-get-disks for Linux
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Tomáš Golembiovský <tgolembi@redhat.com>
+
+The command lists all disks (real and virtual) as well as disk
+partitions. For each disk the list of dependent disks is also listed and
+/dev path is used as a handle so it can be matched with "name" field of
+other returned disk entries. For disk partitions the "dependents" list
+is populated with the the parent device for easier tracking of
+hierarchy.
+
+Example output:
+{
+  "return": [
+    ...
+    {
+      "name": "/dev/dm-0",
+      "partition": false,
+      "dependents": [
+        "/dev/sda2"
+      ],
+      "alias": "luks-7062202e-5b9b-433e-81e8-6628c40da9f7"
+    },
+    {
+      "name": "/dev/sda2",
+      "partition": true,
+      "dependents": [
+        "/dev/sda"
+      ]
+    },
+    {
+      "name": "/dev/sda",
+      "partition": false,
+      "address": {
+        "serial": "SAMSUNG_MZ7LN512HCHP-000L1_S1ZKNXAG822493",
+        "bus-type": "sata",
+        ...
+        "dev": "/dev/sda",
+        "target": 0
+      },
+      "dependents": []
+    },
+    ...
+  ]
+}
+
+Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com>
+Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+*add missing stub for !defined(CONFIG_FSFREEZE)
+*remove unused deps_dir variable
+Signed-off-by: Michael Roth <michael.roth@amd.com>
+
+(cherry picked from commit fed3956429d560a06fc2d2fcf1a01efb58659f87)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ qga/commands-posix.c | 303 +++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 292 insertions(+), 11 deletions(-)
+
+diff --git a/qga/commands-posix.c b/qga/commands-posix.c
+index 9b690f3cceb..af80bb7ccbb 100644
+--- a/qga/commands-posix.c
++++ b/qga/commands-posix.c
+@@ -1091,13 +1091,27 @@ static void build_guest_fsinfo_for_virtual_device(char const *syspath,
+     closedir(dir);
+ }
+ 
++static bool is_disk_virtual(const char *devpath, Error **errp)
++{
++    g_autofree char *syspath = realpath(devpath, NULL);
++
++    if (!syspath) {
++        error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
++        return false;
++    }
++    return strstr(syspath, "/devices/virtual/block/") != NULL;
++}
++
+ /* Dispatch to functions for virtual/real device */
+ static void build_guest_fsinfo_for_device(char const *devpath,
+                                           GuestFilesystemInfo *fs,
+                                           Error **errp)
+ {
+-    char *syspath = realpath(devpath, NULL);
++    ERRP_GUARD();
++    g_autofree char *syspath = NULL;
++    bool is_virtual = false;
+ 
++    syspath = realpath(devpath, NULL);
+     if (!syspath) {
+         error_setg_errno(errp, errno, "realpath(\"%s\")", devpath);
+         return;
+@@ -1108,16 +1122,281 @@ static void build_guest_fsinfo_for_device(char const *devpath,
+     }
+ 
+     g_debug("  parse sysfs path '%s'", syspath);
+-
+-    if (strstr(syspath, "/devices/virtual/block/")) {
++    is_virtual = is_disk_virtual(syspath, errp);
++    if (*errp != NULL) {
++        return;
++    }
++    if (is_virtual) {
+         build_guest_fsinfo_for_virtual_device(syspath, fs, errp);
+     } else {
+         build_guest_fsinfo_for_real_device(syspath, fs, errp);
+     }
++}
++
++#ifdef CONFIG_LIBUDEV
++
++/*
++ * Wrapper around build_guest_fsinfo_for_device() for getting just
++ * the disk address.
++ */
++static GuestDiskAddress *get_disk_address(const char *syspath, Error **errp)
++{
++    g_autoptr(GuestFilesystemInfo) fs = NULL;
+ 
+-    free(syspath);
++    fs = g_new0(GuestFilesystemInfo, 1);
++    build_guest_fsinfo_for_device(syspath, fs, errp);
++    if (fs->disk != NULL) {
++        return g_steal_pointer(&fs->disk->value);
++    }
++    return NULL;
+ }
+ 
++static char *get_alias_for_syspath(const char *syspath)
++{
++    struct udev *udev = NULL;
++    struct udev_device *udevice = NULL;
++    char *ret = NULL;
++
++    udev = udev_new();
++    if (udev == NULL) {
++        g_debug("failed to query udev");
++        goto out;
++    }
++    udevice = udev_device_new_from_syspath(udev, syspath);
++    if (udevice == NULL) {
++        g_debug("failed to query udev for path: %s", syspath);
++        goto out;
++    } else {
++        const char *alias = udev_device_get_property_value(
++            udevice, "DM_NAME");
++        /*
++         * NULL means there was an error and empty string means there is no
++         * alias. In case of no alias we return NULL instead of empty string.
++         */
++        if (alias == NULL) {
++            g_debug("failed to query udev for device alias for: %s",
++                syspath);
++        } else if (*alias != 0) {
++            ret = g_strdup(alias);
++        }
++    }
++
++out:
++    udev_unref(udev);
++    udev_device_unref(udevice);
++    return ret;
++}
++
++static char *get_device_for_syspath(const char *syspath)
++{
++    struct udev *udev = NULL;
++    struct udev_device *udevice = NULL;
++    char *ret = NULL;
++
++    udev = udev_new();
++    if (udev == NULL) {
++        g_debug("failed to query udev");
++        goto out;
++    }
++    udevice = udev_device_new_from_syspath(udev, syspath);
++    if (udevice == NULL) {
++        g_debug("failed to query udev for path: %s", syspath);
++        goto out;
++    } else {
++        ret = g_strdup(udev_device_get_devnode(udevice));
++    }
++
++out:
++    udev_unref(udev);
++    udev_device_unref(udevice);
++    return ret;
++}
++
++static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
++{
++    g_autofree char *deps_dir = NULL;
++    const gchar *dep;
++    GDir *dp_deps = NULL;
++
++    /* List dependent disks */
++    deps_dir = g_strdup_printf("%s/slaves", disk_dir);
++    g_debug("  listing entries in: %s", deps_dir);
++    dp_deps = g_dir_open(deps_dir, 0, NULL);
++    if (dp_deps == NULL) {
++        g_debug("failed to list entries in %s", deps_dir);
++        return;
++    }
++    while ((dep = g_dir_read_name(dp_deps)) != NULL) {
++        g_autofree char *dep_dir = NULL;
++        strList *dep_item = NULL;
++        char *dev_name;
++
++        /* Add dependent disks */
++        dep_dir = g_strdup_printf("%s/%s", deps_dir, dep);
++        dev_name = get_device_for_syspath(dep_dir);
++        if (dev_name != NULL) {
++            g_debug("  adding dependent device: %s", dev_name);
++            dep_item = g_new0(strList, 1);
++            dep_item->value = dev_name;
++            dep_item->next = disk->dependents;
++            disk->dependents = dep_item;
++        }
++    }
++    g_dir_close(dp_deps);
++}
++
++/*
++ * Detect partitions subdirectory, name is "<disk_name><number>" or
++ * "<disk_name>p<number>"
++ *
++ * @disk_name -- last component of /sys path (e.g. sda)
++ * @disk_dir -- sys path of the disk (e.g. /sys/block/sda)
++ * @disk_dev -- device node of the disk (e.g. /dev/sda)
++ */
++static GuestDiskInfoList *get_disk_partitions(
++    GuestDiskInfoList *list,
++    const char *disk_name, const char *disk_dir,
++    const char *disk_dev)
++{
++    GuestDiskInfoList *item, *ret = list;
++    struct dirent *de_disk;
++    DIR *dp_disk = NULL;
++    size_t len = strlen(disk_name);
++
++    dp_disk = opendir(disk_dir);
++    while ((de_disk = readdir(dp_disk)) != NULL) {
++        g_autofree char *partition_dir = NULL;
++        char *dev_name;
++        GuestDiskInfo *partition;
++
++        if (!(de_disk->d_type & DT_DIR)) {
++            continue;
++        }
++
++        if (!(strncmp(disk_name, de_disk->d_name, len) == 0 &&
++            ((*(de_disk->d_name + len) == 'p' &&
++            isdigit(*(de_disk->d_name + len + 1))) ||
++                isdigit(*(de_disk->d_name + len))))) {
++            continue;
++        }
++
++        partition_dir = g_strdup_printf("%s/%s",
++            disk_dir, de_disk->d_name);
++        dev_name = get_device_for_syspath(partition_dir);
++        if (dev_name == NULL) {
++            g_debug("Failed to get device name for syspath: %s",
++                disk_dir);
++            continue;
++        }
++        partition = g_new0(GuestDiskInfo, 1);
++        partition->name = dev_name;
++        partition->partition = true;
++        /* Add parent disk as dependent for easier tracking of hierarchy */
++        partition->dependents = g_new0(strList, 1);
++        partition->dependents->value = g_strdup(disk_dev);
++
++        item = g_new0(GuestDiskInfoList, 1);
++        item->value = partition;
++        item->next = ret;
++        ret = item;
++
++    }
++    closedir(dp_disk);
++
++    return ret;
++}
++
++GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
++{
++    GuestDiskInfoList *item, *ret = NULL;
++    GuestDiskInfo *disk;
++    DIR *dp = NULL;
++    struct dirent *de = NULL;
++
++    g_debug("listing /sys/block directory");
++    dp = opendir("/sys/block");
++    if (dp == NULL) {
++        error_setg_errno(errp, errno, "Can't open directory \"/sys/block\"");
++        return NULL;
++    }
++    while ((de = readdir(dp)) != NULL) {
++        g_autofree char *disk_dir = NULL, *line = NULL,
++            *size_path = NULL;
++        char *dev_name;
++        Error *local_err = NULL;
++        if (de->d_type != DT_LNK) {
++            g_debug("  skipping entry: %s", de->d_name);
++            continue;
++        }
++
++        /* Check size and skip zero-sized disks */
++        g_debug("  checking disk size");
++        size_path = g_strdup_printf("/sys/block/%s/size", de->d_name);
++        if (!g_file_get_contents(size_path, &line, NULL, NULL)) {
++            g_debug("  failed to read disk size");
++            continue;
++        }
++        if (g_strcmp0(line, "0\n") == 0) {
++            g_debug("  skipping zero-sized disk");
++            continue;
++        }
++
++        g_debug("  adding %s", de->d_name);
++        disk_dir = g_strdup_printf("/sys/block/%s", de->d_name);
++        dev_name = get_device_for_syspath(disk_dir);
++        if (dev_name == NULL) {
++            g_debug("Failed to get device name for syspath: %s",
++                disk_dir);
++            continue;
++        }
++        disk = g_new0(GuestDiskInfo, 1);
++        disk->name = dev_name;
++        disk->partition = false;
++        disk->alias = get_alias_for_syspath(disk_dir);
++        disk->has_alias = (disk->alias != NULL);
++        item = g_new0(GuestDiskInfoList, 1);
++        item->value = disk;
++        item->next = ret;
++        ret = item;
++
++        /* Get address for non-virtual devices */
++        bool is_virtual = is_disk_virtual(disk_dir, &local_err);
++        if (local_err != NULL) {
++            g_debug("  failed to check disk path, ignoring error: %s",
++                error_get_pretty(local_err));
++            error_free(local_err);
++            local_err = NULL;
++            /* Don't try to get the address */
++            is_virtual = true;
++        }
++        if (!is_virtual) {
++            disk->address = get_disk_address(disk_dir, &local_err);
++            if (local_err != NULL) {
++                g_debug("  failed to get device info, ignoring error: %s",
++                    error_get_pretty(local_err));
++                error_free(local_err);
++                local_err = NULL;
++            } else if (disk->address != NULL) {
++                disk->has_address = true;
++            }
++        }
++
++        get_disk_deps(disk_dir, disk);
++        ret = get_disk_partitions(ret, de->d_name, disk_dir, dev_name);
++    }
++    return ret;
++}
++
++#else
++
++GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
++{
++    error_setg(errp, QERR_UNSUPPORTED);
++    return NULL;
++}
++
++#endif
++
+ /* Return a list of the disk device(s)' info which @mount lies on */
+ static GuestFilesystemInfo *build_guest_fsinfo(struct FsMount *mount,
+                                                Error **errp)
+@@ -2709,6 +2988,13 @@ int64_t qmp_guest_fsfreeze_thaw(Error **errp)
+ 
+     return 0;
+ }
++
++GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
++{
++    error_setg(errp, QERR_UNSUPPORTED);
++    return NULL;
++}
++
+ #endif /* CONFIG_FSFREEZE */
+ 
+ #if !defined(CONFIG_FSTRIM)
+@@ -2745,7 +3031,8 @@ GList *ga_command_blacklist_init(GList *blacklist)
+         const char *list[] = {
+             "guest-get-fsinfo", "guest-fsfreeze-status",
+             "guest-fsfreeze-freeze", "guest-fsfreeze-freeze-list",
+-            "guest-fsfreeze-thaw", "guest-get-fsinfo", NULL};
++            "guest-fsfreeze-thaw", "guest-get-fsinfo",
++            "guest-get-disks", NULL};
+         char **p = (char **)list;
+ 
+         while (*p) {
+@@ -2978,9 +3265,3 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp)
+ 
+     return info;
+ }
+-
+-GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
+-{
+-    error_setg(errp, QERR_UNSUPPORTED);
+-    return NULL;
+-}
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qga-add-implementation-of-guest-get-disks-for-Window.patch b/SOURCES/kvm-qga-add-implementation-of-guest-get-disks-for-Window.patch
new file mode 100644
index 0000000..37e8ad6
--- /dev/null
+++ b/SOURCES/kvm-qga-add-implementation-of-guest-get-disks-for-Window.patch
@@ -0,0 +1,182 @@
+From 5c5fbed35d6c8b44533ff8a29afb9a85131ea7e9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:40:59 -0500
+Subject: [PATCH 08/10] qga: add implementation of guest-get-disks for Windows
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-9-marcandre.lureau@redhat.com>
+Patchwork-id: 100527
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 08/10] qga: add implementation of guest-get-disks for Windows
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Tomáš Golembiovský <tgolembi@redhat.com>
+
+The command lists all the physical disk drives. Unlike for Linux
+partitions and virtual volumes are not listed.
+
+Example output:
+
+{
+  "return": [
+    {
+      "name": "\\\\.\\PhysicalDrive0",
+      "partition": false,
+      "address": {
+        "serial": "QM00001",
+        "bus-type": "sata",
+        ...
+      },
+      "dependents": []
+    }
+  ]
+}
+
+Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com>
+Signed-off-by: Michael Roth <michael.roth@amd.com>
+
+(cherry picked from commit c67d2efd9d1771fd886e3b58771adaa62897f3d9)
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ qga/commands-win32.c | 107 ++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 101 insertions(+), 6 deletions(-)
+
+diff --git a/qga/commands-win32.c b/qga/commands-win32.c
+index be63fa2b208..a07725e874b 100644
+--- a/qga/commands-win32.c
++++ b/qga/commands-win32.c
+@@ -960,6 +960,101 @@ out:
+     return list;
+ }
+ 
++GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
++{
++    ERRP_GUARD();
++    GuestDiskInfoList *new = NULL, *ret = NULL;
++    HDEVINFO dev_info;
++    SP_DEVICE_INTERFACE_DATA dev_iface_data;
++    int i;
++
++    dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, 0, 0,
++        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
++    if (dev_info == INVALID_HANDLE_VALUE) {
++        error_setg_win32(errp, GetLastError(), "failed to get device tree");
++        return NULL;
++    }
++
++    g_debug("enumerating devices");
++    dev_iface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
++    for (i = 0;
++        SetupDiEnumDeviceInterfaces(dev_info, NULL, &GUID_DEVINTERFACE_DISK,
++            i, &dev_iface_data);
++        i++) {
++        GuestDiskAddress *address = NULL;
++        GuestDiskInfo *disk = NULL;
++        Error *local_err = NULL;
++        g_autofree PSP_DEVICE_INTERFACE_DETAIL_DATA
++            pdev_iface_detail_data = NULL;
++        STORAGE_DEVICE_NUMBER sdn;
++        HANDLE dev_file;
++        DWORD size = 0;
++        BOOL result;
++        int attempt;
++
++        g_debug("  getting device path");
++        for (attempt = 0, result = FALSE; attempt < 2 && !result; attempt++) {
++            result = SetupDiGetDeviceInterfaceDetail(dev_info,
++                &dev_iface_data, pdev_iface_detail_data, size, &size, NULL);
++            if (result) {
++                break;
++            }
++            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
++                pdev_iface_detail_data = g_realloc(pdev_iface_detail_data,
++                    size);
++                pdev_iface_detail_data->cbSize =
++                    sizeof(*pdev_iface_detail_data);
++            } else {
++                g_debug("failed to get device interface details");
++                break;
++            }
++        }
++        if (!result) {
++            g_debug("skipping device");
++            continue;
++        }
++
++        g_debug("  device: %s", pdev_iface_detail_data->DevicePath);
++        dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0,
++            FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
++        if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER,
++                NULL, 0, &sdn, sizeof(sdn), &size, NULL)) {
++            CloseHandle(dev_file);
++            debug_error("failed to get storage device number");
++            continue;
++        }
++        CloseHandle(dev_file);
++
++        disk = g_new0(GuestDiskInfo, 1);
++        disk->name = g_strdup_printf("\\\\.\\PhysicalDrive%lu",
++            sdn.DeviceNumber);
++
++        g_debug("  number: %lu", sdn.DeviceNumber);
++        address = g_malloc0(sizeof(GuestDiskAddress));
++        address->has_dev = true;
++        address->dev = g_strdup(disk->name);
++        get_single_disk_info(sdn.DeviceNumber, address, &local_err);
++        if (local_err) {
++            g_debug("failed to get disk info: %s",
++                error_get_pretty(local_err));
++            error_free(local_err);
++            qapi_free_GuestDiskAddress(address);
++            address = NULL;
++        } else {
++            disk->address = address;
++            disk->has_address = true;
++        }
++
++        new = g_malloc0(sizeof(GuestDiskInfoList));
++        new->value = disk;
++        new->next = ret;
++        ret = new;
++    }
++
++    SetupDiDestroyDeviceInfoList(dev_info);
++    return ret;
++}
++
+ #else
+ 
+ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
+@@ -967,6 +1062,12 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
+     return NULL;
+ }
+ 
++GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
++{
++    error_setg(errp, QERR_UNSUPPORTED);
++    return NULL;
++}
++
+ #endif /* CONFIG_QGA_NTDDSCSI */
+ 
+ static GuestFilesystemInfo *build_guest_fsinfo(char *guid, Error **errp)
+@@ -2234,9 +2335,3 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp)
+ 
+     return info;
+ }
+-
+-GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
+-{
+-    error_setg(errp, QERR_UNSUPPORTED);
+-    return NULL;
+-}
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qga-fix-assert-regression-on-guest-shutdown.patch b/SOURCES/kvm-qga-fix-assert-regression-on-guest-shutdown.patch
new file mode 100644
index 0000000..d16f0c3
--- /dev/null
+++ b/SOURCES/kvm-qga-fix-assert-regression-on-guest-shutdown.patch
@@ -0,0 +1,61 @@
+From 1f47578a5af4e7d4e1587d2334a07e867cf819d4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Tue, 24 Nov 2020 08:43:38 -0500
+Subject: [PATCH] qga: fix assert regression on guest-shutdown
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20201124084338.199348-2-marcandre.lureau@redhat.com>
+Patchwork-id: 99877
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 1/1] qga: fix assert regression on guest-shutdown
+Bugzilla: 1900578
+RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+Since commit 781f2b3d1e ("qga: process_event() simplification"),
+send_response() is called unconditionally, but will assert when "rsp" is
+NULL. This may happen with QCO_NO_SUCCESS_RESP commands, such as
+"guest-shutdown".
+
+Fixes: 781f2b3d1e5ef389b44016a897fd55e7a780bf35
+Cc: Michael Roth <mdroth@linux.vnet.ibm.com>
+Reported-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+Reviewed-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
+Tested-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
+Cc: qemu-stable@nongnu.org
+Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
+
+(cherry picked from commit 844bd70b5652f30bbace89499f513e3fbbb6457a)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ qga/main.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/qga/main.c b/qga/main.c
+index c35c2a21209..12fa463f4cd 100644
+--- a/qga/main.c
++++ b/qga/main.c
+@@ -529,7 +529,11 @@ static int send_response(GAState *s, const QDict *rsp)
+     QString *payload_qstr, *response_qstr;
+     GIOStatus status;
+ 
+-    g_assert(rsp && s->channel);
++    g_assert(s->channel);
++
++    if (!rsp) {
++        return 0;
++    }
+ 
+     payload_qstr = qobject_to_json(QOBJECT(rsp));
+     if (!payload_qstr) {
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qga-fix-missing-closedir-in-qmp_guest_get_disks.patch b/SOURCES/kvm-qga-fix-missing-closedir-in-qmp_guest_get_disks.patch
new file mode 100644
index 0000000..a01ecc0
--- /dev/null
+++ b/SOURCES/kvm-qga-fix-missing-closedir-in-qmp_guest_get_disks.patch
@@ -0,0 +1,56 @@
+From 12e5342e10c384539c8c26f075ce98ebbe887a05 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:41:00 -0500
+Subject: [PATCH 09/10] qga: fix missing closedir() in qmp_guest_get_disks()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-10-marcandre.lureau@redhat.com>
+Patchwork-id: 100528
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 09/10] qga: fix missing closedir() in qmp_guest_get_disks()
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Michael Roth <michael.roth@amd.com>
+
+We opendir("/sys/block") at the beginning of the function, but we never
+close it prior to returning.
+
+Fixes: Coverity CID 1436130
+Fixes: fed3956429d5 ("qga: add implementation of guest-get-disks for Linux")
+Reported-by: Peter Maydell <peter.maydell@linaro.org>
+Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
+Cc: Tomáš Golembiovský <tgolembi@redhat.com>
+Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+Signed-off-by: Michael Roth <michael.roth@amd.com>
+
+(cherry-picked from commit b1b9ab1c04d560f86d8da3dfca4d8b21de75fee6)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ qga/commands-posix.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/qga/commands-posix.c b/qga/commands-posix.c
+index af80bb7ccbb..1a9c2cbc3e6 100644
+--- a/qga/commands-posix.c
++++ b/qga/commands-posix.c
+@@ -1384,6 +1384,9 @@ GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
+         get_disk_deps(disk_dir, disk);
+         ret = get_disk_partitions(ret, de->d_name, disk_dir, dev_name);
+     }
++
++    closedir(dp);
++
+     return ret;
+ }
+ 
+-- 
+2.27.0
+
diff --git a/SOURCES/kvm-qga-update-schema-for-guest-get-disks-dependents-fie.patch b/SOURCES/kvm-qga-update-schema-for-guest-get-disks-dependents-fie.patch
new file mode 100644
index 0000000..3ec8b80
--- /dev/null
+++ b/SOURCES/kvm-qga-update-schema-for-guest-get-disks-dependents-fie.patch
@@ -0,0 +1,115 @@
+From 0829b1e0a9ca1a8270e138beb0c58b0b1ad67c9a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
+Date: Fri, 8 Jan 2021 07:41:01 -0500
+Subject: [PATCH 10/10] qga: update schema for guest-get-disks 'dependents'
+ field
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: <20210108074101.290008-11-marcandre.lureau@redhat.com>
+Patchwork-id: 100529
+O-Subject: [RHEL-8.3.0.z qemu-kvm PATCH 10/10] qga: update schema for guest-get-disks 'dependents' field
+Bugzilla: 1913818
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
+RH-Acked-by: Stefano Garzarella <sgarzare@redhat.com>
+
+From: Marc-André Lureau <marcandre.lureau@redhat.com>
+
+From: Michael Roth <michael.roth@amd.com>
+
+The recently-added 'guest-get-disk' command returns a list of
+GuestDiskInfo entries, which in turn have a 'dependents' field which
+lists devices these entries are dependent upon. Thus, 'dependencies'
+is a better name for this field. Address this by renaming the field
+accordingly.
+
+Additionally, 'dependents' is specified as non-optional, even though
+it's not implemented for w32. This is misleading, since it gives users
+the impression that a particular disk might not have dependencies,
+when in reality that information is simply not known to the guest
+agent. Address this by making 'dependents' an optional field, and only
+marking it as in-use when the facilities to obtain this information are
+available to the guest agent.
+
+Cc: Eric Blake <eblake@redhat.com>
+Cc: Tomáš Golembiovský <tgolembi@redhat.com>
+Cc: Marc-André Lureau <marcandre.lureau@redhat.com>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Michael Roth <michael.roth@amd.com>
+
+(cherry-picked from commit a8aa94b5f8427cc2924d8cdd417c8014db1c86c0)
+Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
+---
+ qga/commands-posix.c | 10 ++++++----
+ qga/qapi-schema.json |  8 ++++----
+ 2 files changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/qga/commands-posix.c b/qga/commands-posix.c
+index 1a9c2cbc3e6..38bc9a229db 100644
+--- a/qga/commands-posix.c
++++ b/qga/commands-posix.c
+@@ -1226,6 +1226,7 @@ static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
+         g_debug("failed to list entries in %s", deps_dir);
+         return;
+     }
++    disk->has_dependencies = true;
+     while ((dep = g_dir_read_name(dp_deps)) != NULL) {
+         g_autofree char *dep_dir = NULL;
+         strList *dep_item = NULL;
+@@ -1238,8 +1239,8 @@ static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
+             g_debug("  adding dependent device: %s", dev_name);
+             dep_item = g_new0(strList, 1);
+             dep_item->value = dev_name;
+-            dep_item->next = disk->dependents;
+-            disk->dependents = dep_item;
++            dep_item->next = disk->dependencies;
++            disk->dependencies = dep_item;
+         }
+     }
+     g_dir_close(dp_deps);
+@@ -1292,8 +1293,9 @@ static GuestDiskInfoList *get_disk_partitions(
+         partition->name = dev_name;
+         partition->partition = true;
+         /* Add parent disk as dependent for easier tracking of hierarchy */
+-        partition->dependents = g_new0(strList, 1);
+-        partition->dependents->value = g_strdup(disk_dev);
++        partition->dependencies = g_new0(strList, 1);
++        partition->dependencies->value = g_strdup(disk_dev);
++        partition->has_dependencies = true;
+ 
+         item = g_new0(GuestDiskInfoList, 1);
+         item->value = partition;
+diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
+index 22df375c92f..4222cb92d34 100644
+--- a/qga/qapi-schema.json
++++ b/qga/qapi-schema.json
+@@ -857,9 +857,9 @@
+ #
+ # @name: device node (Linux) or device UNC (Windows)
+ # @partition: whether this is a partition or disk
+-# @dependents: list of dependent devices; e.g. for LVs of the LVM this will
+-#              hold the list of PVs, for LUKS encrypted volume this will
+-#              contain the disk where the volume is placed.     (Linux)
++# @dependencies: list of device dependencies; e.g. for LVs of the LVM this will
++#                hold the list of PVs, for LUKS encrypted volume this will
++#                contain the disk where the volume is placed.     (Linux)
+ # @address: disk address information (only for non-virtual devices)
+ # @alias: optional alias assigned to the disk, on Linux this is a name assigned
+ #         by device mapper
+@@ -867,7 +867,7 @@
+ # Since 5.2
+ ##
+ { 'struct': 'GuestDiskInfo',
+-  'data': {'name': 'str', 'partition': 'bool', 'dependents': ['str'],
++  'data': {'name': 'str', 'partition': 'bool', '*dependencies': ['str'],
+            '*address': 'GuestDiskAddress', '*alias': 'str'} }
+ 
+ ##
+-- 
+2.27.0
+
diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec
index 483b69d..94de815 100644
--- a/SPECS/qemu-kvm.spec
+++ b/SPECS/qemu-kvm.spec
@@ -67,7 +67,7 @@ Obsoletes: %1-rhev
 Summary: QEMU is a machine emulator and virtualizer
 Name: qemu-kvm
 Version: 4.2.0
-Release: 34%{?dist}.1
+Release: 34%{?dist}.3
 # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
 Epoch: 15
 License: GPLv2 and GPLv2+ and CC-BY
@@ -940,6 +940,28 @@ Patch391: kvm-s390x-protvirt-allow-to-IPL-secure-guests-with-no-re.patch
 Patch392: kvm-usb-fix-setup_len-init-CVE-2020-14364.patch
 # For bz#1890885 - qemu use SCMP_ACT_TRAP even SCMP_ACT_KILL_PROCESS is available [rhel-8.3.0.z]
 Patch393: kvm-seccomp-fix-killing-of-whole-process-instead-of-thre.patch
+# For bz#1900578 - qemu-ga aborts after guest-shutdown command [rhel-8.3.0.z]
+Patch394: kvm-qga-fix-assert-regression-on-guest-shutdown.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch395: kvm-qapi-enable-use-of-g_autoptr-with-QAPI-types.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch396: kvm-error-Fix-examples-in-error.h-s-big-comment.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch397: kvm-error-Improve-error.h-s-big-comment.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch398: kvm-error-Document-Error-API-usage-rules.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch399: kvm-error-New-macro-ERRP_GUARD.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch400: kvm-qga-add-command-guest-get-disks.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch401: kvm-qga-add-implementation-of-guest-get-disks-for-Linux.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch402: kvm-qga-add-implementation-of-guest-get-disks-for-Window.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch403: kvm-qga-fix-missing-closedir-in-qmp_guest_get_disks.patch
+# For bz#1913818 - Report logical_name for disks without mounted file-system [rhel-8.3.0.z]
+Patch404: kvm-qga-update-schema-for-guest-get-disks-dependents-fie.patch
 
 BuildRequires: wget
 BuildRequires: rpm-build
@@ -1875,6 +1897,25 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
 
 
 %changelog
+* Fri Feb 05 2021 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 4.2.0-34.el8_3.3
+- kvm-qapi-enable-use-of-g_autoptr-with-QAPI-types.patch [bz#1913818]
+- kvm-error-Fix-examples-in-error.h-s-big-comment.patch [bz#1913818]
+- kvm-error-Improve-error.h-s-big-comment.patch [bz#1913818]
+- kvm-error-Document-Error-API-usage-rules.patch [bz#1913818]
+- kvm-error-New-macro-ERRP_GUARD.patch [bz#1913818]
+- kvm-qga-add-command-guest-get-disks.patch [bz#1913818]
+- kvm-qga-add-implementation-of-guest-get-disks-for-Linux.patch [bz#1913818]
+- kvm-qga-add-implementation-of-guest-get-disks-for-Window.patch [bz#1913818]
+- kvm-qga-fix-missing-closedir-in-qmp_guest_get_disks.patch [bz#1913818]
+- kvm-qga-update-schema-for-guest-get-disks-dependents-fie.patch [bz#1913818]
+- Resolves: bz#1913818
+  (Report logical_name for disks without mounted file-system [rhel-8.3.0.z])
+
+* Wed Dec 09 2020 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 4.2.0-34.el8_3.2
+- kvm-qga-fix-assert-regression-on-guest-shutdown.patch [bz#1900578]
+- Resolves: bz#1900578
+  (qemu-ga aborts after guest-shutdown command [rhel-8.3.0.z])
+
 * Mon Nov 23 2020 Danilo Cesar Lemes de Paula <ddepaula@redhat.com> - 4.2.0-34.el8_3.1
 - kvm-seccomp-fix-killing-of-whole-process-instead-of-thre.patch [bz#1890885]
 - Resolves: bz#1890885