From af34a9c2602f2c571db1bd09c2ca442c5d4d58e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexe=C3=AF=20KADIR?= Date: Tue, 20 Feb 2024 14:54:04 +0100 Subject: [PATCH] Added space reservation --- src/backing.c | 6 +- src/container.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++- src/container.h | 24 +++++++- src/disk.c | 3 +- src/sandbox.c | 3 + src/utils.c | 4 +- 6 files changed, 177 insertions(+), 7 deletions(-) diff --git a/src/backing.c b/src/backing.c index 400d2f3..160b332 100755 --- a/src/backing.c +++ b/src/backing.c @@ -177,12 +177,13 @@ result_t import_backing(char** _backing, const char* disk) { if (info.backing_path != NULL) { // Get the backing identifier of the parent + errno = 0; char* backing = strdup(basename(info.backing_path)); if (backing == NULL) { free_disk_info(&info); remove(temp_path); free(temp_path); - return failure("Failed to get the backing identifier of the parent."); + return failure("Failed to get the backing identifier of the parent of '%s' (%s).", disk, strerror(errno)); } // Check that the backing exists @@ -406,13 +407,14 @@ result_t get_backing_parent(char** _parent, const char* backing) { } // Get the backing identifier of the parent + errno = 0; char* parent = strdup(basename(info.backing_path)); // Free the disk info as it is not needed anymore free_disk_info(&info); if (parent == NULL) - return failure("Failed to get the backing identifier of the parent."); + return failure("Failed to get the backing identifier of the parent of '%s' (%s).", backing, strerror(errno)); *_parent = parent; return success(); diff --git a/src/container.c b/src/container.c index 5e00b44..4d156d6 100755 --- a/src/container.c +++ b/src/container.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include result_t check_container_identifier(const char* container) { // Check that the container identifier is not null @@ -271,14 +273,152 @@ result_t get_container_backing(char** _backing, const char* container) { } // Get the backing identifier + errno = 0; char* backing = strdup(basename(info.backing_path)); - + // Free the disk information as it is no longer needed free_disk_info(&info); if (backing == NULL) - return failure("Failed to get backing identifier for container '%s'.", container); + return failure("Failed to get backing identifier for container '%s' (%s).", container, strerror(errno)); *_backing = backing; return success(); } + +result_t get_container_info(disk_info_t* _info, const char* container) { + // Initialize the output parameters + _info->size = 0; + _info->allocated = 0; + _info->backing_path = NULL; + + // Check that the container exists + result_t result = check_container_exists(container); + if (result != success()) + return result; + + // Get the container path + char* path; + result = get_container_path(&path, container); + if (result != success()) + return result; + + // Get the disk information + result = get_disk_info(_info, path); + + free(path); + + return result; +} + +result_t get_oldest_container(char** _container) { + // Initialize the output parameters + *_container = NULL; + + // List the containers + char** containers; + result_t result = list_containers(&containers); + if (result != success()) + return result; + + // Find the oldest container + char* oldest_container = NULL; + time_t oldest_time = 0; + + for (size_t i = 0; containers[i] != NULL; i++) { + // Get the container path + char* path; + result = get_container_path(&path, containers[i]); + if (result != success()) + continue; + + // Get information about the container file + struct stat st; + errno = 0; + if (stat(path, &st) != 0) { + free(path); + continue; + } + + // Check if the container is older than the current oldest + if (oldest_container == NULL || st.st_mtime < oldest_time) { + oldest_container = containers[i]; + oldest_time = st.st_mtime; + } + } + + // Duplicate the oldest container + if (oldest_container != NULL) { + errno = 0; + *_container = strdup(oldest_container); + if (*_container == NULL) { + for (size_t i = 0; containers[i] != NULL; i++) + free(containers[i]); + free(containers); + return failure("Failed to allocate memory for the oldest container (%s).", strerror(errno)); + } + } + + // Free the containers + for (size_t i = 0; containers[i] != NULL; i++) + free(containers[i]); + free(containers); + + return success(); +} + +result_t get_container_pool_space(uint64_t* _space) { + // Initialize the output parameters + *_space = 0; + + // Get the container pool path + char* pool_path; + result_t result = get_container_pool_path(&pool_path); + if (result != success()) + return result; + + // Get the space of the container pool + struct statvfs st; + errno = 0; + if (statvfs(pool_path, &st) != 0) { + free(pool_path); + return failure("Failed to get space of container pool (%s).", strerror(errno)); + } + + *_space = st.f_bsize * st.f_bavail; + + free(pool_path); + return success(); +} + +result_t reserve_container_pool_space(uint64_t size) { + // As long as there is not enough space in the container pool, remove the oldest container + while (true) { + // Get the available space in the container pool + uint64_t space; + result_t result = get_container_pool_space(&space); + if (result != success()) + return result; + + // Check if there is enough space + if (space >= size) + return success(); + + // Get the oldest container + char* container; + result = get_oldest_container(&container); + if (result != success()) + return result; + + if (container == NULL) + return success(); // No more containers to remove + + // Remove the oldest container + result = remove_container(container); + + free(container); + + if (result != success()) + return result; + } +} diff --git a/src/container.h b/src/container.h index ee5e35b..24c9ecc 100755 --- a/src/container.h +++ b/src/container.h @@ -1,6 +1,7 @@ #pragma once #include "utils.h" +#include "disk.h" #define CONTAINER_IDENTIFIER_MAX_LENGTH 64 @@ -66,4 +67,25 @@ result_t list_containers(char*** _containers); /// @param _backing The string pointer to store the resulting backing in. /// @param container The container to get the backing of. /// @return The result of the operation. -result_t get_container_backing(char** _backing, const char* container); \ No newline at end of file +result_t get_container_backing(char** _backing, const char* container); + +/// @brief Gets information about the given container. If the container does not exist, the call will return a failure result with an error message. +/// @param _info The string pointer to store the resulting disk information in. The caller is responsible for freeing the string. +/// @param container The container to get information about. +/// @return The result of the operation. +result_t get_container_info(disk_info_t* _info, const char* container); + +/// @brief Gets the oldest container in the pool. +/// @param _container The string pointer to store the resulting container in. The caller is responsible for freeing the string. +/// @return The result of the operation. +result_t get_oldest_container(char** _container); + +/// @brief Gets the available space in the pool. +/// @param _space The string pointer to store the resulting space in, in bytes. The caller is responsible for freeing the string. +/// @return The result of the operation. +result_t get_container_pool_space(uint64_t* _space); + +/// @brief Reserves the given space in the pool. If the pool does not have enough space, the oldest containers will be removed to make space. +/// @param size The size to reserve, in bytes. +/// @return The result of the operation. +result_t reserve_container_pool_space(uint64_t size); \ No newline at end of file diff --git a/src/disk.c b/src/disk.c index 0bb0d11..ea8df80 100755 --- a/src/disk.c +++ b/src/disk.c @@ -273,10 +273,11 @@ result_t get_disk_info(disk_info_t* _info, const char* path) { } // Duplicate the backing path string + errno = 0; backing_path = strdup(backing_str); if (backing_path == NULL) { json_object_put(root); - return failure("Failed to allocate memory for the backing path."); + return failure("Failed to allocate memory for the backing path (%s).", strerror(errno)); } } diff --git a/src/sandbox.c b/src/sandbox.c index 582fe7f..a4d323b 100755 --- a/src/sandbox.c +++ b/src/sandbox.c @@ -67,6 +67,9 @@ int main(int argc, char** argv) { } // TODO: Parse commands from the command line + char* container; + get_oldest_container(&container); + printf("Oldest container: %s\n", container); } int command_help(int argc, char* argv[]) { diff --git a/src/utils.c b/src/utils.c index f4101b9..930c4f1 100755 --- a/src/utils.c +++ b/src/utils.c @@ -202,6 +202,7 @@ result_t execute(int* _exit_code, char** _stdoutbuf, char** _stderrbuf, const ch va_start(args, executable); for (int i = 1; i < argc; i++) { + errno = 0; argv[i] = strdup(va_arg(args, const char*)); if (argv[i] == NULL) { for (int j = 0; j < i; j++) @@ -511,13 +512,14 @@ result_t list_files(char*** _files, const char* path, bool (*filter)(const char* continue; // Add the entry to the files array + errno = 0; files[length] = strdup(entry->d_name); if (files[length] == NULL) { for (size_t i = 0; i < length; i++) free(files[i]); free(files); closedir(dir); - return failure("Failed to allocate memory for the file name."); + return failure("Failed to allocate memory for the file name (%s).", strerror(errno)); } length++;