From: Igor Mammedov <imammedo@redhat.com>
To: qemu-devel@nongnu.org
Cc: lersek@redhat.com
Subject: [Qemu-devel] [PATCH 2/2] guest-agent: preserve online/offline state of VCPUs on guest reboot
Date: Mon, 6 Oct 2014 07:44:51 +0000 [thread overview]
Message-ID: <1412581491-31656-3-git-send-email-imammedo@redhat.com> (raw)
In-Reply-To: <1412581491-31656-1-git-send-email-imammedo@redhat.com>
Fixes issue when CPU was offlined via libvirt using command:
virsh setvcpus --guest myguest NR_CPUS
but it became onlined again after guest was rebooted.
Fix issue by storing current state of CPUs online state
on persistent storage when GA is being stopped and restore
it when it's started at system boot time.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
qga/main.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
diff --git a/qga/main.c b/qga/main.c
index 5afba01..1173ca9 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -32,6 +32,7 @@
#include "qapi/qmp/dispatch.h"
#include "qga/channel.h"
#include "qemu/bswap.h"
+#include "qga-qmp-commands.h"
#ifdef _WIN32
#include "qga/service-win32.h"
#include "qga/vss-win32.h"
@@ -57,6 +58,7 @@
#define QGA_FSFREEZE_HOOK_DEFAULT CONFIG_QEMU_CONFDIR "/fsfreeze-hook"
#endif
#define QGA_SENTINEL_BYTE 0xFF
+#define QGA_CPU_STATE_GROUP "CPU online states"
static struct {
const char *state_dir;
@@ -66,6 +68,7 @@ static struct {
typedef struct GAPersistentState {
#define QGA_PSTATE_DEFAULT_FD_COUNTER 1000
int64_t fd_counter;
+ GuestLogicalProcessorList *vcpus;
} GAPersistentState;
struct GAState {
@@ -770,6 +773,40 @@ static void persistent_state_from_keyfile(GAPersistentState *pstate,
pstate->fd_counter =
g_key_file_get_integer(keyfile, "global", "fd_counter", NULL);
}
+
+ if (g_key_file_has_group(keyfile, QGA_CPU_STATE_GROUP)) {
+ bool state;
+ char **cpu_id_str;
+ GuestLogicalProcessor *vcpu;
+ GuestLogicalProcessorList *entry;
+ GuestLogicalProcessorList *head, **link;
+ char **cpus_list = g_key_file_get_keys(keyfile, QGA_CPU_STATE_GROUP,
+ NULL, NULL);
+
+ head = NULL;
+ link = &head;
+ for (cpu_id_str = cpus_list; *cpu_id_str; ++cpu_id_str) {
+ state = g_key_file_get_boolean(keyfile, QGA_CPU_STATE_GROUP,
+ *cpu_id_str, NULL);
+
+ vcpu = g_malloc0(sizeof *vcpu);
+ vcpu->logical_id = g_ascii_strtoll(*cpu_id_str, NULL, 0);
+ vcpu->online = state;
+ vcpu->has_can_offline = true;
+
+ entry = g_malloc0(sizeof *entry);
+ entry->value = vcpu;
+
+ *link = entry;
+ link = &entry->next;
+ }
+ pstate->vcpus = head;
+
+ g_strfreev(cpus_list);
+ }
+ if (pstate->vcpus == NULL) {
+ pstate->vcpus = qmp_guest_get_vcpus(NULL);
+ }
}
static void persistent_state_to_keyfile(const GAPersistentState *pstate,
@@ -779,6 +816,27 @@ static void persistent_state_to_keyfile(const GAPersistentState *pstate,
g_assert(keyfile);
g_key_file_set_integer(keyfile, "global", "fd_counter", pstate->fd_counter);
+
+ if (pstate->vcpus) {
+ GuestLogicalProcessorList *vcpus = pstate->vcpus;
+
+ while (vcpus != NULL) {
+ char *logical_id;
+ GuestLogicalProcessor *vcpu = vcpus->value;
+
+ if (vcpu->can_offline == false) {
+ vcpus = vcpus->next;
+ continue;
+ }
+
+ logical_id = g_strdup_printf("%" PRId64, vcpu->logical_id);
+ g_key_file_set_boolean(keyfile, QGA_CPU_STATE_GROUP,
+ logical_id, vcpu->online);
+ g_free(logical_id);
+
+ vcpus = vcpus->next;
+ }
+ }
}
static gboolean write_persistent_state(const GAPersistentState *pstate,
@@ -820,6 +878,47 @@ out:
return ret;
}
+static void ga_clean_vcpu_pstate(GAPersistentState *pstate)
+{
+ if (pstate->vcpus) {
+ qapi_free_GuestLogicalProcessorList(pstate->vcpus);
+ pstate->vcpus = NULL;
+ }
+}
+
+static void ga_clean_pstate(GAPersistentState *pstate)
+{
+ ga_clean_vcpu_pstate(pstate);
+}
+
+#if defined(__linux__)
+
+static void ga_update_vcpu_pstate(GAPersistentState *pstate, const char *path)
+{
+ Error *local_err = NULL;
+
+ ga_clean_vcpu_pstate(pstate);
+ pstate->vcpus = qmp_guest_get_vcpus(&local_err);
+
+ if (local_err != NULL) {
+ g_critical("%s", error_get_pretty(local_err));
+ error_free(local_err);
+ return;
+ }
+
+ if (!write_persistent_state(pstate, path)) {
+ g_critical("failed to commit CPU persistent state to disk");
+ }
+}
+
+#else
+
+static void ga_update_vcpu_pstate(GAPersistentState *pstate, const char *path)
+{
+}
+
+#endif
+
static gboolean read_persistent_state(GAPersistentState *pstate,
const gchar *path, gboolean frozen)
{
@@ -878,6 +977,7 @@ static gboolean read_persistent_state(GAPersistentState *pstate,
}
persistent_state_from_keyfile(pstate, keyfile);
+ qmp_guest_set_vcpus(pstate->vcpus, &error_abort);
out:
if (keyfile) {
@@ -1185,6 +1285,8 @@ int main(int argc, char **argv)
ga_command_state_cleanup_all(ga_state->command_state);
ga_channel_free(ga_state->channel);
+ ga_update_vcpu_pstate(&ga_state->pstate, ga_state->pstate_filepath);
+ ga_clean_pstate(&ga_state->pstate);
if (daemonize) {
unlink(pid_filepath);
--
1.8.3.1
next prev parent reply other threads:[~2014-10-06 7:45 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-06 7:44 [Qemu-devel] [PATCH 0/2] guest-agent: make CPU's online/offline state persistent Igor Mammedov
2014-10-06 7:44 ` [Qemu-devel] [PATCH 1/2] guest-agent: keep persistent state on persistent storage Igor Mammedov
2014-10-06 9:25 ` Laszlo Ersek
2014-10-06 7:44 ` Igor Mammedov [this message]
2014-10-06 9:46 ` [Qemu-devel] [PATCH 2/2] guest-agent: preserve online/offline state of VCPUs on guest reboot Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1412581491-31656-3-git-send-email-imammedo@redhat.com \
--to=imammedo@redhat.com \
--cc=lersek@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).