#include <net/if.h>
#include <sys/statvfs.h>
+#ifdef CONFIG_LIBUDEV
+#include <libudev.h>
+#endif
+
#ifdef FIFREEZE
#define CONFIG_FSFREEZE
#endif
GuestDiskAddressList *list = NULL;
bool has_ata = false, has_host = false, has_tgt = false;
char *p, *q, *driver = NULL;
+#ifdef CONFIG_LIBUDEV
+ struct udev *udev = NULL;
+ struct udev_device *udevice = NULL;
+#endif
p = strstr(syspath, "/devices/pci");
if (!p || sscanf(p + 12, "%*x:%*x/%x:%x:%x.%x%n",
break;
}
+ g_free(driver);
if (sscanf(p, "/%x:%x:%x.%x%n",
pci, pci + 1, pci + 2, pci + 3, &pcilen) == 4) {
p += pcilen;
list = g_malloc0(sizeof(*list));
list->value = disk;
+#ifdef CONFIG_LIBUDEV
+ udev = udev_new();
+ udevice = udev_device_new_from_syspath(udev, syspath);
+ if (udev == NULL || udevice == NULL) {
+ g_debug("failed to query udev");
+ } else {
+ const char *devnode, *serial;
+ devnode = udev_device_get_devnode(udevice);
+ if (devnode != NULL) {
+ disk->dev = g_strdup(devnode);
+ disk->has_dev = true;
+ }
+ serial = udev_device_get_property_value(udevice, "ID_SERIAL");
+ if (serial != NULL && *serial != 0) {
+ disk->serial = g_strdup(serial);
+ disk->has_serial = true;
+ }
+ }
+#endif
+
if (strcmp(driver, "ata_piix") == 0) {
/* a host per ide bus, target*:0:<unit>:0 */
if (!has_host || !has_tgt) {
list->next = fs->disk;
fs->disk = list;
- g_free(driver);
- return;
+ goto out;
cleanup:
if (list) {
qapi_free_GuestDiskAddressList(list);
}
+out:
g_free(driver);
+#ifdef CONFIG_LIBUDEV
+ udev_unref(udev);
+ udev_device_unref(udevice);
+#endif
+ return;
}
static void build_guest_fsinfo_for_device(char const *devpath,
/* cannot risk guest agent blocking itself on a write in this state */
ga_set_frozen(ga_state);
- QTAILQ_FOREACH_REVERSE(mount, &mounts, FsMountList, next) {
+ QTAILQ_FOREACH_REVERSE(mount, &mounts, next) {
/* To issue fsfreeze in the reverse order of mounts, check if the
* mount is listed in the list here */
if (has_mountpoints) {
return true;
}
- if (local_err) {
- error_propagate(errp, local_err);
- }
-
+ error_propagate(errp, local_err);
return false;
}
}
ret = read(fd, buf, sizeof(buf) - 1);
+ close(fd);
if (ret <= 0) {
return false;
}
if (!mode_supported) {
error_setg(errp,
"the requested suspend mode is not supported by the guest");
- } else if (local_err) {
+ } else {
error_propagate(errp, local_err);
}
}
* 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)
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) {
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;
}