Signed-off-by: Laszlo Ersek <ler...@redhat.com> --- qga/commands-posix.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 87 insertions(+), 0 deletions(-)
diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 1ad231a..d4b6bdc 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -15,6 +15,9 @@ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/wait.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> #include "qga/guest-agent-core.h" #include "qga-qmp-commands.h" #include "qapi/qmp/qerror.h" @@ -1083,9 +1086,93 @@ void qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **err) } #endif +#if defined(__linux__) +#define SYSCONF_EXACT(name, err) sysconf_exact((name), #name, (err)) + +static long sysconf_exact(int name, const char *name_str, Error **err) +{ + long ret; + + errno = 0; + ret = sysconf(name); + if (ret == -1) { + if (errno == 0) { + error_setg(err, "sysconf(%s): value indefinite", name_str); + } else { + error_setg_errno(err, errno, "sysconf(%s)", name_str); + } + } + return ret; +} + +/* + * Store a VCPU structure under the link, and return the link to store into + * at the next time. + */ +static GuestLogicalProcessorList ** +append_vcpu(int64_t logical_id, bool online, GuestLogicalProcessorList **link) +{ + GuestLogicalProcessor *vcpu; + GuestLogicalProcessorList *entry; + + vcpu = g_malloc0(sizeof *vcpu); + vcpu->logical_id = logical_id; + vcpu->online = online; + + entry = g_malloc0(sizeof *entry); + entry->value = vcpu; + + *link = entry; + return &entry->next; +} +#endif + GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) { +#if defined(__linux__) + long current; + GuestLogicalProcessorList **link, *head; + long sc_max; + Error *local_err = NULL; + + current = 0; + link = append_vcpu(current++, true, &head); + + sc_max = SYSCONF_EXACT(_SC_NPROCESSORS_CONF, &local_err); + while (local_err == NULL && current < sc_max) { + char *buf; + FILE *f; + + buf = g_strdup_printf("/sys/devices/system/cpu/cpu%ld/online", + current); + f = fopen(buf, "r"); + if (f == NULL) { + error_setg_errno(&local_err, errno, "fopen(\"%s\", \"r\")", buf); + } else { + unsigned online; + + if (fscanf(f, "%u", &online) != 1) { + error_setg(&local_err, "failed to read or parse \"%s\"", buf); + } else { + link = append_vcpu(current++, online != 0, link); + } + + if (fclose(f) == EOF && local_err == NULL) { + error_setg_errno(&local_err, errno, "fclose(\"%s\")", buf); + } + } + g_free(buf); + } + + if (local_err == NULL) { + return head; + } + + qapi_free_GuestLogicalProcessorList(head); + error_propagate(errp, local_err); +#else error_set(errp, QERR_UNSUPPORTED); +#endif return NULL; } -- 1.7.1