Skip to content

Commit aee4734

Browse files
Igor Mammedovmdroth
Igor Mammedov
authored andcommitted
qga: ignore non present cpus when handling qmp_guest_get_vcpus()
If VM has VCPUs plugged sparselly (for example a VM started with 3 VCPUs (cpu0, cpu1 and cpu2) and then cpu1 was hotunplugged so only cpu0 and cpu2 are present), QGA will rise a error error: internal error: unable to execute QEMU agent command 'guest-get-vcpus': open("/sys/devices/system/cpu/cpu1/"): No such file or directory when virsh vcpucount FOO --guest is executed. Fix it by ignoring non present CPUs when fetching CPUs status from sysfs. Signed-off-by: Igor Mammedov <[email protected]> Reviewed-by: Laszlo Ersek <[email protected]> Reviewed-by: Marc-André Lureau <[email protected]> Signed-off-by: Michael Roth <[email protected]>
1 parent ebb55d0 commit aee4734

File tree

1 file changed

+59
-56
lines changed

1 file changed

+59
-56
lines changed

qga/commands-posix.c

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,61 +2035,56 @@ static long sysconf_exact(int name, const char *name_str, Error **errp)
20352035
* Written members remain unmodified on error.
20362036
*/
20372037
static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu,
2038-
Error **errp)
2038+
char *dirpath, Error **errp)
20392039
{
2040-
char *dirpath;
2040+
int fd;
2041+
int res;
20412042
int dirfd;
2043+
static const char fn[] = "online";
20422044

2043-
dirpath = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/",
2044-
vcpu->logical_id);
20452045
dirfd = open(dirpath, O_RDONLY | O_DIRECTORY);
20462046
if (dirfd == -1) {
20472047
error_setg_errno(errp, errno, "open(\"%s\")", dirpath);
2048-
} else {
2049-
static const char fn[] = "online";
2050-
int fd;
2051-
int res;
2052-
2053-
fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR);
2054-
if (fd == -1) {
2055-
if (errno != ENOENT) {
2056-
error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn);
2057-
} else if (sys2vcpu) {
2058-
vcpu->online = true;
2059-
vcpu->can_offline = false;
2060-
} else if (!vcpu->online) {
2061-
error_setg(errp, "logical processor #%" PRId64 " can't be "
2062-
"offlined", vcpu->logical_id);
2063-
} /* otherwise pretend successful re-onlining */
2064-
} else {
2065-
unsigned char status;
2066-
2067-
res = pread(fd, &status, 1, 0);
2068-
if (res == -1) {
2069-
error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn);
2070-
} else if (res == 0) {
2071-
error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath,
2072-
fn);
2073-
} else if (sys2vcpu) {
2074-
vcpu->online = (status != '0');
2075-
vcpu->can_offline = true;
2076-
} else if (vcpu->online != (status != '0')) {
2077-
status = '0' + vcpu->online;
2078-
if (pwrite(fd, &status, 1, 0) == -1) {
2079-
error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath,
2080-
fn);
2081-
}
2082-
} /* otherwise pretend successful re-(on|off)-lining */
2048+
return;
2049+
}
20832050

2084-
res = close(fd);
2085-
g_assert(res == 0);
2086-
}
2051+
fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR);
2052+
if (fd == -1) {
2053+
if (errno != ENOENT) {
2054+
error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn);
2055+
} else if (sys2vcpu) {
2056+
vcpu->online = true;
2057+
vcpu->can_offline = false;
2058+
} else if (!vcpu->online) {
2059+
error_setg(errp, "logical processor #%" PRId64 " can't be "
2060+
"offlined", vcpu->logical_id);
2061+
} /* otherwise pretend successful re-onlining */
2062+
} else {
2063+
unsigned char status;
2064+
2065+
res = pread(fd, &status, 1, 0);
2066+
if (res == -1) {
2067+
error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn);
2068+
} else if (res == 0) {
2069+
error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath,
2070+
fn);
2071+
} else if (sys2vcpu) {
2072+
vcpu->online = (status != '0');
2073+
vcpu->can_offline = true;
2074+
} else if (vcpu->online != (status != '0')) {
2075+
status = '0' + vcpu->online;
2076+
if (pwrite(fd, &status, 1, 0) == -1) {
2077+
error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath,
2078+
fn);
2079+
}
2080+
} /* otherwise pretend successful re-(on|off)-lining */
20872081

2088-
res = close(dirfd);
2082+
res = close(fd);
20892083
g_assert(res == 0);
20902084
}
20912085

2092-
g_free(dirpath);
2086+
res = close(dirfd);
2087+
g_assert(res == 0);
20932088
}
20942089

20952090
GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
@@ -2107,17 +2102,21 @@ GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp)
21072102
while (local_err == NULL && current < sc_max) {
21082103
GuestLogicalProcessor *vcpu;
21092104
GuestLogicalProcessorList *entry;
2110-
2111-
vcpu = g_malloc0(sizeof *vcpu);
2112-
vcpu->logical_id = current++;
2113-
vcpu->has_can_offline = true; /* lolspeak ftw */
2114-
transfer_vcpu(vcpu, true, &local_err);
2115-
2116-
entry = g_malloc0(sizeof *entry);
2117-
entry->value = vcpu;
2118-
2119-
*link = entry;
2120-
link = &entry->next;
2105+
int64_t id = current++;
2106+
char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/",
2107+
id);
2108+
2109+
if (g_file_test(path, G_FILE_TEST_EXISTS)) {
2110+
vcpu = g_malloc0(sizeof *vcpu);
2111+
vcpu->logical_id = id;
2112+
vcpu->has_can_offline = true; /* lolspeak ftw */
2113+
transfer_vcpu(vcpu, true, path, &local_err);
2114+
entry = g_malloc0(sizeof *entry);
2115+
entry->value = vcpu;
2116+
*link = entry;
2117+
link = &entry->next;
2118+
}
2119+
g_free(path);
21212120
}
21222121

21232122
if (local_err == NULL) {
@@ -2138,7 +2137,11 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList *vcpus, Error **errp)
21382137

21392138
processed = 0;
21402139
while (vcpus != NULL) {
2141-
transfer_vcpu(vcpus->value, false, &local_err);
2140+
char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/",
2141+
vcpus->value->logical_id);
2142+
2143+
transfer_vcpu(vcpus->value, false, path, &local_err);
2144+
g_free(path);
21422145
if (local_err != NULL) {
21432146
break;
21442147
}

0 commit comments

Comments
 (0)