Added space reservation
This commit is contained in:
parent
a260002a6c
commit
af34a9c260
@ -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();
|
||||
|
144
src/container.c
144
src/container.c
@ -9,6 +9,8 @@
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
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);
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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[]) {
|
||||
|
@ -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++;
|
||||
|
Loading…
Reference in New Issue
Block a user