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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Markus Armbruster + +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 +Reviewed-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Greg Kurz +Message-Id: <20200707160613.848843-4-armbru@redhat.com> + +(cherry picked from commit e3fe3988d7851cac30abffae06d2f555ff7bee62) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Markus Armbruster + +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 +Reviewed-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Reviewed-by: Greg Kurz +Message-Id: <20200707160613.848843-2-armbru@redhat.com> + +(cherry picked from commit 47ff5ac81e8bb3096500de7b132051691d533d36) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Markus Armbruster + +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 +Message-Id: <20200707160613.848843-3-armbru@redhat.com> +Reviewed-by: Eric Blake +Reviewed-by: Greg Kurz + +(cherry picked from commit 9aac7d486cc792191c25c30851f501624b0c2751) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Vladimir Sementsov-Ogievskiy + +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 +Reviewed-by: Paul Durrant +Reviewed-by: Greg Kurz +Reviewed-by: Eric Blake +[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 +Message-Id: <20200707165037.1026246-2-armbru@redhat.com> + +(cherry picked from commit ae7c80a7bd73685437bf6ba9d7c26098351f4166) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Daniel P. Berrangé + +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é +Message-Id: <20200723153845.2934357-1-berrange@redhat.com> +Reviewed-by: Markus Armbruster +Reviewed-by: Eric Blake +Signed-off-by: Markus Armbruster + +(cherry picked from commit 221db5daf6b3666f1c8e4ca06ae45892e99a112f) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Tomáš Golembiovský + +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ý +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Marc-André Lureau +Signed-off-by: Michael Roth + +(cherry-picked from commit c27ea3f9ef7c7f29e55bde91879f8514abce9c38) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Tomáš Golembiovský + +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ý +Reviewed-by: Marc-André Lureau +*add missing stub for !defined(CONFIG_FSFREEZE) +*remove unused deps_dir variable +Signed-off-by: Michael Roth + +(cherry picked from commit fed3956429d560a06fc2d2fcf1a01efb58659f87) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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 "" or ++ * "p" ++ * ++ * @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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Tomáš Golembiovský + +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ý +Signed-off-by: Michael Roth + +(cherry picked from commit c67d2efd9d1771fd886e3b58771adaa62897f3d9) +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé + +From: Marc-André Lureau + +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 +Reported-by: Christian Ehrhardt +Signed-off-by: Marc-André Lureau +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Christian Ehrhardt +Tested-by: Christian Ehrhardt +Cc: qemu-stable@nongnu.org +Signed-off-by: Michael Roth + +(cherry picked from commit 844bd70b5652f30bbace89499f513e3fbbb6457a) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Michael Roth + +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 +Cc: Marc-André Lureau +Cc: Tomáš Golembiovský +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Michael Roth + +(cherry-picked from commit b1b9ab1c04d560f86d8da3dfca4d8b21de75fee6) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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?= +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 +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 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +From: Marc-André Lureau + +From: Michael Roth + +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 +Cc: Tomáš Golembiovský +Cc: Marc-André Lureau +Reviewed-by: Eric Blake +Reviewed-by: Marc-André Lureau +Signed-off-by: Michael Roth + +(cherry-picked from commit a8aa94b5f8427cc2924d8cdd417c8014db1c86c0) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + 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 - 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 - 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 - 4.2.0-34.el8_3.1 - kvm-seccomp-fix-killing-of-whole-process-instead-of-thre.patch [bz#1890885] - Resolves: bz#1890885