diff options
author | Lin Ma <lma@suse.com> | 2021-02-24 13:14:28 +0800 |
---|---|---|
committer | Michael Roth <michael.roth@amd.com> | 2021-03-16 19:47:32 -0500 |
commit | 27e7de3ca740cffbdfc06e9cb138f3339d14dda7 (patch) | |
tree | 1a609865bb4cf14042fa361c8957d2324079c164 | |
parent | 5b7f5586d182b0cafb1f8d558992a14763e2953e (diff) |
qga: Correct loop count in qmp_guest_get_vcpus()
The guest-get-vcpus returns incorrect vcpu info in case we hotunplug vcpus(not
the last one).
e.g.:
A VM has 4 VCPUs: cpu0 + 3 hotunpluggable online vcpus(cpu1, cpu2 and cpu3).
Hotunplug cpu2, Now only cpu0, cpu1 and cpu3 are present & online.
./qmp-shell /tmp/qmp-monitor.sock
(QEMU) query-hotpluggable-cpus
{"return": [
{"props": {"core-id": 0, "thread-id": 0, "socket-id": 3}, "vcpus-count": 1,
"qom-path": "/machine/peripheral/cpu3", "type": "host-x86_64-cpu"},
{"props": {"core-id": 0, "thread-id": 0, "socket-id": 2}, "vcpus-count": 1,
"qom-path": "/machine/peripheral/cpu2", "type": "host-x86_64-cpu"},
{"props": {"core-id": 0, "thread-id": 0, "socket-id": 1}, "vcpus-count": 1,
"qom-path": "/machine/peripheral/cpu1", "type": "host-x86_64-cpu"},
{"props": {"core-id": 0, "thread-id": 0, "socket-id": 0}, "vcpus-count": 1,
"qom-path": "/machine/unattached/device[0]", "type": "host-x86_64-cpu"}
]}
(QEMU) device_del id=cpu2
{"return": {}}
(QEMU) query-hotpluggable-cpus
{"return": [
{"props": {"core-id": 0, "thread-id": 0, "socket-id": 3}, "vcpus-count": 1,
"qom-path": "/machine/peripheral/cpu3", "type": "host-x86_64-cpu"},
{"props": {"core-id": 0, "thread-id": 0, "socket-id": 2}, "vcpus-count": 1,
"type": "host-x86_64-cpu"},
{"props": {"core-id": 0, "thread-id": 0, "socket-id": 1}, "vcpus-count": 1,
"qom-path": "/machine/peripheral/cpu1", "type": "host-x86_64-cpu"},
{"props": {"core-id": 0, "thread-id": 0, "socket-id": 0}, "vcpus-count": 1,
"qom-path": "/machine/unattached/device[0]", "type": "host-x86_64-cpu"}
]}
Before:
./qmp-shell -N /tmp/qmp-ga.sock
Welcome to the QMP low-level shell!
Connected
(QEMU) guest-get-vcpus
{"return": [
{"online": true, "can-offline": false, "logical-id": 0},
{"online": true, "can-offline": true, "logical-id": 1}]}
After:
./qmp-shell -N /tmp/qmp-ga.sock
Welcome to the QMP low-level shell!
Connected
(QEMU) guest-get-vcpus
{"return": [
{"online": true, "can-offline": false, "logical-id": 0},
{"online": true, "can-offline": true, "logical-id": 1},
{"online": true, "can-offline": true, "logical-id": 3}]}
Signed-off-by: Lin Ma <lma@suse.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
*fix build breakage by using PRId64 for sscanf
Signed-off-by: Michael Roth <michael.roth@amd.com>
-rw-r--r-- | qga/commands-posix.c | 43 |
1 files changed, 14 insertions, 29 deletions
diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 3f18df1bb6..665735fd09 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -2370,24 +2370,6 @@ error: return NULL; } -#define SYSCONF_EXACT(name, errp) sysconf_exact((name), #name, (errp)) - -static long sysconf_exact(int name, const char *name_str, Error **errp) -{ - long ret; - - errno = 0; - ret = sysconf(name); - if (ret == -1) { - if (errno == 0) { - error_setg(errp, "sysconf(%s): value indefinite", name_str); - } else { - error_setg_errno(errp, errno, "sysconf(%s)", name_str); - } - } - return ret; -} - /* Transfer online/offline status between @vcpu and the guest system. * * On input either @errp or *@errp must be NULL. @@ -2458,30 +2440,33 @@ static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu, GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) { - int64_t current; GuestLogicalProcessorList *head, **tail; - long sc_max; + const char *cpu_dir = "/sys/devices/system/cpu"; + const gchar *line; + g_autoptr(GDir) cpu_gdir = NULL; Error *local_err = NULL; - current = 0; head = NULL; tail = &head; - sc_max = SYSCONF_EXACT(_SC_NPROCESSORS_CONF, &local_err); + cpu_gdir = g_dir_open(cpu_dir, 0, NULL); - while (local_err == NULL && current < sc_max) { - GuestLogicalProcessor *vcpu; - int64_t id = current++; - char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", - id); + if (cpu_gdir == NULL) { + error_setg_errno(errp, errno, "failed to list entries: %s", cpu_dir); + return NULL; + } - if (g_file_test(path, G_FILE_TEST_EXISTS)) { + while (local_err == NULL && (line = g_dir_read_name(cpu_gdir)) != NULL) { + GuestLogicalProcessor *vcpu; + int64_t id; + if (sscanf(line, "cpu%" PRId64, &id)) { + g_autofree char *path = g_strdup_printf("/sys/devices/system/cpu/" + "cpu%" PRId64 "/", id); vcpu = g_malloc0(sizeof *vcpu); vcpu->logical_id = id; vcpu->has_can_offline = true; /* lolspeak ftw */ transfer_vcpu(vcpu, true, path, &local_err); QAPI_LIST_APPEND(tail, vcpu); } - g_free(path); } if (local_err == NULL) { |