From 839b6ddabcc55a69bda480ae39547a1dcb6cca7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexe=C3=AF=20KADIR?= Date: Wed, 21 Feb 2024 17:30:13 +0100 Subject: [PATCH] Added a function to convert multiple IOMMU groups into a single array --- src/pci.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++-- src/pci.h | 7 +++++ src/utils.c | 2 +- src/xml.c | 4 +-- 4 files changed, 88 insertions(+), 6 deletions(-) diff --git a/src/pci.c b/src/pci.c index b55cfe1..48a993d 100644 --- a/src/pci.c +++ b/src/pci.c @@ -80,11 +80,11 @@ result_t get_iommu_group(int* _group, const char* pci) { char iommu_group_path[256]; // 256 should be enough for the path ssize_t len = readlink(path, iommu_group_path, sizeof(iommu_group_path) - 1); + free(path); + // Check for errors during the readlink call - if (len == -1) { - free(path); + if (len == -1) return failure("Failed to read IOMMU group of PCI address '%s'.", pci); - } // Null-terminate the path iommu_group_path[len] = '\0'; @@ -165,3 +165,78 @@ result_t get_iommu_group_devices(char*** _devices, int group) { free(path); return result; } + +result_t get_iommu_groups_devices(char*** _devices, const int* groups, int groups_count) { + // Initialize the output parameters + *_devices = NULL; + + char*** devices = malloc(groups_count * sizeof(char**)); + if (devices == NULL) + return failure("Failed to allocate memory for IOMMU group devices."); + + // Get the devices of each IOMMU group + for (int i = 0; i < groups_count; i++) { + result_t result = get_iommu_group_devices(&devices[i], groups[i]); + if (result != success()) { + // Free every individual device + for (int j = 0; j < i; j++) { + char** group_devices = devices[j]; + for (int k = 0; group_devices[k] != NULL; k++) + free(group_devices[k]); + free(devices[j]); + } + + // Free the devices array + free(devices); + return result; + } + } + + // Count the number of devices + int count = 0; + for (int i = 0; i < groups_count; i++) { + char** group_devices = devices[i]; + for (int j = 0; group_devices[j] != NULL; j++) + count++; + } + + // Allocate memory for the output + char** output_devices = malloc((count + 1) * sizeof(char*)); + if (output_devices == NULL) { + // Free every individual device + for (int i = 0; i < groups_count; i++) { + char** group_devices = devices[i]; + for (int j = 0; group_devices[j] != NULL; j++) + free(group_devices[j]); + free(devices[i]); + } + + // Free the devices array + free(devices); + return failure("Failed to allocate memory for IOMMU group devices."); + } + + // Move the devices to the output + int index = 0; + for (int i = 0; i < groups_count; i++) { + char** group_devices = devices[i]; + for (int j = 0; group_devices[j] != NULL; j++) { + output_devices[index] = group_devices[j]; + group_devices[j] = NULL; + index++; + } + + // Free the group devices + free(group_devices); + } + + // Null-terminate the output + output_devices[count] = NULL; + + // Free the devices array + free(devices); + + *_devices = output_devices; + + return success(); +} diff --git a/src/pci.h b/src/pci.h index f3cc453..397ab7a 100644 --- a/src/pci.h +++ b/src/pci.h @@ -35,3 +35,10 @@ bool pci_filter(const char* file); /// @param group The IOMMU group to get the devices of. /// @return The result of the operation. result_t get_iommu_group_devices(char*** _devices, int group); + +/// @brief Get the PCI devices in the given IOMMU groups. +/// @param _devices The string array pointer to store the resulting devices in. The caller is responsible for freeing the strings and the array. +/// @param groups The IOMMU groups to get the devices of. +/// @param groups_count The number of IOMMU groups. +/// @return The result of the operation. +result_t get_iommu_groups_devices(char*** _devices, const int* groups, int groups_count); \ No newline at end of file diff --git a/src/utils.c b/src/utils.c index d73b190..072e682 100755 --- a/src/utils.c +++ b/src/utils.c @@ -244,7 +244,7 @@ result_t execute(int* _exit_code, char** _stdoutbuf, char** _stderrbuf, const ch // Allocate memory for the arguments array errno = 0; - char** argv = malloc((argc + 1) * sizeof(char*)); // +1 for the NULL terminator + char** argv = malloc((argc + 1) * sizeof(char*)); // +1 for the null terminator if (argv == NULL) return failure("Failed to allocate memory for the arguments array (%s).", strerror(errno)); diff --git a/src/xml.c b/src/xml.c index a7bb08e..c4727d9 100644 --- a/src/xml.c +++ b/src/xml.c @@ -46,7 +46,7 @@ result_t generate_container_xml(char** _xml, char* container, int cpu, uint64_t // Generate the XML result = format(_xml, "\n" - "%s\n" + "" LIBVIRT_DOMAIN "\n" "\n\n" "%llu\n" "%d\n" @@ -96,7 +96,7 @@ result_t generate_container_xml(char** _xml, char* container, int cpu, uint64_t "\n" "\n" "\n", - LIBVIRT_DOMAIN, memory, cpu, container_path, iso_xml, vnc_xml, pci_xml); + memory, cpu, container_path, iso_xml, vnc_xml, pci_xml); // Free the PCI, ISO, and VNC XML free(pci_xml);