diff --git a/capio-common/capio/filesystem.hpp b/capio-common/capio/filesystem.hpp index d9c30e6eb..7b06a2f8c 100644 --- a/capio-common/capio/filesystem.hpp +++ b/capio-common/capio/filesystem.hpp @@ -72,17 +72,12 @@ inline bool is_capio_dir(const std::filesystem::path &path_to_check) { inline bool is_capio_path(const std::filesystem::path &path_to_check) { START_LOG(capio_syscall(SYS_gettid), "call(path_to_check=%s)", path_to_check.c_str()); - // check if path_to_check begins with CAPIO_DIR - const auto is_prefix_res = is_prefix(get_capio_dir(), path_to_check); + // check if path_to_check begins with CAPIO_DIR and is not within the forbidden paths + const auto is_capio_path = + is_prefix(get_capio_dir(), path_to_check) && !is_forbidden_path(path_to_check.string()); - LOG("IS PREFIX=%s", is_prefix_res ? "TRUE" : "FALSE"); - - const auto is_forbidden_res = is_forbidden_path(path_to_check.string()); - - LOG("IS FORBIDDEN=%s", is_forbidden_res ? "TRUE" : "FALSE"); - - LOG("is_capio_path:%s", is_prefix_res && !is_forbidden_res ? "yes" : "no"); - return is_prefix_res && !is_forbidden_res; + LOG("is_capio_path:%s", is_capio_path ? "yes" : "no"); + return is_capio_path; } /** diff --git a/capio-posix/handlers/exit.hpp b/capio-posix/handlers/exit.hpp index c966035fc..1c81f8cef 100644 --- a/capio-posix/handlers/exit.hpp +++ b/capio-posix/handlers/exit.hpp @@ -21,15 +21,15 @@ int exit_handler(long arg0, long arg1, long arg2, long arg3, long arg4, long arg syscall_no_intercept_flag = true; LOG("syscall_no_intercept_flag = true"); + delete_caches(); + LOG("Removed caches"); + if (is_capio_tid(tid)) { LOG("Thread %d is a CAPIO thread: clean up", tid); exit_group_request(tid); remove_capio_tid(tid); } - delete_caches(); - LOG("Removed caches"); - if (const auto itm = bufs_response->find(tid); itm != bufs_response->end()) { delete itm->second; bufs_response->erase(tid); diff --git a/capio-posix/utils/cache/read_request_cache_fs.hpp b/capio-posix/utils/cache/read_request_cache_fs.hpp index a82130a40..89c2c1949 100644 --- a/capio-posix/utils/cache/read_request_cache_fs.hpp +++ b/capio-posix/utils/cache/read_request_cache_fs.hpp @@ -48,7 +48,7 @@ class ReadRequestCacheFS { } else { LOG("[cache] Entry not found, initializing new entry to offset 0"); max_read = 0; - available_read_cache->emplace(current_path, max_read); + available_read_cache->emplace(current_path, 0); } LOG("[cache] Max read value is %llu %s", max_read, max_read == ULLONG_MAX ? "(ULLONG_MAX)" : ""); @@ -65,9 +65,12 @@ class ReadRequestCacheFS { max_read = _read_request(current_path, end_of_read, tid, fd); LOG("[cache] Obtained value from server is %llu", max_read); if (available_read_cache->find(path) == available_read_cache->end()) { + LOG("[cache] Cound not find entry in cache. Adding new entry to cache"); available_read_cache->emplace(path, max_read); } else { available_read_cache->at(path) = max_read; + LOG("[cache] Updating max read value in cache. new value: %llu", + available_read_cache->at(path)); } LOG("[cache] completed update from server of max read for file. returning control to " "application"); diff --git a/capio-posix/utils/cache/write_request_cache_fs.hpp b/capio-posix/utils/cache/write_request_cache_fs.hpp index a2da60615..570eb1b52 100644 --- a/capio-posix/utils/cache/write_request_cache_fs.hpp +++ b/capio-posix/utils/cache/write_request_cache_fs.hpp @@ -2,19 +2,18 @@ #define WRITE_REQUEST_CACHE_FS_HPP class WriteRequestCacheFS { - int current_fd = -1; - capio_off64_t current_size = 0; + std::unordered_map capio_internal_write_offsets; const capio_off64_t _max_size; std::filesystem::path current_path; // non-blocking as write is not in the pre port of CAPIO semantics - inline void _write_request(const off64_t count, const long tid, const long fd) const { + inline void _write_request(capio_off64_t count, const long tid, const long fd) const { START_LOG(capio_syscall(SYS_gettid), "call(path=%s, count=%ld, tid=%ld)", current_path.c_str(), count, tid); char req[CAPIO_REQ_MAX_SIZE]; - sprintf(req, "%04d %ld %ld %s %ld", CAPIO_REQUEST_WRITE, tid, fd, current_path.c_str(), + sprintf(req, "%04d %ld %ld %s %llu", CAPIO_REQUEST_WRITE, tid, fd, current_path.c_str(), count); buf_requests->write(req, CAPIO_REQ_MAX_SIZE); } @@ -24,34 +23,34 @@ class WriteRequestCacheFS { ~WriteRequestCacheFS() { START_LOG(capio_syscall(SYS_gettid), "call()"); - this->flush(capio_syscall(SYS_gettid)); + const int tid = capio_syscall(SYS_gettid); + for (auto &[path, size] : capio_internal_write_offsets) { + this->flush(path, tid, -1); + } } - void write_request(std::filesystem::path path, int tid, int fd, long count) { + void write_request(const std::filesystem::path &path, int tid, int fd, long count) { START_LOG(capio_syscall(SYS_gettid), "call(path=%s, tid=%ld, fd=%ld, count=%ld)", path.c_str(), tid, fd, count); - if (fd != current_fd || path.compare(current_path) != 0) { - LOG("File descriptor changed from previous state. updating"); - this->flush(tid); - current_path = std::move(path); - current_fd = fd; + + if (!capio_internal_write_offsets.contains(path.c_str())) { + capio_internal_write_offsets[path.c_str()] = 0; } - current_size += count; - if (current_size > _max_size) { + capio_internal_write_offsets[path.c_str()] += count; + + if (capio_internal_write_offsets[path.c_str()] >= _max_size) { LOG("exceeded maximum cache size. flushing..."); - this->flush(tid); + this->flush(path, tid, fd); + capio_internal_write_offsets[path.c_str()] = 0; } }; - void flush(int tid) { - START_LOG(capio_syscall(SYS_gettid), "call(tid=%ld)", tid); - if (current_fd != -1 && current_size > 0) { - LOG("Performing write to SHM"); - _write_request(tid, current_fd, current_size); - } - current_fd = -1; - current_size = 0; + void flush(const std::filesystem::path &path, long tid, int fd) { + START_LOG(capio_syscall(SYS_gettid), "call(tid=%ld, path=%s)", tid, path.c_str()); + + LOG("Performing write to SHM"); + _write_request(capio_internal_write_offsets[path.c_str()], tid, fd); } }; diff --git a/capio-posix/utils/filesystem.hpp b/capio-posix/utils/filesystem.hpp index 47b6ecebc..04f3b64f1 100644 --- a/capio-posix/utils/filesystem.hpp +++ b/capio-posix/utils/filesystem.hpp @@ -307,48 +307,56 @@ inline void set_current_dir(const std::filesystem::path &cwd) { */ [[maybe_unused]] [[nodiscard]] static std::string resolve_possible_symlink(const std::filesystem::path &input_path) { - START_LOG(capio_syscall(SYS_gettid), "call(path=%s)", input_path.c_str()); - LOG("Absolute path = %s", input_path.c_str()); + // Cache for resolved symbolic links: link -> realpath + static std::unordered_map resolved_symlinks_cache; + + if (!resolved_symlinks_cache.contains(input_path)) { + START_LOG(capio_syscall(SYS_gettid), "call(path=%s)", input_path.c_str()); + + LOG("Absolute path = %s", input_path.c_str()); #ifdef __CAPIO_POSIX - syscall_no_intercept_flag = true; + syscall_no_intercept_flag = true; #endif - std::filesystem::path resolved, input_abs_path = std::filesystem::absolute(input_path); + std::filesystem::path resolved; - for (const auto &part : input_abs_path) { - resolved /= part; + for (std::filesystem::path input_abs_path = std::filesystem::absolute(input_path); + const auto &part : input_abs_path) { + resolved /= part; - if (part == "." || part.empty()) { - continue; - } - if (part == "..") { - resolved = resolved.parent_path(); - continue; - } - if (std::filesystem::is_symlink(resolved)) { - char buf[PATH_MAX]{0}; - auto result = - capio_syscall(SYS_readlinkat, AT_FDCWD, resolved.c_str(), buf, sizeof(buf) - 1); - if (result == -1) { - LOG("File might not exist. path was %s and Error is %s", resolved.c_str(), - strerror(errno)); + if (part == "." || part.empty()) { continue; } - - if (std::filesystem::path target(buf); target.is_relative()) { - resolved = resolved.parent_path() / target; - } else { - resolved = target; + if (part == "..") { + resolved = resolved.parent_path(); + continue; + } + if (std::filesystem::is_symlink(resolved)) { + char buf[PATH_MAX]{0}; + auto result = + capio_syscall(SYS_readlinkat, AT_FDCWD, resolved.c_str(), buf, sizeof(buf) - 1); + if (result == -1) { + LOG("File might not exist. path was %s and Error is %s", resolved.c_str(), + strerror(errno)); + continue; + } + + if (std::filesystem::path target(buf); target.is_relative()) { + resolved = resolved.parent_path() / target; + } else { + resolved = target; + } } } - } #ifdef __CAPIO_POSIX - syscall_no_intercept_flag = false; + syscall_no_intercept_flag = false; #endif - return resolved; + resolved_symlinks_cache[input_path] = resolved; + } + return resolved_symlinks_cache[input_path]; } #endif // CAPIO_POSIX_UTILS_FILESYSTEM_HPP \ No newline at end of file diff --git a/capio-posix/utils/requests.hpp b/capio-posix/utils/requests.hpp index 1e7dd531d..55d40452b 100644 --- a/capio-posix/utils/requests.hpp +++ b/capio-posix/utils/requests.hpp @@ -113,7 +113,7 @@ inline capio_off64_t posix_directory_committed_request(const long pid, // 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); - write_request_cache_fs->flush(tid); + write_request_cache_fs->flush(path, tid, -1); char req[CAPIO_REQ_MAX_SIZE]; sprintf(req, "%04d %ld %s", CAPIO_REQUEST_CLOSE, tid, path.c_str()); buf_requests->write(req, CAPIO_REQ_MAX_SIZE); @@ -130,7 +130,6 @@ inline void create_request(const int fd, const std::filesystem::path &path, cons // non blocking inline void exit_group_request(const long tid) { START_LOG(capio_syscall(SYS_gettid), "call(tid=%ld)", tid); - write_request_cache_fs->flush(tid); char req[CAPIO_REQ_MAX_SIZE]; sprintf(req, "%04d %ld", CAPIO_REQUEST_EXIT_GROUP, tid); buf_requests->write(req, CAPIO_REQ_MAX_SIZE); @@ -140,8 +139,6 @@ inline void exit_group_request(const long tid) { [[nodiscard]] inline capio_off64_t open_request(const int fd, const std::filesystem::path &path, const long tid) { START_LOG(capio_syscall(SYS_gettid), "call(fd=%ld, path=%s, tid=%ld)", fd, path.c_str(), tid); - write_request_cache_fs->flush(tid); - char req[CAPIO_REQ_MAX_SIZE]; sprintf(req, "%04d %ld %d %s", CAPIO_REQUEST_OPEN, tid, fd, path.c_str()); buf_requests->write(req, CAPIO_REQ_MAX_SIZE); diff --git a/capio-server/src/capio-cl-engine/capio_cl_engine.cpp b/capio-server/src/capio-cl-engine/capio_cl_engine.cpp index 369e65c9f..a6415fc23 100644 --- a/capio-server/src/capio-cl-engine/capio_cl_engine.cpp +++ b/capio-server/src/capio-cl-engine/capio_cl_engine.cpp @@ -233,15 +233,27 @@ bool CapioCLEngine::isFirable(const std::string &path) { LOG("Fire rule for file %s is %s", path.c_str(), std::get<3>(itm->second).c_str()); return std::get<3>(itm->second) == CAPIO_FILE_MODE_NO_UPDATE; } + + LOG("No entry found on map. checking globs..."); + const auto is_firable = std::any_of(_locations.begin(), _locations.end(), [&](auto &itm) { + LOG("Checking against %s", itm.first.c_str()); + if (std::regex_match(path.c_str(), std::get<10>(itm.second))) { + LOG("Found match. Is Firable: %s", + std::get<3>(itm.second) == CAPIO_FILE_MODE_NO_UPDATE ? "YES" : "NO"); + return std::get<3>(itm.second) == CAPIO_FILE_MODE_NO_UPDATE; + } + return false; + }); + /* * For caching purpose, each new file is then added to the map if not found, * with its data being instantiated from the metadata of the most likely matched glob - * TODO: check overhead of this */ - LOG("No entry found on map. checking globs. Creating new file from globs"); - this->newFile((path)); + LOG("Creating new file for caching purpose..."); + this->newFile(path); + this->setFireRule(path, is_firable ? CAPIO_FILE_MODE_NO_UPDATE : CAPIO_FILE_MODE_UPDATE); LOG("Fire rule for file %s is %s", path.c_str(), std::get<3>(_locations.at((path))).c_str()); - return std::get<3>(_locations.at((path))) == CAPIO_FILE_MODE_NO_UPDATE; + return is_firable; } void CapioCLEngine::setPermanent(const std::string &path, bool value) {