From b850194eaa373cf1d9ad89d522ea4109a57a3c67 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Wed, 4 Jun 2025 12:03:23 +0200 Subject: [PATCH 01/13] Began working on adding DIR futures Added patches to dirent.h defined functions --- src/posix/handlers.hpp | 11 +++ src/posix/handlers/posix_readdir.hpp | 115 +++++++++++++++++++++++++++ src/posix/libcapio_posix.cpp | 2 + 3 files changed, 128 insertions(+) create mode 100644 src/posix/handlers/posix_readdir.hpp diff --git a/src/posix/handlers.hpp b/src/posix/handlers.hpp index 653620fa0..15054589e 100644 --- a/src/posix/handlers.hpp +++ b/src/posix/handlers.hpp @@ -1,6 +1,10 @@ #ifndef CAPIO_POSIX_HANDLERS_HPP #define CAPIO_POSIX_HANDLERS_HPP +/********************/ +// SYSCALL HANDLERS // +/********************/ + #include "handlers/access.hpp" #include "handlers/chdir.hpp" #include "handlers/close.hpp" @@ -26,4 +30,11 @@ #include "handlers/unlink.hpp" #include "handlers/write.hpp" + +/********************/ +// POSIX HANDLERS // +/********************/ + +#include "handlers/posix_readdir.hpp" + #endif // CAPIO_POSIX_HANDLERS_HPP diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp new file mode 100644 index 000000000..4a2290a6b --- /dev/null +++ b/src/posix/handlers/posix_readdir.hpp @@ -0,0 +1,115 @@ +#ifndef POSIX_READDIR_HPP +#define POSIX_READDIR_HPP + +#include +#include +#include +#include +#include + +// Map &DIR -> dirpath +std::unordered_map opened_directory; + +DIR *opendir(const char *name) { + char realpath[PATH_MAX]{0}; + capio_realpath(name, realpath); + START_LOG(gettid(), "call(path=%s)", realpath); + + static DIR *(*real_opendir)(const char *) = NULL; + + if (!real_opendir) { + syscall_no_intercept_flag = true; + real_opendir = (DIR * (*) (const char *) ) dlsym(RTLD_NEXT, "opendir"); + syscall_no_intercept_flag = false; + if (!real_opendir) { + ERR_EXIT("Failed to find original opendir: %s\n", dlerror()); + } + } + + if (!is_capio_path(realpath)) { + LOG("Not a CAPIO path. continuing execution"); + auto dir = real_opendir(realpath); + + return dir; + } + + LOG("Performing consent request to open directory %s", realpath); + consent_request_cache_fs->consent_request(realpath, gettid(), __FUNCTION__); + + syscall_no_intercept_flag = true; + auto dir = real_opendir(realpath); + syscall_no_intercept_flag = false; + + LOG("Opened directory with offset %ld", dir); + opened_directory.insert({reinterpret_cast(dir), std::string(realpath)}); + + return dir; +} + +int closedir(DIR *dirp) { + START_LOG(capio_syscall(SYS_gettid), "call(dir=%ld)", dirp); + + static int (*real_closedir)(DIR *) = NULL; + if (!real_closedir) { + syscall_no_intercept_flag = true; + real_closedir = (int (*)(DIR *)) dlsym(RTLD_NEXT, "closedir"); + syscall_no_intercept_flag = false; + if (!real_closedir) { + ERR_EXIT("Failed to find original closedir: %s\n", dlerror()); + } + } + + if (const auto pos = opened_directory.find(reinterpret_cast(dirp)); + pos != opened_directory.end()) { + opened_directory.erase(pos); + LOG("removed dir from map of opened files"); + } + syscall_no_intercept_flag = true; + auto return_code = real_closedir(dirp); + syscall_no_intercept_flag = false; + LOG("Return code of closedir = %d", return_code); + + return return_code; +} + +struct dirent *readdir(DIR *dirp) { + syscall_no_intercept_flag = true; + static struct dirent *(*real_readdir)(DIR *) = NULL; + if (!real_readdir) { + real_readdir = (struct dirent * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir"); + } + + struct dirent *entry; + while ((entry = real_readdir(dirp)) != NULL) { + // Example: skip hidden files + if (entry->d_name[0] == '.') { + continue; + } + printf("[HOOK] readdir: %s\n", entry->d_name); + return entry; + } + syscall_no_intercept_flag = false; + + return NULL; // end of directory +} + +struct dirent64 *readdir64(DIR *dirp) { + syscall_no_intercept_flag = true; + static struct dirent64 *(*real_readdir64)(DIR *) = NULL; + if (!real_readdir64) { + real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); + } + + struct dirent64 *entry; + while ((entry = real_readdir64(dirp)) != NULL) { + if (entry->d_name[0] == '.') { + continue; + } + printf("[HOOK] readdir64: %s\n", entry->d_name); + return entry; + } + syscall_no_intercept_flag = false; + return NULL; +} + +#endif // POSIX_READDIR_HPP diff --git a/src/posix/libcapio_posix.cpp b/src/posix/libcapio_posix.cpp index 93dc776eb..06d943b87 100644 --- a/src/posix/libcapio_posix.cpp +++ b/src/posix/libcapio_posix.cpp @@ -366,6 +366,8 @@ static constexpr std::array build_syscall_table( return _syscallTable; } + + static int hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long *result) { static constexpr std::array syscallTable = From b0d2f2ec46477fa611bc4c5dabd00f5f3a58302d Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Wed, 4 Jun 2025 16:25:20 +0200 Subject: [PATCH 02/13] continued work on directory --- src/posix/handlers/posix_readdir.hpp | 144 ++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 24 deletions(-) diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 4a2290a6b..77a4b75d3 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -7,8 +7,74 @@ #include #include -// Map &DIR -> dirpath -std::unordered_map opened_directory; +// Map &DIR -> +std::unordered_map> opened_directory; + +std::unordered_map *> *directory_items; + +int count_files_in_directory(const char *path) { + static struct dirent64 *(*real_readdir64)(DIR *) = NULL; + static DIR *(*real_opendir)(const char *) = NULL; + static int (*real_closedir)(DIR *) = NULL; + + START_LOG(capio_syscall(SYS_gettid), "call()"); + syscall_no_intercept_flag = true; + if (!real_readdir64) { + real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); + } + + if (!real_opendir) { + real_opendir = (DIR * (*) (const char *) ) dlsym(RTLD_NEXT, "opendir"); + } + + if (!real_closedir) { + + real_closedir = (int (*)(DIR *)) dlsym(RTLD_NEXT, "closedir"); + } + + struct dirent64 *entry; + DIR *dir = real_opendir(path); + int count = 0; + + while ((entry = real_readdir64(dir)) != NULL) { + + auto entry_realpath = (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + ? entry->d_name + : capio_absolute(entry->d_name); + + if (auto directory_object = directory_items->find(entry_realpath); + directory_object == directory_items->end()) { + LOG("Directory vector not present"); + directory_items->emplace(entry_realpath, new std::vector()); + } + + auto directory_object = directory_items->at(entry_realpath); + + auto itm = std::find_if(directory_object->begin(), directory_object->end(), + [&](const dirent64 *_scope_entry) { + return std::string(entry_realpath) == _scope_entry->d_name; + }); + + if (itm == directory_object->end()) { + LOG("Item %s is not stored within internal capio data structure. adding it", + entry_realpath.c_str()); + dirent64 *new_entry = new dirent64(); + memcpy(new_entry->d_name, entry->d_name, sizeof(entry->d_name)); + new_entry->d_ino = entry->d_ino; + new_entry->d_off = entry->d_off; + new_entry->d_reclen = entry->d_reclen; + new_entry->d_type = entry->d_type; + directory_object->emplace_back(new_entry); + } + count++; + } + + LOG("Found %ld items.", count); + + real_closedir(dir); + syscall_no_intercept_flag = false; + return count; +} DIR *opendir(const char *name) { char realpath[PATH_MAX]{0}; @@ -26,6 +92,10 @@ DIR *opendir(const char *name) { } } + if (directory_items == nullptr) { + directory_items = new std::unordered_map *>(); + } + if (!is_capio_path(realpath)) { LOG("Not a CAPIO path. continuing execution"); auto dir = real_opendir(realpath); @@ -41,7 +111,8 @@ DIR *opendir(const char *name) { syscall_no_intercept_flag = false; LOG("Opened directory with offset %ld", dir); - opened_directory.insert({reinterpret_cast(dir), std::string(realpath)}); + opened_directory.insert({reinterpret_cast(dir), {std::string(realpath), 0}}); + directory_items->emplace(std::string(realpath), new std::vector()); return dir; } @@ -61,6 +132,10 @@ int closedir(DIR *dirp) { if (const auto pos = opened_directory.find(reinterpret_cast(dirp)); pos != opened_directory.end()) { + + if (auto pos1 = directory_items->find(pos->second.first); pos1 != directory_items->end()) { + directory_items->erase(pos1); + } opened_directory.erase(pos); LOG("removed dir from map of opened files"); } @@ -73,43 +148,64 @@ int closedir(DIR *dirp) { } struct dirent *readdir(DIR *dirp) { - syscall_no_intercept_flag = true; + START_LOG(capio_syscall(SYS_gettid), "call(dir=%ld)", dirp); + static struct dirent *(*real_readdir)(DIR *) = NULL; if (!real_readdir) { - real_readdir = (struct dirent * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir"); + LOG("Loading real glibc method"); + syscall_no_intercept_flag = true; + real_readdir = (struct dirent * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir"); + syscall_no_intercept_flag = false; } - struct dirent *entry; - while ((entry = real_readdir(dirp)) != NULL) { - // Example: skip hidden files - if (entry->d_name[0] == '.') { - continue; + auto item = opened_directory.find((unsigned long int) dirp); + if (item != opened_directory.end()) { + LOG("Found dirp."); + auto dir_path_name = std::get<0>(item->second); + auto capio_internal_offset = std::get<1>(item->second); + + while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { + LOG("Not enough files... waiting"); + sleep(1); } - printf("[HOOK] readdir: %s\n", entry->d_name); - return entry; + + std::get<1>(item->second)++; } - syscall_no_intercept_flag = false; - return NULL; // end of directory + return real_readdir(dirp); } struct dirent64 *readdir64(DIR *dirp) { - syscall_no_intercept_flag = true; + + START_LOG(capio_syscall(SYS_gettid), "call(dir=%ld)", dirp); + static struct dirent64 *(*real_readdir64)(DIR *) = NULL; if (!real_readdir64) { - real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); + LOG("Loading real glibc method"); + syscall_no_intercept_flag = true; + real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); + syscall_no_intercept_flag = false; } - struct dirent64 *entry; - while ((entry = real_readdir64(dirp)) != NULL) { - if (entry->d_name[0] == '.') { - continue; + auto item = opened_directory.find((unsigned long int) dirp); + if (item != opened_directory.end()) { + LOG("Found dirp."); + auto dir_path_name = std::get<0>(item->second); + auto capio_internal_offset = std::get<1>(item->second); + + while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { + LOG("Not enough files... waiting"); + syscall_no_intercept_flag = true; + sleep(1); + syscall_no_intercept_flag = false; } - printf("[HOOK] readdir64: %s\n", entry->d_name); - return entry; + + std::get<1>(item->second)++; + + return directory_items->at(dir_path_name.c_str())->at(std::get<1>(item->second)); } - syscall_no_intercept_flag = false; - return NULL; + + return real_readdir64(dirp); } #endif // POSIX_READDIR_HPP From e8b9e5b4a518fd49d3187ace6b974217b7d5a285 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Wed, 4 Jun 2025 17:23:01 +0200 Subject: [PATCH 03/13] Fixed readdir. add commit return Now readdir works. I need to return NULL as soon as the directory is committed. Ask for committmenet on directory from capio server --- src/posix/handlers/posix_readdir.hpp | 40 ++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 77a4b75d3..cab8ba198 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -8,9 +8,9 @@ #include // Map &DIR -> -std::unordered_map> opened_directory; +inline std::unordered_map> opened_directory; -std::unordered_map *> *directory_items; +inline std::unordered_map *> *directory_items; int count_files_in_directory(const char *path) { static struct dirent64 *(*real_readdir64)(DIR *) = NULL; @@ -41,18 +41,20 @@ int count_files_in_directory(const char *path) { auto entry_realpath = (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) ? entry->d_name : capio_absolute(entry->d_name); + char realp_dir_path[PATH_MAX]; + capio_realpath(path, realp_dir_path); if (auto directory_object = directory_items->find(entry_realpath); directory_object == directory_items->end()) { - LOG("Directory vector not present"); - directory_items->emplace(entry_realpath, new std::vector()); + LOG("Directory vector not present. Adding it at path %s", realp_dir_path); + directory_items->emplace(realp_dir_path, new std::vector()); } - auto directory_object = directory_items->at(entry_realpath); + auto directory_object = directory_items->at(realp_dir_path); auto itm = std::find_if(directory_object->begin(), directory_object->end(), [&](const dirent64 *_scope_entry) { - return std::string(entry_realpath) == _scope_entry->d_name; + return std::string(entry->d_name) == _scope_entry->d_name; }); if (itm == directory_object->end()) { @@ -166,17 +168,27 @@ struct dirent *readdir(DIR *dirp) { while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { LOG("Not enough files... waiting"); + syscall_no_intercept_flag = true; sleep(1); + syscall_no_intercept_flag = false; } + LOG("Returning item %d", std::get<1>(item->second)); + + char real_path[PATH_MAX]; + capio_realpath(dir_path_name.c_str(), real_path); + + LOG("Getting files inside directory %s", real_path); + + auto return_value = + (dirent *) directory_items->at(real_path)->at(std::get<1>(item->second)); std::get<1>(item->second)++; + return return_value; } - return real_readdir(dirp); } struct dirent64 *readdir64(DIR *dirp) { - START_LOG(capio_syscall(SYS_gettid), "call(dir=%ld)", dirp); static struct dirent64 *(*real_readdir64)(DIR *) = NULL; @@ -200,11 +212,17 @@ struct dirent64 *readdir64(DIR *dirp) { syscall_no_intercept_flag = false; } - std::get<1>(item->second)++; + LOG("Returning item %d", std::get<1>(item->second)); - return directory_items->at(dir_path_name.c_str())->at(std::get<1>(item->second)); - } + char real_path[PATH_MAX]; + capio_realpath(dir_path_name.c_str(), real_path); + LOG("Getting files inside directory %s", real_path); + + auto return_value = directory_items->at(real_path)->at(std::get<1>(item->second)); + std::get<1>(item->second)++; + return return_value; + } return real_readdir64(dirp); } From be98f15ee46d6dbbc02e885666466932755b22b6 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Wed, 4 Jun 2025 19:48:02 +0000 Subject: [PATCH 04/13] code cleanup --- src/posix/handlers/posix_readdir.hpp | 53 +++++++++++++--------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index cab8ba198..9225e800f 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -8,36 +8,34 @@ #include // Map &DIR -> -inline std::unordered_map> opened_directory; +inline std::unordered_map > opened_directory; inline std::unordered_map *> *directory_items; -int count_files_in_directory(const char *path) { +inline int count_files_in_directory(const char *path) { static struct dirent64 *(*real_readdir64)(DIR *) = NULL; - static DIR *(*real_opendir)(const char *) = NULL; - static int (*real_closedir)(DIR *) = NULL; + static DIR *(*real_opendir)(const char *) = NULL; + static int (*real_closedir)(DIR *) = NULL; START_LOG(capio_syscall(SYS_gettid), "call()"); syscall_no_intercept_flag = true; if (!real_readdir64) { - real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); + real_readdir64 = (struct dirent64 * (*)(DIR *)) dlsym(RTLD_NEXT, "readdir64"); } if (!real_opendir) { - real_opendir = (DIR * (*) (const char *) ) dlsym(RTLD_NEXT, "opendir"); + real_opendir = (DIR * (*)(const char *)) dlsym(RTLD_NEXT, "opendir"); } if (!real_closedir) { - real_closedir = (int (*)(DIR *)) dlsym(RTLD_NEXT, "closedir"); } struct dirent64 *entry; - DIR *dir = real_opendir(path); + DIR *dir = real_opendir(path); int count = 0; while ((entry = real_readdir64(dir)) != NULL) { - auto entry_realpath = (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) ? entry->d_name : capio_absolute(entry->d_name); @@ -60,12 +58,12 @@ int count_files_in_directory(const char *path) { if (itm == directory_object->end()) { LOG("Item %s is not stored within internal capio data structure. adding it", entry_realpath.c_str()); - dirent64 *new_entry = new dirent64(); + auto *new_entry = new dirent64(); memcpy(new_entry->d_name, entry->d_name, sizeof(entry->d_name)); - new_entry->d_ino = entry->d_ino; - new_entry->d_off = entry->d_off; + new_entry->d_ino = entry->d_ino; + new_entry->d_off = entry->d_off; new_entry->d_reclen = entry->d_reclen; - new_entry->d_type = entry->d_type; + new_entry->d_type = entry->d_type; directory_object->emplace_back(new_entry); } count++; @@ -87,7 +85,7 @@ DIR *opendir(const char *name) { if (!real_opendir) { syscall_no_intercept_flag = true; - real_opendir = (DIR * (*) (const char *) ) dlsym(RTLD_NEXT, "opendir"); + real_opendir = (DIR * (*)(const char *)) dlsym(RTLD_NEXT, "opendir"); syscall_no_intercept_flag = false; if (!real_opendir) { ERR_EXIT("Failed to find original opendir: %s\n", dlerror()); @@ -109,7 +107,7 @@ DIR *opendir(const char *name) { consent_request_cache_fs->consent_request(realpath, gettid(), __FUNCTION__); syscall_no_intercept_flag = true; - auto dir = real_opendir(realpath); + auto dir = real_opendir(realpath); syscall_no_intercept_flag = false; LOG("Opened directory with offset %ld", dir); @@ -125,7 +123,7 @@ int closedir(DIR *dirp) { static int (*real_closedir)(DIR *) = NULL; if (!real_closedir) { syscall_no_intercept_flag = true; - real_closedir = (int (*)(DIR *)) dlsym(RTLD_NEXT, "closedir"); + real_closedir = (int (*)(DIR *)) dlsym(RTLD_NEXT, "closedir"); syscall_no_intercept_flag = false; if (!real_closedir) { ERR_EXIT("Failed to find original closedir: %s\n", dlerror()); @@ -134,7 +132,6 @@ int closedir(DIR *dirp) { if (const auto pos = opened_directory.find(reinterpret_cast(dirp)); pos != opened_directory.end()) { - if (auto pos1 = directory_items->find(pos->second.first); pos1 != directory_items->end()) { directory_items->erase(pos1); } @@ -142,7 +139,7 @@ int closedir(DIR *dirp) { LOG("removed dir from map of opened files"); } syscall_no_intercept_flag = true; - auto return_code = real_closedir(dirp); + auto return_code = real_closedir(dirp); syscall_no_intercept_flag = false; LOG("Return code of closedir = %d", return_code); @@ -156,14 +153,13 @@ struct dirent *readdir(DIR *dirp) { if (!real_readdir) { LOG("Loading real glibc method"); syscall_no_intercept_flag = true; - real_readdir = (struct dirent * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir"); + real_readdir = (struct dirent * (*)(DIR *)) dlsym(RTLD_NEXT, "readdir"); syscall_no_intercept_flag = false; } - auto item = opened_directory.find((unsigned long int) dirp); - if (item != opened_directory.end()) { + if (auto item = opened_directory.find((unsigned long int) dirp); item != opened_directory.end()) { LOG("Found dirp."); - auto dir_path_name = std::get<0>(item->second); + auto dir_path_name = std::get<0>(item->second); auto capio_internal_offset = std::get<1>(item->second); while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { @@ -180,8 +176,8 @@ struct dirent *readdir(DIR *dirp) { LOG("Getting files inside directory %s", real_path); - auto return_value = - (dirent *) directory_items->at(real_path)->at(std::get<1>(item->second)); + const auto return_value = + reinterpret_cast(directory_items->at(real_path)->at(std::get<1>(item->second))); std::get<1>(item->second)++; return return_value; } @@ -195,14 +191,13 @@ struct dirent64 *readdir64(DIR *dirp) { if (!real_readdir64) { LOG("Loading real glibc method"); syscall_no_intercept_flag = true; - real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); + real_readdir64 = (struct dirent64 * (*)(DIR *)) dlsym(RTLD_NEXT, "readdir64"); syscall_no_intercept_flag = false; } - auto item = opened_directory.find((unsigned long int) dirp); - if (item != opened_directory.end()) { + if (auto item = opened_directory.find((unsigned long int) dirp); item != opened_directory.end()) { LOG("Found dirp."); - auto dir_path_name = std::get<0>(item->second); + auto dir_path_name = std::get<0>(item->second); auto capio_internal_offset = std::get<1>(item->second); while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { @@ -219,7 +214,7 @@ struct dirent64 *readdir64(DIR *dirp) { LOG("Getting files inside directory %s", real_path); - auto return_value = directory_items->at(real_path)->at(std::get<1>(item->second)); + const auto return_value = directory_items->at(real_path)->at(std::get<1>(item->second)); std::get<1>(item->second)++; return return_value; } From 85e286dd47eb539471fce22508fa12940fc0a01b Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Thu, 5 Jun 2025 18:34:13 +0000 Subject: [PATCH 05/13] Added posix side dir committed request --- src/common/capio/requests.hpp | 25 +++++++++++++------------ src/posix/handlers/posix_readdir.hpp | 21 +++++++++++++++++---- src/posix/utils/requests.hpp | 18 +++++++++++++++--- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/src/common/capio/requests.hpp b/src/common/capio/requests.hpp index 5e4b68863..5a52b9ecc 100644 --- a/src/common/capio/requests.hpp +++ b/src/common/capio/requests.hpp @@ -1,19 +1,20 @@ #ifndef CAPIO_COMMON_REQUESTS_HPP #define CAPIO_COMMON_REQUESTS_HPP -constexpr const int CAPIO_REQUEST_CONSENT = 0; -constexpr const int CAPIO_REQUEST_CLOSE = 1; -constexpr const int CAPIO_REQUEST_CREATE = 2; -constexpr const int CAPIO_REQUEST_EXIT_GROUP = 3; -constexpr const int CAPIO_REQUEST_HANDSHAKE = 4; -constexpr const int CAPIO_REQUEST_MKDIR = 5; -constexpr const int CAPIO_REQUEST_OPEN = 6; -constexpr const int CAPIO_REQUEST_READ = 7; -constexpr const int CAPIO_REQUEST_READ_MEM = 8; -constexpr const int CAPIO_REQUEST_RENAME = 9; -constexpr const int CAPIO_REQUEST_WRITE = 10; -constexpr const int CAPIO_REQUEST_WRITE_MEM = 11; +constexpr const int CAPIO_REQUEST_CONSENT = 0; +constexpr const int CAPIO_REQUEST_CLOSE = 1; +constexpr const int CAPIO_REQUEST_CREATE = 2; +constexpr const int CAPIO_REQUEST_EXIT_GROUP = 3; +constexpr const int CAPIO_REQUEST_HANDSHAKE = 4; +constexpr const int CAPIO_REQUEST_MKDIR = 5; +constexpr const int CAPIO_REQUEST_OPEN = 6; +constexpr const int CAPIO_REQUEST_READ = 7; +constexpr const int CAPIO_REQUEST_READ_MEM = 8; +constexpr const int CAPIO_REQUEST_RENAME = 9; +constexpr const int CAPIO_REQUEST_WRITE = 10; +constexpr const int CAPIO_REQUEST_WRITE_MEM = 11; constexpr const int CAPIO_REQUEST_QUERY_MEM_FILE = 12; +constexpr const int CAPIO_REQUEST_POSIX_DIR_COMMITTED = 13; constexpr const int CAPIO_NR_REQUESTS = 13; diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 9225e800f..2733fff93 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -6,6 +6,7 @@ #include #include #include +#include // Map &DIR -> inline std::unordered_map > opened_directory; @@ -157,13 +158,23 @@ struct dirent *readdir(DIR *dirp) { syscall_no_intercept_flag = false; } - if (auto item = opened_directory.find((unsigned long int) dirp); item != opened_directory.end()) { + const bool dir_committed = posix_directory_committed( + capio_syscall(SYS_gettid), + std::get<0>(opened_directory.at(reinterpret_cast(dirp)))); + + if (const auto item = opened_directory.find(reinterpret_cast(dirp)); + item != opened_directory.end() || dir_committed) { LOG("Found dirp."); - auto dir_path_name = std::get<0>(item->second); - auto capio_internal_offset = std::get<1>(item->second); + const auto dir_path_name = std::get<0>(item->second); + const auto capio_internal_offset = std::get<1>(item->second); while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { LOG("Not enough files... waiting"); + if (posix_directory_committed( + capio_syscall(SYS_gettid), + std::get<0>(opened_directory.at(reinterpret_cast(dirp))))) { + return real_readdir(dirp); + } syscall_no_intercept_flag = true; sleep(1); syscall_no_intercept_flag = false; @@ -184,6 +195,7 @@ struct dirent *readdir(DIR *dirp) { return real_readdir(dirp); } +/* struct dirent64 *readdir64(DIR *dirp) { START_LOG(capio_syscall(SYS_gettid), "call(dir=%ld)", dirp); @@ -195,7 +207,7 @@ struct dirent64 *readdir64(DIR *dirp) { syscall_no_intercept_flag = false; } - if (auto item = opened_directory.find((unsigned long int) dirp); item != opened_directory.end()) { + if (auto item = opened_directory.find(reinterpret_cast(dirp)); item != opened_directory.end()) { LOG("Found dirp."); auto dir_path_name = std::get<0>(item->second); auto capio_internal_offset = std::get<1>(item->second); @@ -220,5 +232,6 @@ struct dirent64 *readdir64(DIR *dirp) { } return real_readdir64(dirp); } +*/ #endif // POSIX_READDIR_HPP diff --git a/src/posix/utils/requests.hpp b/src/posix/utils/requests.hpp index e32858515..12174b79c 100644 --- a/src/posix/utils/requests.hpp +++ b/src/posix/utils/requests.hpp @@ -26,9 +26,8 @@ inline thread_local SPSCQueue *stc_queue; * @return */ inline void init_client() { - buf_requests = - new CircularBuffer(SHM_COMM_CHAN_NAME, CAPIO_REQ_BUFF_CNT, CAPIO_REQ_MAX_SIZE); + new CircularBuffer(SHM_COMM_CHAN_NAME, CAPIO_REQ_BUFF_CNT, CAPIO_REQ_MAX_SIZE); bufs_response = new std::unordered_map(); } @@ -75,6 +74,19 @@ inline std::vector *file_in_memory_request(const long pid) { return regex_vector; } +inline bool posix_directory_committed(const long pid, const std::filesystem::path &path) { + START_LOG(capio_syscall(SYS_gettid), "call(path=%s)", path.c_str()); + char req[CAPIO_REQ_MAX_SIZE]; + + sprintf(req, "%04d %s ", CAPIO_REQUEST_POSIX_DIR_COMMITTED, path.c_str()); + buf_requests->write(req, CAPIO_REQ_MAX_SIZE); + LOG("Sent query for directory committement"); + capio_off64_t committed = bufs_response->at(pid)->read(); + LOG("Directory %s is %s", path.c_str(), committed ? "committed" : "not yet committed"); + + return committed == 1; +} + // non blocking inline void close_request(const std::filesystem::path &path, const long tid) { START_LOG(capio_syscall(SYS_gettid), "call(path=%s, tid=%ld)", path.c_str(), tid); @@ -125,4 +137,4 @@ inline void rename_request(const std::filesystem::path &old_path, #include "utils/storage.hpp" -#endif // CAPIO_POSIX_UTILS_REQUESTS_HPP \ No newline at end of file +#endif // CAPIO_POSIX_UTILS_REQUESTS_HPP From 664c6b81bb2121793eea2c4ae9de6fdf6abccf27 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Fri, 6 Jun 2025 10:37:01 +0200 Subject: [PATCH 06/13] Added checks on committement of file... This commit changes the behaviour of posix component and server component of listdir. When called, it no longer directly asks if a file is committed, but asks for the commit token path. It then caches it, and periodically checks if said token exists. as soon as it does, it returns NULL, as specified by the POSIX semantic for listdir||() --- src/common/capio/requests.hpp | 2 +- src/posix/handlers/posix_readdir.hpp | 67 ++++++++++--------- src/posix/utils/requests.hpp | 15 +++-- .../capio-cl-engine/capio_cl_engine.hpp | 7 ++ .../client-manager/handlers/posix_readdir.hpp | 18 +++++ .../client-manager/request_handler_engine.hpp | 34 ++++++---- src/server/file-manager/file_manager.hpp | 2 + src/server/file-manager/file_manager_impl.hpp | 39 ++++++++++- src/server/file-manager/fs_monitor.hpp | 1 + .../storage-service/capio_storage_service.hpp | 10 +++ 10 files changed, 141 insertions(+), 54 deletions(-) create mode 100644 src/server/client-manager/handlers/posix_readdir.hpp diff --git a/src/common/capio/requests.hpp b/src/common/capio/requests.hpp index 5a52b9ecc..63e253739 100644 --- a/src/common/capio/requests.hpp +++ b/src/common/capio/requests.hpp @@ -16,6 +16,6 @@ constexpr const int CAPIO_REQUEST_WRITE_MEM = 11; constexpr const int CAPIO_REQUEST_QUERY_MEM_FILE = 12; constexpr const int CAPIO_REQUEST_POSIX_DIR_COMMITTED = 13; -constexpr const int CAPIO_NR_REQUESTS = 13; +constexpr const int CAPIO_NR_REQUESTS = 14; #endif // CAPIO_COMMON_REQUESTS_HPP diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 2733fff93..40264d5db 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -9,23 +9,25 @@ #include // Map &DIR -> -inline std::unordered_map > opened_directory; +inline std::unordered_map> opened_directory; inline std::unordered_map *> *directory_items; +inline std::unordered_map directory_commit_token_path; + inline int count_files_in_directory(const char *path) { static struct dirent64 *(*real_readdir64)(DIR *) = NULL; - static DIR *(*real_opendir)(const char *) = NULL; - static int (*real_closedir)(DIR *) = NULL; + static DIR *(*real_opendir)(const char *) = NULL; + static int (*real_closedir)(DIR *) = NULL; START_LOG(capio_syscall(SYS_gettid), "call()"); syscall_no_intercept_flag = true; if (!real_readdir64) { - real_readdir64 = (struct dirent64 * (*)(DIR *)) dlsym(RTLD_NEXT, "readdir64"); + real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); } if (!real_opendir) { - real_opendir = (DIR * (*)(const char *)) dlsym(RTLD_NEXT, "opendir"); + real_opendir = (DIR * (*) (const char *) ) dlsym(RTLD_NEXT, "opendir"); } if (!real_closedir) { @@ -33,7 +35,7 @@ inline int count_files_in_directory(const char *path) { } struct dirent64 *entry; - DIR *dir = real_opendir(path); + DIR *dir = real_opendir(path); int count = 0; while ((entry = real_readdir64(dir)) != NULL) { @@ -61,10 +63,10 @@ inline int count_files_in_directory(const char *path) { entry_realpath.c_str()); auto *new_entry = new dirent64(); memcpy(new_entry->d_name, entry->d_name, sizeof(entry->d_name)); - new_entry->d_ino = entry->d_ino; - new_entry->d_off = entry->d_off; + new_entry->d_ino = entry->d_ino; + new_entry->d_off = entry->d_off; new_entry->d_reclen = entry->d_reclen; - new_entry->d_type = entry->d_type; + new_entry->d_type = entry->d_type; directory_object->emplace_back(new_entry); } count++; @@ -86,7 +88,7 @@ DIR *opendir(const char *name) { if (!real_opendir) { syscall_no_intercept_flag = true; - real_opendir = (DIR * (*)(const char *)) dlsym(RTLD_NEXT, "opendir"); + real_opendir = (DIR * (*) (const char *) ) dlsym(RTLD_NEXT, "opendir"); syscall_no_intercept_flag = false; if (!real_opendir) { ERR_EXIT("Failed to find original opendir: %s\n", dlerror()); @@ -108,7 +110,7 @@ DIR *opendir(const char *name) { consent_request_cache_fs->consent_request(realpath, gettid(), __FUNCTION__); syscall_no_intercept_flag = true; - auto dir = real_opendir(realpath); + auto dir = real_opendir(realpath); syscall_no_intercept_flag = false; LOG("Opened directory with offset %ld", dir); @@ -124,7 +126,7 @@ int closedir(DIR *dirp) { static int (*real_closedir)(DIR *) = NULL; if (!real_closedir) { syscall_no_intercept_flag = true; - real_closedir = (int (*)(DIR *)) dlsym(RTLD_NEXT, "closedir"); + real_closedir = (int (*)(DIR *)) dlsym(RTLD_NEXT, "closedir"); syscall_no_intercept_flag = false; if (!real_closedir) { ERR_EXIT("Failed to find original closedir: %s\n", dlerror()); @@ -140,7 +142,7 @@ int closedir(DIR *dirp) { LOG("removed dir from map of opened files"); } syscall_no_intercept_flag = true; - auto return_code = real_closedir(dirp); + auto return_code = real_closedir(dirp); syscall_no_intercept_flag = false; LOG("Return code of closedir = %d", return_code); @@ -148,32 +150,38 @@ int closedir(DIR *dirp) { } struct dirent *readdir(DIR *dirp) { - START_LOG(capio_syscall(SYS_gettid), "call(dir=%ld)", dirp); + long pid = capio_syscall(SYS_gettid); + START_LOG(pid, "call(dir=%ld)", dirp); static struct dirent *(*real_readdir)(DIR *) = NULL; if (!real_readdir) { LOG("Loading real glibc method"); syscall_no_intercept_flag = true; - real_readdir = (struct dirent * (*)(DIR *)) dlsym(RTLD_NEXT, "readdir"); + real_readdir = (struct dirent * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir"); syscall_no_intercept_flag = false; } - const bool dir_committed = posix_directory_committed( - capio_syscall(SYS_gettid), - std::get<0>(opened_directory.at(reinterpret_cast(dirp)))); + const auto directory_path = + std::get<0>(opened_directory.at(reinterpret_cast(dirp))); + + if (directory_commit_token_path.find(directory_path) == directory_commit_token_path.end()) { + char token_path[PATH_MAX]; + posix_directory_committed_request(pid, directory_path.c_str(), token_path); + directory_commit_token_path.insert({directory_path, token_path}); + } + + const auto token_path = directory_commit_token_path.at(directory_path); if (const auto item = opened_directory.find(reinterpret_cast(dirp)); - item != opened_directory.end() || dir_committed) { + item != opened_directory.end() || std::filesystem::exists(token_path)) { LOG("Found dirp."); - const auto dir_path_name = std::get<0>(item->second); + const auto dir_path_name = std::get<0>(item->second); const auto capio_internal_offset = std::get<1>(item->second); while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { LOG("Not enough files... waiting"); - if (posix_directory_committed( - capio_syscall(SYS_gettid), - std::get<0>(opened_directory.at(reinterpret_cast(dirp))))) { - return real_readdir(dirp); + if (std::filesystem::exists(token_path)) { + return NULL; } syscall_no_intercept_flag = true; sleep(1); @@ -187,8 +195,8 @@ struct dirent *readdir(DIR *dirp) { LOG("Getting files inside directory %s", real_path); - const auto return_value = - reinterpret_cast(directory_items->at(real_path)->at(std::get<1>(item->second))); + const auto return_value = reinterpret_cast( + directory_items->at(real_path)->at(std::get<1>(item->second))); std::get<1>(item->second)++; return return_value; } @@ -207,10 +215,9 @@ struct dirent64 *readdir64(DIR *dirp) { syscall_no_intercept_flag = false; } - if (auto item = opened_directory.find(reinterpret_cast(dirp)); item != opened_directory.end()) { - LOG("Found dirp."); - auto dir_path_name = std::get<0>(item->second); - auto capio_internal_offset = std::get<1>(item->second); + if (auto item = opened_directory.find(reinterpret_cast(dirp)); item != +opened_directory.end()) { LOG("Found dirp."); auto dir_path_name = std::get<0>(item->second); auto +capio_internal_offset = std::get<1>(item->second); while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { LOG("Not enough files... waiting"); diff --git a/src/posix/utils/requests.hpp b/src/posix/utils/requests.hpp index 12174b79c..3e4f0ebf6 100644 --- a/src/posix/utils/requests.hpp +++ b/src/posix/utils/requests.hpp @@ -27,7 +27,7 @@ inline thread_local SPSCQueue *stc_queue; */ inline void init_client() { buf_requests = - new CircularBuffer(SHM_COMM_CHAN_NAME, CAPIO_REQ_BUFF_CNT, CAPIO_REQ_MAX_SIZE); + new CircularBuffer(SHM_COMM_CHAN_NAME, CAPIO_REQ_BUFF_CNT, CAPIO_REQ_MAX_SIZE); bufs_response = new std::unordered_map(); } @@ -74,17 +74,20 @@ inline std::vector *file_in_memory_request(const long pid) { return regex_vector; } -inline bool posix_directory_committed(const long pid, const std::filesystem::path &path) { +inline capio_off64_t posix_directory_committed_request(const long pid, const std::filesystem::path &path, + char *token_path) { START_LOG(capio_syscall(SYS_gettid), "call(path=%s)", path.c_str()); char req[CAPIO_REQ_MAX_SIZE]; - sprintf(req, "%04d %s ", CAPIO_REQUEST_POSIX_DIR_COMMITTED, path.c_str()); + sprintf(req, "%04d %ld %s ", CAPIO_REQUEST_POSIX_DIR_COMMITTED, pid, path.c_str()); buf_requests->write(req, CAPIO_REQ_MAX_SIZE); LOG("Sent query for directory committement"); - capio_off64_t committed = bufs_response->at(pid)->read(); - LOG("Directory %s is %s", path.c_str(), committed ? "committed" : "not yet committed"); + capio_off64_t path_len = bufs_response->at(pid)->read(); + LOG("Directory %s has the token length of %llu", path.c_str(), path_len); - return committed == 1; + stc_queue->read(token_path, path_len); + LOG("commit token path will exist at %s", token_path); + return path_len; } // non blocking diff --git a/src/server/capio-cl-engine/capio_cl_engine.hpp b/src/server/capio-cl-engine/capio_cl_engine.hpp index bbd8ac3cc..18e30ad91 100644 --- a/src/server/capio-cl-engine/capio_cl_engine.hpp +++ b/src/server/capio-cl-engine/capio_cl_engine.hpp @@ -431,6 +431,13 @@ class CapioCLEngine { return files; } + + std::vector getPathsInConfig() { + std::vector paths; + std::transform(_locations.begin(), _locations.end(), std::back_inserter(paths), + [](auto pair) { return pair.first; }); + return paths; + } }; inline CapioCLEngine *capio_cl_engine; diff --git a/src/server/client-manager/handlers/posix_readdir.hpp b/src/server/client-manager/handlers/posix_readdir.hpp new file mode 100644 index 000000000..3e9377d0d --- /dev/null +++ b/src/server/client-manager/handlers/posix_readdir.hpp @@ -0,0 +1,18 @@ + +#ifndef POSIX_READDIR_HPP +#define POSIX_READDIR_HPP + +inline void posix_readdir_handler(const char *const str) { + pid_t pid; + char path[PATH_MAX]; + sscanf(str, "%d %s", &pid, path); + START_LOG(gettid(), "call(pid=%d, path=%s", pid, path); + + auto metadata_token = file_manager->getMetadataPath(path); + LOG("sending to pid %ld token path of %s", pid, metadata_token.c_str()); + + client_manager->reply_to_client(pid, metadata_token.length()); + storage_service->reply_to_client_raw(pid, metadata_token.c_str(), metadata_token.length()); +} + +#endif // POSIX_READDIR_HPP diff --git a/src/server/client-manager/request_handler_engine.hpp b/src/server/client-manager/request_handler_engine.hpp index fc96a0857..db1c340af 100644 --- a/src/server/client-manager/request_handler_engine.hpp +++ b/src/server/client-manager/request_handler_engine.hpp @@ -8,7 +8,7 @@ #include "file-manager/file_manager.hpp" /* - * REQUESTS handlers + * SYSCALL REQUESTS handlers */ #include "handlers/close.hpp" #include "handlers/consent.hpp" @@ -21,6 +21,11 @@ #include "handlers/rename.hpp" #include "handlers/write.hpp" +/* + * POSIX GLIBC REQUESTS handlers + */ +#include "handlers/posix_readdir.hpp" + /** * @brief Class that handles the system calls received from the posix client application * @@ -32,19 +37,20 @@ class RequestHandlerEngine { static constexpr std::array build_request_handlers_table() { std::array _request_handlers{0}; - _request_handlers[CAPIO_REQUEST_CONSENT] = consent_to_proceed_handler; - _request_handlers[CAPIO_REQUEST_CLOSE] = close_handler; - _request_handlers[CAPIO_REQUEST_CREATE] = create_handler; - _request_handlers[CAPIO_REQUEST_EXIT_GROUP] = exit_handler; - _request_handlers[CAPIO_REQUEST_HANDSHAKE] = handshake_handler; - _request_handlers[CAPIO_REQUEST_MKDIR] = create_handler; - _request_handlers[CAPIO_REQUEST_OPEN] = open_handler; - _request_handlers[CAPIO_REQUEST_READ] = read_handler; - _request_handlers[CAPIO_REQUEST_RENAME] = rename_handler; - _request_handlers[CAPIO_REQUEST_WRITE] = write_handler; - _request_handlers[CAPIO_REQUEST_QUERY_MEM_FILE] = files_to_store_in_memory_handler; - _request_handlers[CAPIO_REQUEST_READ_MEM] = read_mem_handler; - _request_handlers[CAPIO_REQUEST_WRITE_MEM] = write_mem_handler; + _request_handlers[CAPIO_REQUEST_CONSENT] = consent_to_proceed_handler; + _request_handlers[CAPIO_REQUEST_CLOSE] = close_handler; + _request_handlers[CAPIO_REQUEST_CREATE] = create_handler; + _request_handlers[CAPIO_REQUEST_EXIT_GROUP] = exit_handler; + _request_handlers[CAPIO_REQUEST_HANDSHAKE] = handshake_handler; + _request_handlers[CAPIO_REQUEST_MKDIR] = create_handler; + _request_handlers[CAPIO_REQUEST_OPEN] = open_handler; + _request_handlers[CAPIO_REQUEST_READ] = read_handler; + _request_handlers[CAPIO_REQUEST_RENAME] = rename_handler; + _request_handlers[CAPIO_REQUEST_WRITE] = write_handler; + _request_handlers[CAPIO_REQUEST_QUERY_MEM_FILE] = files_to_store_in_memory_handler; + _request_handlers[CAPIO_REQUEST_READ_MEM] = read_mem_handler; + _request_handlers[CAPIO_REQUEST_WRITE_MEM] = write_mem_handler; + _request_handlers[CAPIO_REQUEST_POSIX_DIR_COMMITTED] = posix_readdir_handler; return _request_handlers; } diff --git a/src/server/file-manager/file_manager.hpp b/src/server/file-manager/file_manager.hpp index 05664a0db..1fab3e965 100644 --- a/src/server/file-manager/file_manager.hpp +++ b/src/server/file-manager/file_manager.hpp @@ -31,6 +31,7 @@ class CapioFileManager { ~CapioFileManager() { START_LOG(gettid(), "call()"); } static uintmax_t get_file_size_if_exists(const std::filesystem::path &path); + static std::string getMetadataPath(const std::string &path); static void increaseCloseCount(const std::filesystem::path &path); static bool isCommitted(const std::filesystem::path &path); static void setCommitted(const std::filesystem::path &path); @@ -39,6 +40,7 @@ class CapioFileManager { void addThreadAwaitingCreation(const std::string &path, pid_t tid); void checkFilesAwaitingCreation(); void checkFileAwaitingData(); + void checkDirectoriesNFiles() const; }; inline CapioFileManager *file_manager; diff --git a/src/server/file-manager/file_manager_impl.hpp b/src/server/file-manager/file_manager_impl.hpp index 775b36ca3..15a58f2bc 100644 --- a/src/server/file-manager/file_manager_impl.hpp +++ b/src/server/file-manager/file_manager_impl.hpp @@ -6,10 +6,14 @@ #include "storage-service/capio_storage_service.hpp" #include "utils/distributed_semaphore.hpp" +inline std::string CapioFileManager::getMetadataPath(const std::string &path) { + return get_capio_metadata_path() / (path.substr(path.find(get_capio_dir()) + 1) + ".capio"); +} + /** * @brief Creates the directory structure for the metadata file and proceed to return the path * pointing to the metadata token file. For improvements in performances, a hash map is included to - * cache the computed paths. For thread safety conserns, see + * cache the computed paths. For thread safety concerns, see * https://en.cppreference.com/w/cpp/container#Thread_safety * * @param path real path of the file @@ -19,8 +23,8 @@ inline std::string CapioFileManager::getAndCreateMetadataPath(const std::string START_LOG(gettid(), "call(path=%s)", path.c_str()); static std::unordered_map metadata_paths; if (metadata_paths.find(path) == metadata_paths.end()) { - std::filesystem::path result = - get_capio_metadata_path() / (path.substr(path.find(get_capio_dir()) + 1) + ".capio"); + std::filesystem::path result = getMetadataPath(path); + metadata_paths.emplace(path, result); LOG("Creating metadata directory (%s)", result.parent_path().c_str()); std::filesystem::create_directories(result.parent_path()); @@ -382,4 +386,33 @@ inline void CapioFileManager::checkFileAwaitingData() { } } +/** + * @brief commit firectories that have NFILES inside them if their commit rule is n_files + */ +inline void CapioFileManager::checkDirectoriesNFiles() const { + START_LOG(gettid(), "call()"); + for (const auto &path_config : capio_cl_engine->getPathsInConfig()) { + if (!capio_cl_engine->isDirectory(path_config)) { + continue; + } + + auto n_files = capio_cl_engine->getDirectoryFileCount(path_config); + if (n_files > 0) { + LOG("Directory %s needs $ld files before being committed", path_config.c_str(), + n_files); + // There must be n_files inside the directory to commit the file + long count = 0; + for (const auto &entry : std::filesystem::directory_iterator(path_config)) { + ++count; + } + + LOG("Directory %s has %ld files inside", path_config.c_str(), count); + if (count >= n_files) { + LOG("Committing directory"); + this->setCommitted(path_config); + } + } + } +} + #endif // FILE_MANAGER_HPP \ No newline at end of file diff --git a/src/server/file-manager/fs_monitor.hpp b/src/server/file-manager/fs_monitor.hpp index 0be699842..92af56dda 100644 --- a/src/server/file-manager/fs_monitor.hpp +++ b/src/server/file-manager/fs_monitor.hpp @@ -32,6 +32,7 @@ class FileSystemMonitor { file_manager->checkFilesAwaitingCreation(); file_manager->checkFileAwaitingData(); + file_manager->checkDirectoriesNFiles(); nanosleep(&sleep, nullptr); } diff --git a/src/server/storage-service/capio_storage_service.hpp b/src/server/storage-service/capio_storage_service.hpp index 5de1c3d6d..88d8f1385 100644 --- a/src/server/storage-service/capio_storage_service.hpp +++ b/src/server/storage-service/capio_storage_service.hpp @@ -137,6 +137,16 @@ class CapioStorageService { getFile(file)->writeToQueue(*_server_to_client_queue->at(pid), offset, size); } + /** + * Send raw data to client without fetching from the storage manager itself + * @param pid + * @param data + * @param len + */ + void reply_to_client_raw(pid_t pid, const char *data, const capio_off64_t len) const { + _server_to_client_queue->at(pid)->write(data, len); + } + /** * Receive the file content from the client application * @param tid From 7f662a58ece29edf49d8f077dcb72352ce2a6e4c Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Fri, 6 Jun 2025 10:48:02 +0200 Subject: [PATCH 07/13] Increased responsiveness of posix component --- src/posix/handlers/posix_readdir.hpp | 77 +++++++++---------- src/server/file-manager/file_manager_impl.hpp | 4 +- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 40264d5db..811475246 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include // Map &DIR -> @@ -149,18 +150,8 @@ int closedir(DIR *dirp) { return return_code; } -struct dirent *readdir(DIR *dirp) { - long pid = capio_syscall(SYS_gettid); - START_LOG(pid, "call(dir=%ld)", dirp); - - static struct dirent *(*real_readdir)(DIR *) = NULL; - if (!real_readdir) { - LOG("Loading real glibc method"); - syscall_no_intercept_flag = true; - real_readdir = (struct dirent * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir"); - syscall_no_intercept_flag = false; - } - +bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *&value1) { + START_LOG(pid, "call()"); const auto directory_path = std::get<0>(opened_directory.at(reinterpret_cast(dirp))); @@ -181,10 +172,11 @@ struct dirent *readdir(DIR *dirp) { while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { LOG("Not enough files... waiting"); if (std::filesystem::exists(token_path)) { - return NULL; + value1 = NULL; + return true; } syscall_no_intercept_flag = true; - sleep(1); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); syscall_no_intercept_flag = false; } @@ -195,50 +187,51 @@ struct dirent *readdir(DIR *dirp) { LOG("Getting files inside directory %s", real_path); - const auto return_value = reinterpret_cast( - directory_items->at(real_path)->at(std::get<1>(item->second))); + const auto return_value = directory_items->at(real_path)->at(std::get<1>(item->second)); std::get<1>(item->second)++; - return return_value; + value1 = return_value; + return true; + } + return false; +} + +struct dirent *readdir(DIR *dirp) { + long pid = capio_syscall(SYS_gettid); + START_LOG(pid, "call(dir=%ld)", dirp); + + static struct dirent *(*real_readdir)(DIR *) = NULL; + if (!real_readdir) { + LOG("Loading real glibc method"); + syscall_no_intercept_flag = true; + real_readdir = (struct dirent * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir"); + syscall_no_intercept_flag = false; + } + struct dirent64 *capio_internal_dirent64; + if (capio_internal_Readdir(dirp, pid, capio_internal_dirent64)) { + return reinterpret_cast(capio_internal_dirent64); } + return real_readdir(dirp); } -/* struct dirent64 *readdir64(DIR *dirp) { - START_LOG(capio_syscall(SYS_gettid), "call(dir=%ld)", dirp); + long pid = capio_syscall(SYS_gettid); + START_LOG(pid, "call(dir=%ld)", dirp); static struct dirent64 *(*real_readdir64)(DIR *) = NULL; if (!real_readdir64) { LOG("Loading real glibc method"); syscall_no_intercept_flag = true; - real_readdir64 = (struct dirent64 * (*)(DIR *)) dlsym(RTLD_NEXT, "readdir64"); + real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); syscall_no_intercept_flag = false; } - if (auto item = opened_directory.find(reinterpret_cast(dirp)); item != -opened_directory.end()) { LOG("Found dirp."); auto dir_path_name = std::get<0>(item->second); auto -capio_internal_offset = std::get<1>(item->second); - - while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { - LOG("Not enough files... waiting"); - syscall_no_intercept_flag = true; - sleep(1); - syscall_no_intercept_flag = false; - } - - LOG("Returning item %d", std::get<1>(item->second)); - - char real_path[PATH_MAX]; - capio_realpath(dir_path_name.c_str(), real_path); - - LOG("Getting files inside directory %s", real_path); - - const auto return_value = directory_items->at(real_path)->at(std::get<1>(item->second)); - std::get<1>(item->second)++; - return return_value; + struct dirent64 *capio_internal_dirent64; + if (capio_internal_Readdir(dirp, pid, capio_internal_dirent64)) { + return capio_internal_dirent64; } + return real_readdir64(dirp); } -*/ #endif // POSIX_READDIR_HPP diff --git a/src/server/file-manager/file_manager_impl.hpp b/src/server/file-manager/file_manager_impl.hpp index 15a58f2bc..afb2df954 100644 --- a/src/server/file-manager/file_manager_impl.hpp +++ b/src/server/file-manager/file_manager_impl.hpp @@ -390,12 +390,12 @@ inline void CapioFileManager::checkFileAwaitingData() { * @brief commit firectories that have NFILES inside them if their commit rule is n_files */ inline void CapioFileManager::checkDirectoriesNFiles() const { - START_LOG(gettid(), "call()"); + for (const auto &path_config : capio_cl_engine->getPathsInConfig()) { if (!capio_cl_engine->isDirectory(path_config)) { continue; } - + START_LOG(gettid(), "call()"); auto n_files = capio_cl_engine->getDirectoryFileCount(path_config); if (n_files > 0) { LOG("Directory %s needs $ld files before being committed", path_config.c_str(), From 6b675c46d1845804526272eaee874679aaacf26f Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Mon, 9 Jun 2025 13:58:58 +0200 Subject: [PATCH 08/13] Fixes --- src/server/capio-cl-engine/capio_cl_engine.hpp | 6 ++++++ src/server/file-manager/file_manager_impl.hpp | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/server/capio-cl-engine/capio_cl_engine.hpp b/src/server/capio-cl-engine/capio_cl_engine.hpp index 18e30ad91..b4a027951 100644 --- a/src/server/capio-cl-engine/capio_cl_engine.hpp +++ b/src/server/capio-cl-engine/capio_cl_engine.hpp @@ -377,6 +377,12 @@ class CapioCLEngine { void setFileDeps(const std::filesystem::path &path, const std::vector &dependencies) { START_LOG(gettid(), "call()"); + if (dependencies.empty()) { + return; + } + if (_locations.find(path) == _locations.end()) { + this->newFile(path); + } std::get<9>(_locations.at(path)) = dependencies; for (const auto &itm : dependencies) { LOG("Creating new fie (if it exists) for path %s", itm.c_str()); diff --git a/src/server/file-manager/file_manager_impl.hpp b/src/server/file-manager/file_manager_impl.hpp index afb2df954..2e5aee877 100644 --- a/src/server/file-manager/file_manager_impl.hpp +++ b/src/server/file-manager/file_manager_impl.hpp @@ -402,8 +402,11 @@ inline void CapioFileManager::checkDirectoriesNFiles() const { n_files); // There must be n_files inside the directory to commit the file long count = 0; - for (const auto &entry : std::filesystem::directory_iterator(path_config)) { - ++count; + if (std::filesystem::exists(path_config)) { + auto iterator = std::filesystem::directory_iterator(path_config); + for (const auto &entry : iterator) { + ++count; + } } LOG("Directory %s has %ld files inside", path_config.c_str(), count); From 0aa828372ade985a99f25d799c17de27fc63f4bd Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Mon, 9 Jun 2025 17:41:25 +0200 Subject: [PATCH 09/13] Fixes --- src/common/capio/filesystem.hpp | 2 +- src/posix/handlers/posix_readdir.hpp | 10 +++++++++- src/server/capio-cl-engine/capio_cl_engine.hpp | 1 + src/server/file-manager/file_manager_impl.hpp | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/common/capio/filesystem.hpp b/src/common/capio/filesystem.hpp index bd295df86..eafdb1018 100644 --- a/src/common/capio/filesystem.hpp +++ b/src/common/capio/filesystem.hpp @@ -106,7 +106,7 @@ inline bool is_capio_path(const std::filesystem::path &path_to_check) { START_LOG(gettid(), "call(capio_path=%s)", capio_path.c_str()); auto computed = replaceSymbol(capio_path, '.', "\\."); computed = replaceSymbol(computed, '/', "\\/"); - computed = replaceSymbol(computed, '*', R"([a-zA-Z0-9\/\.\-_]*)"); + computed = replaceSymbol(computed, '*', R"([a-zA-Z0-9\/\.\-_:]*)"); computed = replaceSymbol(computed, '+', "."); LOG("Computed regex: %s", computed.c_str()); return std::regex(computed); diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 811475246..46e3ba61e 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -151,7 +151,14 @@ int closedir(DIR *dirp) { } bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *&value1) { - START_LOG(pid, "call()"); + START_LOG(pid, "call(dirp=%ld)", dirp); + + if (opened_directory.find(reinterpret_cast(dirp)) == + opened_directory.end()) { + LOG("Directory is not handled by CAPIO. Returning false"); + return false; + } + const auto directory_path = std::get<0>(opened_directory.at(reinterpret_cast(dirp))); @@ -206,6 +213,7 @@ struct dirent *readdir(DIR *dirp) { real_readdir = (struct dirent * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir"); syscall_no_intercept_flag = false; } + struct dirent64 *capio_internal_dirent64; if (capio_internal_Readdir(dirp, pid, capio_internal_dirent64)) { return reinterpret_cast(capio_internal_dirent64); diff --git a/src/server/capio-cl-engine/capio_cl_engine.hpp b/src/server/capio-cl-engine/capio_cl_engine.hpp index b4a027951..89214524c 100644 --- a/src/server/capio-cl-engine/capio_cl_engine.hpp +++ b/src/server/capio-cl-engine/capio_cl_engine.hpp @@ -141,6 +141,7 @@ class CapioCLEngine { * @return */ bool contains(const std::filesystem::path &file) { + START_LOG(gettid(), "call(file=%s)", file.c_str()); return std::any_of(_locations.begin(), _locations.end(), [&](auto &itm) { return std::regex_match(file.c_str(), std::get<10>(itm.second)); }); diff --git a/src/server/file-manager/file_manager_impl.hpp b/src/server/file-manager/file_manager_impl.hpp index 2e5aee877..deb99110c 100644 --- a/src/server/file-manager/file_manager_impl.hpp +++ b/src/server/file-manager/file_manager_impl.hpp @@ -398,7 +398,7 @@ inline void CapioFileManager::checkDirectoriesNFiles() const { START_LOG(gettid(), "call()"); auto n_files = capio_cl_engine->getDirectoryFileCount(path_config); if (n_files > 0) { - LOG("Directory %s needs $ld files before being committed", path_config.c_str(), + LOG("Directory %s needs %ld files before being committed", path_config.c_str(), n_files); // There must be n_files inside the directory to commit the file long count = 0; From 297c2b800a2ec56c0fe4cb4fe94b3e21059fdc7b Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Mon, 9 Jun 2025 18:20:16 +0200 Subject: [PATCH 10/13] fixes --- src/posix/handlers/posix_readdir.hpp | 31 +++++++++++++++------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 46e3ba61e..1c3763c38 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -21,7 +21,7 @@ inline int count_files_in_directory(const char *path) { static DIR *(*real_opendir)(const char *) = NULL; static int (*real_closedir)(DIR *) = NULL; - START_LOG(capio_syscall(SYS_gettid), "call()"); + START_LOG(capio_syscall(SYS_gettid), "call(path=%s)", path); syscall_no_intercept_flag = true; if (!real_readdir64) { real_readdir64 = (struct dirent64 * (*) (DIR *) ) dlsym(RTLD_NEXT, "readdir64"); @@ -40,19 +40,20 @@ inline int count_files_in_directory(const char *path) { int count = 0; while ((entry = real_readdir64(dir)) != NULL) { - auto entry_realpath = (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - ? entry->d_name - : capio_absolute(entry->d_name); - char realp_dir_path[PATH_MAX]; - capio_realpath(path, realp_dir_path); + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + LOG("Entry name is %s... skipping", entry->d_name); + continue; + } + auto dir_abs_path = std::string(path) + "/" + entry->d_name; + LOG("Directory abs path = %s", dir_abs_path.c_str()); - if (auto directory_object = directory_items->find(entry_realpath); + if (auto directory_object = directory_items->find(dir_abs_path.c_str()); directory_object == directory_items->end()) { - LOG("Directory vector not present. Adding it at path %s", realp_dir_path); - directory_items->emplace(realp_dir_path, new std::vector()); + LOG("Directory vector not present. Adding it at path %s", path); + directory_items->emplace(path, new std::vector()); } - auto directory_object = directory_items->at(realp_dir_path); + auto directory_object = directory_items->at(path); auto itm = std::find_if(directory_object->begin(), directory_object->end(), [&](const dirent64 *_scope_entry) { @@ -61,7 +62,7 @@ inline int count_files_in_directory(const char *path) { if (itm == directory_object->end()) { LOG("Item %s is not stored within internal capio data structure. adding it", - entry_realpath.c_str()); + dir_abs_path.c_str()); auto *new_entry = new dirent64(); memcpy(new_entry->d_name, entry->d_name, sizeof(entry->d_name)); new_entry->d_ino = entry->d_ino; @@ -182,9 +183,11 @@ bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *&value1) { value1 = NULL; return true; } - syscall_no_intercept_flag = true; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - syscall_no_intercept_flag = false; + + struct timespec req; + req.tv_sec = 0; + req.tv_nsec = 100 * 1000000L; // 100 ms + syscall_no_intercept(SYS_nanosleep, &req, NULL); } LOG("Returning item %d", std::get<1>(item->second)); From 2ac87bbd56efca005de6dae50da58330cbcf122b Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Tue, 10 Jun 2025 15:22:05 +0200 Subject: [PATCH 11/13] tests --- src/posix/handlers/open.hpp | 3 +- src/posix/handlers/posix_readdir.hpp | 91 +++++++++++++++++++++------- 2 files changed, 71 insertions(+), 23 deletions(-) diff --git a/src/posix/handlers/open.hpp b/src/posix/handlers/open.hpp index 65340469f..f8424a25d 100644 --- a/src/posix/handlers/open.hpp +++ b/src/posix/handlers/open.hpp @@ -103,7 +103,8 @@ int openat_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long a int flags = static_cast(arg2); mode_t mode = static_cast(arg3); auto tid = static_cast(syscall_no_intercept(SYS_gettid)); - START_LOG(tid, "call(path=%s, flags=%d, mode=%d)", pathname.data(), flags, mode); + START_LOG(tid, "call(dirfd=%ld, path=%s, flags=%d, mode=%d)", dirfd, pathname.data(), flags, + mode); std::string path = compute_abs_path(pathname.data(), dirfd); diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 1c3763c38..31113dfa5 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -40,12 +40,14 @@ inline int count_files_in_directory(const char *path) { int count = 0; while ((entry = real_readdir64(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { - LOG("Entry name is %s... skipping", entry->d_name); - continue; + + std::filesystem::path dir_abs_path(entry->d_name); + + if (!(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)) { + LOG("Entry name is %s. computing absolute path", entry->d_name); + dir_abs_path = std::filesystem::path(path) / entry->d_name; + LOG("Directory abs path = %s", dir_abs_path.c_str()); } - auto dir_abs_path = std::string(path) + "/" + entry->d_name; - LOG("Directory abs path = %s", dir_abs_path.c_str()); if (auto directory_object = directory_items->find(dir_abs_path.c_str()); directory_object == directory_items->end()) { @@ -82,9 +84,14 @@ inline int count_files_in_directory(const char *path) { } DIR *opendir(const char *name) { - char realpath[PATH_MAX]{0}; - capio_realpath(name, realpath); - START_LOG(gettid(), "call(path=%s)", realpath); + + auto tmp = std::string(name); + + START_LOG(capio_syscall(SYS_gettid), "call(path=%s)", tmp.c_str()); + + auto absolute_path = capio_absolute(name); + + LOG("Resolved absolute path = %s", absolute_path.c_str()); static DIR *(*real_opendir)(const char *) = NULL; @@ -101,23 +108,31 @@ DIR *opendir(const char *name) { directory_items = new std::unordered_map *>(); } - if (!is_capio_path(realpath)) { + if (!is_capio_path(absolute_path)) { LOG("Not a CAPIO path. continuing execution"); - auto dir = real_opendir(realpath); + syscall_no_intercept_flag = true; + auto dir = real_opendir(absolute_path.c_str()); + syscall_no_intercept_flag = false; return dir; } - LOG("Performing consent request to open directory %s", realpath); - consent_request_cache_fs->consent_request(realpath, gettid(), __FUNCTION__); + LOG("Performing consent request to open directory %s", absolute_path.c_str()); + consent_request_cache_fs->consent_request(absolute_path.c_str(), gettid(), __FUNCTION__); syscall_no_intercept_flag = true; - auto dir = real_opendir(realpath); + auto dir = real_opendir(absolute_path.c_str()); syscall_no_intercept_flag = false; LOG("Opened directory with offset %ld", dir); - opened_directory.insert({reinterpret_cast(dir), {std::string(realpath), 0}}); - directory_items->emplace(std::string(realpath), new std::vector()); + opened_directory.insert( + {reinterpret_cast(dir), {std::string(absolute_path), 0}}); + directory_items->emplace(std::string(absolute_path), new std::vector()); + + auto fd = dirfd(dir); + LOG("File descriptor for directory %s is %d", absolute_path.c_str(), fd); + + add_capio_fd(capio_syscall(SYS_gettid), absolute_path.c_str(), fd, 0, 0); return dir; } @@ -137,12 +152,18 @@ int closedir(DIR *dirp) { if (const auto pos = opened_directory.find(reinterpret_cast(dirp)); pos != opened_directory.end()) { + + syscall_no_intercept_flag = true; + delete_capio_fd(dirfd(dirp)); + syscall_no_intercept_flag = false; + if (auto pos1 = directory_items->find(pos->second.first); pos1 != directory_items->end()) { directory_items->erase(pos1); } opened_directory.erase(pos); LOG("removed dir from map of opened files"); } + syscall_no_intercept_flag = true; auto return_code = real_closedir(dirp); syscall_no_intercept_flag = false; @@ -151,7 +172,7 @@ int closedir(DIR *dirp) { return return_code; } -bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *&value1) { +bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *value1) { START_LOG(pid, "call(dirp=%ld)", dirp); if (opened_directory.find(reinterpret_cast(dirp)) == @@ -164,8 +185,9 @@ bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *&value1) { std::get<0>(opened_directory.at(reinterpret_cast(dirp))); if (directory_commit_token_path.find(directory_path) == directory_commit_token_path.end()) { - char token_path[PATH_MAX]; + char token_path[PATH_MAX]{0}; posix_directory_committed_request(pid, directory_path.c_str(), token_path); + LOG("Inserting token path %s", token_path); directory_commit_token_path.insert({directory_path, token_path}); } @@ -177,9 +199,18 @@ bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *&value1) { const auto dir_path_name = std::get<0>(item->second); const auto capio_internal_offset = std::get<1>(item->second); - while (count_files_in_directory(dir_path_name.c_str()) <= capio_internal_offset) { - LOG("Not enough files... waiting"); - if (std::filesystem::exists(token_path)) { + auto files_in_directory = count_files_in_directory(dir_path_name.c_str()); + LOG("There are %ld files inside %s", files_in_directory, dir_path_name.c_str()); + while (files_in_directory <= capio_internal_offset) { + LOG("Not enough files: expected %ld, got %ld... waiting", files_in_directory, + capio_internal_offset); + LOG("Checking for commit token existence (%s)", token_path.c_str()); + syscall_no_intercept_flag = true; + bool is_committed = std::filesystem::exists(token_path); + syscall_no_intercept_flag = false; + LOG("File %s committed", is_committed ? "is" : "is not"); + if (is_committed) { + LOG("Returning NULL as result"); value1 = NULL; return true; } @@ -188,6 +219,8 @@ bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *&value1) { req.tv_sec = 0; req.tv_nsec = 100 * 1000000L; // 100 ms syscall_no_intercept(SYS_nanosleep, &req, NULL); + files_in_directory = count_files_in_directory(dir_path_name.c_str()); + LOG("There are %ld files inside %s", files_in_directory, dir_path_name.c_str()); } LOG("Returning item %d", std::get<1>(item->second)); @@ -200,6 +233,12 @@ bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *&value1) { const auto return_value = directory_items->at(real_path)->at(std::get<1>(item->second)); std::get<1>(item->second)++; value1 = return_value; + LOG("Returned dirent structure:"); + LOG("dirent.d_name = %s", value1->d_name); + LOG("dirent.d_type = %d", value1->d_type); + LOG("dirent.d_ino = %d", value1->d_ino); + LOG("dirent.d_off = %d", value1->d_off); + LOG("dirent.d_reclen = %d", value1->d_reclen); return true; } return false; @@ -222,7 +261,11 @@ struct dirent *readdir(DIR *dirp) { return reinterpret_cast(capio_internal_dirent64); } - return real_readdir(dirp); + syscall_no_intercept_flag = true; + auto result = real_readdir(dirp); + syscall_no_intercept_flag = false; + + return result; } struct dirent64 *readdir64(DIR *dirp) { @@ -242,7 +285,11 @@ struct dirent64 *readdir64(DIR *dirp) { return capio_internal_dirent64; } - return real_readdir64(dirp); + syscall_no_intercept_flag = true; + auto result = real_readdir64(dirp); + syscall_no_intercept_flag = false; + + return result; } #endif // POSIX_READDIR_HPP From 571c77b8a0886a4dfd095ec53e7ef2cb709fbfda Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Wed, 11 Jun 2025 15:28:21 +0200 Subject: [PATCH 12/13] Fixed stream on directories added missing errno, and fixed return value when doing directory streaming --- src/posix/handlers/posix_readdir.hpp | 70 ++++++++++++++-------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/src/posix/handlers/posix_readdir.hpp b/src/posix/handlers/posix_readdir.hpp index 31113dfa5..2f9c8d8d6 100644 --- a/src/posix/handlers/posix_readdir.hpp +++ b/src/posix/handlers/posix_readdir.hpp @@ -172,15 +172,9 @@ int closedir(DIR *dirp) { return return_code; } -bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *value1) { +inline struct dirent64 *capio_internal_readdir(DIR *dirp, long pid) { START_LOG(pid, "call(dirp=%ld)", dirp); - if (opened_directory.find(reinterpret_cast(dirp)) == - opened_directory.end()) { - LOG("Directory is not handled by CAPIO. Returning false"); - return false; - } - const auto directory_path = std::get<0>(opened_directory.at(reinterpret_cast(dirp))); @@ -211,11 +205,11 @@ bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *value1) { LOG("File %s committed", is_committed ? "is" : "is not"); if (is_committed) { LOG("Returning NULL as result"); - value1 = NULL; - return true; + errno = 0; + return NULL; } - struct timespec req; + struct timespec req{0}; req.tv_sec = 0; req.tv_nsec = 100 * 1000000L; // 100 ms syscall_no_intercept(SYS_nanosleep, &req, NULL); @@ -232,16 +226,18 @@ bool capio_internal_Readdir(DIR *dirp, long pid, struct dirent64 *value1) { const auto return_value = directory_items->at(real_path)->at(std::get<1>(item->second)); std::get<1>(item->second)++; - value1 = return_value; + LOG("Returned dirent structure:"); - LOG("dirent.d_name = %s", value1->d_name); - LOG("dirent.d_type = %d", value1->d_type); - LOG("dirent.d_ino = %d", value1->d_ino); - LOG("dirent.d_off = %d", value1->d_off); - LOG("dirent.d_reclen = %d", value1->d_reclen); - return true; + LOG("dirent.d_name = %s", return_value->d_name); + LOG("dirent.d_type = %d", return_value->d_type); + LOG("dirent.d_ino = %d", return_value->d_ino); + LOG("dirent.d_off = %d", return_value->d_off); + LOG("dirent.d_reclen = %d", return_value->d_reclen); + return return_value; } - return false; + LOG("Reached end of branch... something might be amiss.. returning EOS"); + errno = 0; + return NULL; } struct dirent *readdir(DIR *dirp) { @@ -256,16 +252,19 @@ struct dirent *readdir(DIR *dirp) { syscall_no_intercept_flag = false; } - struct dirent64 *capio_internal_dirent64; - if (capio_internal_Readdir(dirp, pid, capio_internal_dirent64)) { - return reinterpret_cast(capio_internal_dirent64); - } + if (opened_directory.find(reinterpret_cast(dirp)) == + opened_directory.end()) { + LOG("Directory is not handled by CAPIO. Returning false"); + syscall_no_intercept_flag = true; + auto result = real_readdir(dirp); + syscall_no_intercept_flag = false; - syscall_no_intercept_flag = true; - auto result = real_readdir(dirp); - syscall_no_intercept_flag = false; + return result; + } - return result; + struct dirent64 *capio_internal_dirent64 = capio_internal_readdir(dirp, pid); + LOG("return value == NULL ? %s", capio_internal_dirent64 == NULL ? "TRUE" : "FALSE"); + return reinterpret_cast(capio_internal_dirent64); } struct dirent64 *readdir64(DIR *dirp) { @@ -280,16 +279,19 @@ struct dirent64 *readdir64(DIR *dirp) { syscall_no_intercept_flag = false; } - struct dirent64 *capio_internal_dirent64; - if (capio_internal_Readdir(dirp, pid, capio_internal_dirent64)) { - return capio_internal_dirent64; - } + if (opened_directory.find(reinterpret_cast(dirp)) == + opened_directory.end()) { + LOG("Directory is not handled by CAPIO. Returning false"); + syscall_no_intercept_flag = true; + auto result = real_readdir64(dirp); + syscall_no_intercept_flag = false; - syscall_no_intercept_flag = true; - auto result = real_readdir64(dirp); - syscall_no_intercept_flag = false; + return result; + } - return result; + auto capio_internal_dirent64 = capio_internal_readdir(dirp, pid); + LOG("return value == NULL ? %s", capio_internal_dirent64 == NULL ? "TRUE" : "FALSE"); + return capio_internal_dirent64; } #endif // POSIX_READDIR_HPP From 1731b825ede13d5f06e16f8db889ca59d4f1b694 Mon Sep 17 00:00:00 2001 From: Marco Edoardo Santimaria Date: Wed, 11 Jun 2025 15:52:56 +0200 Subject: [PATCH 13/13] format cleanup --- src/common/capio/requests.hpp | 26 +++++++++++++------------- src/posix/handlers.hpp | 1 - src/posix/libcapio_posix.cpp | 2 -- src/posix/utils/requests.hpp | 5 +++-- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/common/capio/requests.hpp b/src/common/capio/requests.hpp index 63e253739..627cdff92 100644 --- a/src/common/capio/requests.hpp +++ b/src/common/capio/requests.hpp @@ -1,19 +1,19 @@ #ifndef CAPIO_COMMON_REQUESTS_HPP #define CAPIO_COMMON_REQUESTS_HPP -constexpr const int CAPIO_REQUEST_CONSENT = 0; -constexpr const int CAPIO_REQUEST_CLOSE = 1; -constexpr const int CAPIO_REQUEST_CREATE = 2; -constexpr const int CAPIO_REQUEST_EXIT_GROUP = 3; -constexpr const int CAPIO_REQUEST_HANDSHAKE = 4; -constexpr const int CAPIO_REQUEST_MKDIR = 5; -constexpr const int CAPIO_REQUEST_OPEN = 6; -constexpr const int CAPIO_REQUEST_READ = 7; -constexpr const int CAPIO_REQUEST_READ_MEM = 8; -constexpr const int CAPIO_REQUEST_RENAME = 9; -constexpr const int CAPIO_REQUEST_WRITE = 10; -constexpr const int CAPIO_REQUEST_WRITE_MEM = 11; -constexpr const int CAPIO_REQUEST_QUERY_MEM_FILE = 12; +constexpr const int CAPIO_REQUEST_CONSENT = 0; +constexpr const int CAPIO_REQUEST_CLOSE = 1; +constexpr const int CAPIO_REQUEST_CREATE = 2; +constexpr const int CAPIO_REQUEST_EXIT_GROUP = 3; +constexpr const int CAPIO_REQUEST_HANDSHAKE = 4; +constexpr const int CAPIO_REQUEST_MKDIR = 5; +constexpr const int CAPIO_REQUEST_OPEN = 6; +constexpr const int CAPIO_REQUEST_READ = 7; +constexpr const int CAPIO_REQUEST_READ_MEM = 8; +constexpr const int CAPIO_REQUEST_RENAME = 9; +constexpr const int CAPIO_REQUEST_WRITE = 10; +constexpr const int CAPIO_REQUEST_WRITE_MEM = 11; +constexpr const int CAPIO_REQUEST_QUERY_MEM_FILE = 12; constexpr const int CAPIO_REQUEST_POSIX_DIR_COMMITTED = 13; constexpr const int CAPIO_NR_REQUESTS = 14; diff --git a/src/posix/handlers.hpp b/src/posix/handlers.hpp index 15054589e..6cbd7172d 100644 --- a/src/posix/handlers.hpp +++ b/src/posix/handlers.hpp @@ -30,7 +30,6 @@ #include "handlers/unlink.hpp" #include "handlers/write.hpp" - /********************/ // POSIX HANDLERS // /********************/ diff --git a/src/posix/libcapio_posix.cpp b/src/posix/libcapio_posix.cpp index 06d943b87..93dc776eb 100644 --- a/src/posix/libcapio_posix.cpp +++ b/src/posix/libcapio_posix.cpp @@ -366,8 +366,6 @@ static constexpr std::array build_syscall_table( return _syscallTable; } - - static int hook(long syscall_number, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5, long *result) { static constexpr std::array syscallTable = diff --git a/src/posix/utils/requests.hpp b/src/posix/utils/requests.hpp index 3e4f0ebf6..661642cad 100644 --- a/src/posix/utils/requests.hpp +++ b/src/posix/utils/requests.hpp @@ -74,8 +74,9 @@ inline std::vector *file_in_memory_request(const long pid) { return regex_vector; } -inline capio_off64_t posix_directory_committed_request(const long pid, const std::filesystem::path &path, - char *token_path) { +inline capio_off64_t posix_directory_committed_request(const long pid, + const std::filesystem::path &path, + char *token_path) { START_LOG(capio_syscall(SYS_gettid), "call(path=%s)", path.c_str()); char req[CAPIO_REQ_MAX_SIZE];