Quoting Igor Mammedov (2018-09-06 07:51:54) > 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 <imamm...@redhat.com>
Thanks, applied to qga tree: https://github.com/mdroth/qemu/commits/qga > --- > v2: > do not create CPU entry if cpu isn't present > (Laszlo Ersek <ler...@redhat.com>) > --- > qga/commands-posix.c | 115 > ++++++++++++++++++++++++++------------------------- > 1 file changed, 59 insertions(+), 56 deletions(-) > > diff --git a/qga/commands-posix.c b/qga/commands-posix.c > index 37e8a2d..42d30f0 100644 > --- a/qga/commands-posix.c > +++ b/qga/commands-posix.c > @@ -2035,61 +2035,56 @@ static long sysconf_exact(int name, const char > *name_str, Error **errp) > * Written members remain unmodified on error. > */ > static void transfer_vcpu(GuestLogicalProcessor *vcpu, bool sys2vcpu, > - Error **errp) > + char *dirpath, Error **errp) > { > - char *dirpath; > + int fd; > + int res; > int dirfd; > + static const char fn[] = "online"; > > - dirpath = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 "/", > - vcpu->logical_id); > dirfd = open(dirpath, O_RDONLY | O_DIRECTORY); > if (dirfd == -1) { > error_setg_errno(errp, errno, "open(\"%s\")", dirpath); > - } else { > - static const char fn[] = "online"; > - int fd; > - int res; > - > - fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); > - if (fd == -1) { > - if (errno != ENOENT) { > - error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, > fn); > - } else if (sys2vcpu) { > - vcpu->online = true; > - vcpu->can_offline = false; > - } else if (!vcpu->online) { > - error_setg(errp, "logical processor #%" PRId64 " can't be " > - "offlined", vcpu->logical_id); > - } /* otherwise pretend successful re-onlining */ > - } else { > - unsigned char status; > - > - res = pread(fd, &status, 1, 0); > - if (res == -1) { > - error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, > fn); > - } else if (res == 0) { > - error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, > - fn); > - } else if (sys2vcpu) { > - vcpu->online = (status != '0'); > - vcpu->can_offline = true; > - } else if (vcpu->online != (status != '0')) { > - status = '0' + vcpu->online; > - if (pwrite(fd, &status, 1, 0) == -1) { > - error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", > dirpath, > - fn); > - } > - } /* otherwise pretend successful re-(on|off)-lining */ > + return; > + } > > - res = close(fd); > - g_assert(res == 0); > - } > + fd = openat(dirfd, fn, sys2vcpu ? O_RDONLY : O_RDWR); > + if (fd == -1) { > + if (errno != ENOENT) { > + error_setg_errno(errp, errno, "open(\"%s/%s\")", dirpath, fn); > + } else if (sys2vcpu) { > + vcpu->online = true; > + vcpu->can_offline = false; > + } else if (!vcpu->online) { > + error_setg(errp, "logical processor #%" PRId64 " can't be " > + "offlined", vcpu->logical_id); > + } /* otherwise pretend successful re-onlining */ > + } else { > + unsigned char status; > + > + res = pread(fd, &status, 1, 0); > + if (res == -1) { > + error_setg_errno(errp, errno, "pread(\"%s/%s\")", dirpath, fn); > + } else if (res == 0) { > + error_setg(errp, "pread(\"%s/%s\"): unexpected EOF", dirpath, > + fn); > + } else if (sys2vcpu) { > + vcpu->online = (status != '0'); > + vcpu->can_offline = true; > + } else if (vcpu->online != (status != '0')) { > + status = '0' + vcpu->online; > + if (pwrite(fd, &status, 1, 0) == -1) { > + error_setg_errno(errp, errno, "pwrite(\"%s/%s\")", dirpath, > + fn); > + } > + } /* otherwise pretend successful re-(on|off)-lining */ > > - res = close(dirfd); > + res = close(fd); > g_assert(res == 0); > } > > - g_free(dirpath); > + res = close(dirfd); > + g_assert(res == 0); > } > > GuestLogicalProcessorList *qmp_guest_get_vcpus(Error **errp) > @@ -2107,17 +2102,21 @@ GuestLogicalProcessorList *qmp_guest_get_vcpus(Error > **errp) > while (local_err == NULL && current < sc_max) { > GuestLogicalProcessor *vcpu; > GuestLogicalProcessorList *entry; > - > - vcpu = g_malloc0(sizeof *vcpu); > - vcpu->logical_id = current++; > - vcpu->has_can_offline = true; /* lolspeak ftw */ > - transfer_vcpu(vcpu, true, &local_err); > - > - entry = g_malloc0(sizeof *entry); > - entry->value = vcpu; > - > - *link = entry; > - link = &entry->next; > + int64_t id = current++; > + char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 > "/", > + id); > + > + if (g_file_test(path, G_FILE_TEST_EXISTS)) { > + vcpu = g_malloc0(sizeof *vcpu); > + vcpu->logical_id = id; > + vcpu->has_can_offline = true; /* lolspeak ftw */ > + transfer_vcpu(vcpu, true, path, &local_err); > + entry = g_malloc0(sizeof *entry); > + entry->value = vcpu; > + *link = entry; > + link = &entry->next; > + } > + g_free(path); > } > > if (local_err == NULL) { > @@ -2138,7 +2137,11 @@ int64_t qmp_guest_set_vcpus(GuestLogicalProcessorList > *vcpus, Error **errp) > > processed = 0; > while (vcpus != NULL) { > - transfer_vcpu(vcpus->value, false, &local_err); > + char *path = g_strdup_printf("/sys/devices/system/cpu/cpu%" PRId64 > "/", > + vcpus->value->logical_id); > + > + transfer_vcpu(vcpus->value, false, path, &local_err); > + g_free(path); > if (local_err != NULL) { > break; > } > -- > 2.7.4 >