commands-posix.c (b17d3b7b77f043f0e76f0e6ce6def3c1b1d5ee8b) commands-posix.c (54aa3de72ea2aaa2e903e7e879a4f3dda515a00e)
1/*
2 * QEMU Guest Agent POSIX-specific command implementations
3 *
4 * Copyright IBM Corp. 2011
5 *
6 * Authors:
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
8 * Michal Privoznik <mprivozn@redhat.com>

--- 1022 unchanged lines hidden (view full) ---

1031
1032/* Store disk device info specified by @sysfs into @fs */
1033static void build_guest_fsinfo_for_real_device(char const *syspath,
1034 GuestFilesystemInfo *fs,
1035 Error **errp)
1036{
1037 GuestDiskAddress *disk;
1038 GuestPCIAddress *pciaddr;
1/*
2 * QEMU Guest Agent POSIX-specific command implementations
3 *
4 * Copyright IBM Corp. 2011
5 *
6 * Authors:
7 * Michael Roth <mdroth@linux.vnet.ibm.com>
8 * Michal Privoznik <mprivozn@redhat.com>

--- 1022 unchanged lines hidden (view full) ---

1031
1032/* Store disk device info specified by @sysfs into @fs */
1033static void build_guest_fsinfo_for_real_device(char const *syspath,
1034 GuestFilesystemInfo *fs,
1035 Error **errp)
1036{
1037 GuestDiskAddress *disk;
1038 GuestPCIAddress *pciaddr;
1039 GuestDiskAddressList *list = NULL;
1040 bool has_hwinf;
1041#ifdef CONFIG_LIBUDEV
1042 struct udev *udev = NULL;
1043 struct udev_device *udevice = NULL;
1044#endif
1045
1046 pciaddr = g_new0(GuestPCIAddress, 1);
1047 pciaddr->domain = -1; /* -1 means field is invalid */
1048 pciaddr->bus = -1;
1049 pciaddr->slot = -1;
1050 pciaddr->function = -1;
1051
1052 disk = g_new0(GuestDiskAddress, 1);
1053 disk->pci_controller = pciaddr;
1054 disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN;
1055
1039 bool has_hwinf;
1040#ifdef CONFIG_LIBUDEV
1041 struct udev *udev = NULL;
1042 struct udev_device *udevice = NULL;
1043#endif
1044
1045 pciaddr = g_new0(GuestPCIAddress, 1);
1046 pciaddr->domain = -1; /* -1 means field is invalid */
1047 pciaddr->bus = -1;
1048 pciaddr->slot = -1;
1049 pciaddr->function = -1;
1050
1051 disk = g_new0(GuestDiskAddress, 1);
1052 disk->pci_controller = pciaddr;
1053 disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN;
1054
1056 list = g_new0(GuestDiskAddressList, 1);
1057 list->value = disk;
1058
1059#ifdef CONFIG_LIBUDEV
1060 udev = udev_new();
1061 udevice = udev_device_new_from_syspath(udev, syspath);
1062 if (udev == NULL || udevice == NULL) {
1063 g_debug("failed to query udev");
1064 } else {
1065 const char *devnode, *serial;
1066 devnode = udev_device_get_devnode(udevice);

--- 17 unchanged lines hidden (view full) ---

1084 } else if (strstr(syspath, "/virtio")) {
1085 has_hwinf = build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp);
1086 } else {
1087 g_debug("Unsupported device type for '%s'", syspath);
1088 has_hwinf = false;
1089 }
1090
1091 if (has_hwinf || disk->has_dev || disk->has_serial) {
1055#ifdef CONFIG_LIBUDEV
1056 udev = udev_new();
1057 udevice = udev_device_new_from_syspath(udev, syspath);
1058 if (udev == NULL || udevice == NULL) {
1059 g_debug("failed to query udev");
1060 } else {
1061 const char *devnode, *serial;
1062 devnode = udev_device_get_devnode(udevice);

--- 17 unchanged lines hidden (view full) ---

1080 } else if (strstr(syspath, "/virtio")) {
1081 has_hwinf = build_guest_fsinfo_for_nonpci_virtio(syspath, disk, errp);
1082 } else {
1083 g_debug("Unsupported device type for '%s'", syspath);
1084 has_hwinf = false;
1085 }
1086
1087 if (has_hwinf || disk->has_dev || disk->has_serial) {
1092 list->next = fs->disk;
1093 fs->disk = list;
1088 QAPI_LIST_PREPEND(fs->disk, disk);
1094 } else {
1089 } else {
1095 qapi_free_GuestDiskAddressList(list);
1090 qapi_free_GuestDiskAddress(disk);
1096 }
1097}
1098
1099static void build_guest_fsinfo_for_device(char const *devpath,
1100 GuestFilesystemInfo *fs,
1101 Error **errp);
1102
1103/* Store a list of slave devices of virtual volume specified by @syspath into

--- 179 unchanged lines hidden (view full) ---

1283 dp_deps = g_dir_open(deps_dir, 0, NULL);
1284 if (dp_deps == NULL) {
1285 g_debug("failed to list entries in %s", deps_dir);
1286 return;
1287 }
1288 disk->has_dependencies = true;
1289 while ((dep = g_dir_read_name(dp_deps)) != NULL) {
1290 g_autofree char *dep_dir = NULL;
1091 }
1092}
1093
1094static void build_guest_fsinfo_for_device(char const *devpath,
1095 GuestFilesystemInfo *fs,
1096 Error **errp);
1097
1098/* Store a list of slave devices of virtual volume specified by @syspath into

--- 179 unchanged lines hidden (view full) ---

1278 dp_deps = g_dir_open(deps_dir, 0, NULL);
1279 if (dp_deps == NULL) {
1280 g_debug("failed to list entries in %s", deps_dir);
1281 return;
1282 }
1283 disk->has_dependencies = true;
1284 while ((dep = g_dir_read_name(dp_deps)) != NULL) {
1285 g_autofree char *dep_dir = NULL;
1291 strList *dep_item = NULL;
1292 char *dev_name;
1293
1294 /* Add dependent disks */
1295 dep_dir = g_strdup_printf("%s/%s", deps_dir, dep);
1296 dev_name = get_device_for_syspath(dep_dir);
1297 if (dev_name != NULL) {
1298 g_debug(" adding dependent device: %s", dev_name);
1286 char *dev_name;
1287
1288 /* Add dependent disks */
1289 dep_dir = g_strdup_printf("%s/%s", deps_dir, dep);
1290 dev_name = get_device_for_syspath(dep_dir);
1291 if (dev_name != NULL) {
1292 g_debug(" adding dependent device: %s", dev_name);
1299 dep_item = g_new0(strList, 1);
1300 dep_item->value = dev_name;
1301 dep_item->next = disk->dependencies;
1302 disk->dependencies = dep_item;
1293 QAPI_LIST_PREPEND(disk->dependencies, dev_name);
1303 }
1304 }
1305 g_dir_close(dp_deps);
1306}
1307
1308/*
1309 * Detect partitions subdirectory, name is "<disk_name><number>" or
1310 * "<disk_name>p<number>"
1311 *
1312 * @disk_name -- last component of /sys path (e.g. sda)
1313 * @disk_dir -- sys path of the disk (e.g. /sys/block/sda)
1314 * @disk_dev -- device node of the disk (e.g. /dev/sda)
1315 */
1316static GuestDiskInfoList *get_disk_partitions(
1317 GuestDiskInfoList *list,
1318 const char *disk_name, const char *disk_dir,
1319 const char *disk_dev)
1320{
1294 }
1295 }
1296 g_dir_close(dp_deps);
1297}
1298
1299/*
1300 * Detect partitions subdirectory, name is "<disk_name><number>" or
1301 * "<disk_name>p<number>"
1302 *
1303 * @disk_name -- last component of /sys path (e.g. sda)
1304 * @disk_dir -- sys path of the disk (e.g. /sys/block/sda)
1305 * @disk_dev -- device node of the disk (e.g. /dev/sda)
1306 */
1307static GuestDiskInfoList *get_disk_partitions(
1308 GuestDiskInfoList *list,
1309 const char *disk_name, const char *disk_dir,
1310 const char *disk_dev)
1311{
1321 GuestDiskInfoList *item, *ret = list;
1312 GuestDiskInfoList *ret = list;
1322 struct dirent *de_disk;
1323 DIR *dp_disk = NULL;
1324 size_t len = strlen(disk_name);
1325
1326 dp_disk = opendir(disk_dir);
1327 while ((de_disk = readdir(dp_disk)) != NULL) {
1328 g_autofree char *partition_dir = NULL;
1329 char *dev_name;

--- 17 unchanged lines hidden (view full) ---

1347 g_debug("Failed to get device name for syspath: %s",
1348 disk_dir);
1349 continue;
1350 }
1351 partition = g_new0(GuestDiskInfo, 1);
1352 partition->name = dev_name;
1353 partition->partition = true;
1354 /* Add parent disk as dependent for easier tracking of hierarchy */
1313 struct dirent *de_disk;
1314 DIR *dp_disk = NULL;
1315 size_t len = strlen(disk_name);
1316
1317 dp_disk = opendir(disk_dir);
1318 while ((de_disk = readdir(dp_disk)) != NULL) {
1319 g_autofree char *partition_dir = NULL;
1320 char *dev_name;

--- 17 unchanged lines hidden (view full) ---

1338 g_debug("Failed to get device name for syspath: %s",
1339 disk_dir);
1340 continue;
1341 }
1342 partition = g_new0(GuestDiskInfo, 1);
1343 partition->name = dev_name;
1344 partition->partition = true;
1345 /* Add parent disk as dependent for easier tracking of hierarchy */
1355 partition->dependencies = g_new0(strList, 1);
1356 partition->dependencies->value = g_strdup(disk_dev);
1357 partition->has_dependencies = true;
1346 QAPI_LIST_PREPEND(partition->dependencies, g_strdup(disk_dev));
1358
1347
1359 item = g_new0(GuestDiskInfoList, 1);
1360 item->value = partition;
1361 item->next = ret;
1362 ret = item;
1363
1348 QAPI_LIST_PREPEND(ret, partition);
1364 }
1365 closedir(dp_disk);
1366
1367 return ret;
1368}
1369
1370GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
1371{
1349 }
1350 closedir(dp_disk);
1351
1352 return ret;
1353}
1354
1355GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
1356{
1372 GuestDiskInfoList *item, *ret = NULL;
1357 GuestDiskInfoList *ret = NULL;
1373 GuestDiskInfo *disk;
1374 DIR *dp = NULL;
1375 struct dirent *de = NULL;
1376
1377 g_debug("listing /sys/block directory");
1378 dp = opendir("/sys/block");
1379 if (dp == NULL) {
1380 error_setg_errno(errp, errno, "Can't open directory \"/sys/block\"");

--- 29 unchanged lines hidden (view full) ---

1410 disk_dir);
1411 continue;
1412 }
1413 disk = g_new0(GuestDiskInfo, 1);
1414 disk->name = dev_name;
1415 disk->partition = false;
1416 disk->alias = get_alias_for_syspath(disk_dir);
1417 disk->has_alias = (disk->alias != NULL);
1358 GuestDiskInfo *disk;
1359 DIR *dp = NULL;
1360 struct dirent *de = NULL;
1361
1362 g_debug("listing /sys/block directory");
1363 dp = opendir("/sys/block");
1364 if (dp == NULL) {
1365 error_setg_errno(errp, errno, "Can't open directory \"/sys/block\"");

--- 29 unchanged lines hidden (view full) ---

1395 disk_dir);
1396 continue;
1397 }
1398 disk = g_new0(GuestDiskInfo, 1);
1399 disk->name = dev_name;
1400 disk->partition = false;
1401 disk->alias = get_alias_for_syspath(disk_dir);
1402 disk->has_alias = (disk->alias != NULL);
1418 item = g_new0(GuestDiskInfoList, 1);
1419 item->value = disk;
1420 item->next = ret;
1421 ret = item;
1403 QAPI_LIST_PREPEND(ret, disk);
1422
1423 /* Get address for non-virtual devices */
1424 bool is_virtual = is_disk_virtual(disk_dir, &local_err);
1425 if (local_err != NULL) {
1426 g_debug(" failed to check disk path, ignoring error: %s",
1427 error_get_pretty(local_err));
1428 error_free(local_err);
1429 local_err = NULL;

--- 60 unchanged lines hidden (view full) ---

1490
1491 return fs;
1492}
1493
1494GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
1495{
1496 FsMountList mounts;
1497 struct FsMount *mount;
1404
1405 /* Get address for non-virtual devices */
1406 bool is_virtual = is_disk_virtual(disk_dir, &local_err);
1407 if (local_err != NULL) {
1408 g_debug(" failed to check disk path, ignoring error: %s",
1409 error_get_pretty(local_err));
1410 error_free(local_err);
1411 local_err = NULL;

--- 60 unchanged lines hidden (view full) ---

1472
1473 return fs;
1474}
1475
1476GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
1477{
1478 FsMountList mounts;
1479 struct FsMount *mount;
1498 GuestFilesystemInfoList *new, *ret = NULL;
1480 GuestFilesystemInfoList *ret = NULL;
1499 Error *local_err = NULL;
1500
1501 QTAILQ_INIT(&mounts);
1502 build_fs_mount_list(&mounts, &local_err);
1503 if (local_err) {
1504 error_propagate(errp, local_err);
1505 return NULL;
1506 }
1507
1508 QTAILQ_FOREACH(mount, &mounts, next) {
1509 g_debug("Building guest fsinfo for '%s'", mount->dirname);
1510
1481 Error *local_err = NULL;
1482
1483 QTAILQ_INIT(&mounts);
1484 build_fs_mount_list(&mounts, &local_err);
1485 if (local_err) {
1486 error_propagate(errp, local_err);
1487 return NULL;
1488 }
1489
1490 QTAILQ_FOREACH(mount, &mounts, next) {
1491 g_debug("Building guest fsinfo for '%s'", mount->dirname);
1492
1511 new = g_malloc0(sizeof(*ret));
1512 new->value = build_guest_fsinfo(mount, &local_err);
1513 new->next = ret;
1514 ret = new;
1493 QAPI_LIST_PREPEND(ret, build_guest_fsinfo(mount, &local_err));
1515 if (local_err) {
1516 error_propagate(errp, local_err);
1517 qapi_free_GuestFilesystemInfoList(ret);
1518 ret = NULL;
1519 break;
1520 }
1521 }
1522

--- 249 unchanged lines hidden (view full) ---

1772#if defined(CONFIG_FSTRIM)
1773/*
1774 * Walk list of mounted file systems in the guest, and trim them.
1775 */
1776GuestFilesystemTrimResponse *
1777qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
1778{
1779 GuestFilesystemTrimResponse *response;
1494 if (local_err) {
1495 error_propagate(errp, local_err);
1496 qapi_free_GuestFilesystemInfoList(ret);
1497 ret = NULL;
1498 break;
1499 }
1500 }
1501

--- 249 unchanged lines hidden (view full) ---

1751#if defined(CONFIG_FSTRIM)
1752/*
1753 * Walk list of mounted file systems in the guest, and trim them.
1754 */
1755GuestFilesystemTrimResponse *
1756qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
1757{
1758 GuestFilesystemTrimResponse *response;
1780 GuestFilesystemTrimResultList *list;
1781 GuestFilesystemTrimResult *result;
1782 int ret = 0;
1783 FsMountList mounts;
1784 struct FsMount *mount;
1785 int fd;
1786 Error *local_err = NULL;
1787 struct fstrim_range r;
1788

--- 7 unchanged lines hidden (view full) ---

1796 }
1797
1798 response = g_malloc0(sizeof(*response));
1799
1800 QTAILQ_FOREACH(mount, &mounts, next) {
1801 result = g_malloc0(sizeof(*result));
1802 result->path = g_strdup(mount->dirname);
1803
1759 GuestFilesystemTrimResult *result;
1760 int ret = 0;
1761 FsMountList mounts;
1762 struct FsMount *mount;
1763 int fd;
1764 Error *local_err = NULL;
1765 struct fstrim_range r;
1766

--- 7 unchanged lines hidden (view full) ---

1774 }
1775
1776 response = g_malloc0(sizeof(*response));
1777
1778 QTAILQ_FOREACH(mount, &mounts, next) {
1779 result = g_malloc0(sizeof(*result));
1780 result->path = g_strdup(mount->dirname);
1781
1804 list = g_malloc0(sizeof(*list));
1805 list->value = result;
1806 list->next = response->paths;
1807 response->paths = list;
1782 QAPI_LIST_PREPEND(response->paths, result);
1808
1809 fd = qemu_open_old(mount->dirname, O_RDONLY);
1810 if (fd == -1) {
1811 result->error = g_strdup_printf("failed to open: %s",
1812 strerror(errno));
1813 result->has_error = true;
1814 continue;
1815 }

--- 1530 unchanged lines hidden ---
1783
1784 fd = qemu_open_old(mount->dirname, O_RDONLY);
1785 if (fd == -1) {
1786 result->error = g_strdup_printf("failed to open: %s",
1787 strerror(errno));
1788 result->has_error = true;
1789 continue;
1790 }

--- 1530 unchanged lines hidden ---