Loading .gitlab-ci.yml +5 −2 Original line number Diff line number Diff line Loading @@ -62,6 +62,9 @@ gkfs: - sed -i 's/constexpr bool use_dentry_cache = false;/constexpr bool use_dentry_cache = true;/g' "${CI_PROJECT_DIR}/include/config.hpp" #- sed -i 's/constexpr auto zero_buffer_before_read = false;/constexpr auto zero_buffer_before_read = true;/g' "${CI_PROJECT_DIR}/include/config.hpp" #- sed -i 's/constexpr auto implicit_data_removal = true;/constexpr auto implicit_data_removal = false;/g' "${CI_PROJECT_DIR}/include/config.hpp" # install libfuse - apt update - apt install libfuse3-dev fuse3 # use ccache - ccache --zero-stats -M 750MiB -F 800 --evict-older-than 10d - /usr/sbin/update-ccache-symlinks Loading include/client/fuse/fuse_client.hpp +3 −182 Original line number Diff line number Diff line Loading @@ -46,8 +46,7 @@ extern "C" { #define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 12) #include <fuse3/fuse_lowlevel.h> // TODO do we really need this? Now its to replace the libc.hpp def for the // sizeof(DIR) statement // TODO do we really need this? sizeof(DIR) statement, copied from gkfs_libc.hpp struct __dirstream { int fd; // File descriptor. //__libc_lock_define (, lock) // Mutex lock for this structure. //TODO Loading Loading @@ -75,29 +74,10 @@ struct __dirstream { #include <pthread.h> #include <sys/file.h> #include <sys/xattr.h> /* We are re-using pointers to our `struct lo_inode` and `struct lo_dirp` elements as inodes. This means that we must be able to store uintptr_t values in a fuse_ino_t variable. The following incantation checks this condition at compile time. */ #if defined(__GNUC__) && \ (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && \ !defined __cplusplus _Static_assert(sizeof(fuse_ino_t) >= sizeof(uintptr_t), "fuse_ino_t too small to hold uintptr_t values!"); #else struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct { unsigned _uintptr_to_must_hold_fuse_ino_t : ((sizeof(fuse_ino_t) >= sizeof(uintptr_t)) ? 1 : -1); }; #endif #include <errno.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> #include <filesystem> #include <unordered_map> #include <string> #include <mutex> Loading @@ -117,98 +97,6 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct { #include <client/preload_context.hpp> #include <client/user_functions.hpp> static inline int do_fallocate(int fd, int mode, off_t offset, off_t length) { #ifdef HAVE_FALLOCATE if(fallocate(fd, mode, offset, length) == -1) return -errno; return 0; #else // HAVE_FALLOCATE #ifdef HAVE_POSIX_FALLOCATE if(mode == 0) return -posix_fallocate(fd, offset, length); #endif #ifdef HAVE_FSPACECTL // 0x3 == FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE if(mode == 0x3) { struct spacectl_range sr; sr.r_offset = offset; sr.r_len = length; if(fspacectl(fd, SPACECTL_DEALLOC, &sr, 0, NULL) == -1) return -errno; return 0; } #endif return -EOPNOTSUPP; #endif // HAVE_FALLOCATE } // all from the gkfs_libc enum class PathStatus { External, Internal, Error }; /** * @brief Resolves a path in the context of GekkoFS. * (Details as in original comment) */ static inline PathStatus resolve_gkfs_path(int dirfd, const char* path, std::string& resolved, int flags = 0, bool resolve_last_link = true) { const auto status = CTX->relativize_fd_path(dirfd, path, resolved, flags, resolve_last_link); switch(status) { case gkfs::preload::RelativizeStatus::internal: return PathStatus::Internal; case gkfs::preload::RelativizeStatus::fd_not_a_dir: errno = ENOTDIR; return PathStatus::Error; case gkfs::preload::RelativizeStatus::fd_unknown: errno = EBADF; return PathStatus::Error; default: // Assuming other statuses mean external or not applicable return PathStatus::External; } } #define DEBUG_INFO(...) \ do { \ if(CTX->interception_enabled()) \ LOG(DEBUG, __VA_ARGS__); \ } while(0) #define GKFS_PATH_OPERATION(name, dirfd, path, ...) \ if(CTX->interception_enabled()) { \ std::string resolved; \ switch(resolve_gkfs_path(dirfd, path, resolved)) { \ case PathStatus::Internal: \ fuse_log(FUSE_LOG_DEBUG, "[GKFS] {}(path='{}')\n", #name, \ resolved.c_str()); \ return gkfs::syscall::gkfs_##name(resolved, __VA_ARGS__); \ case PathStatus::Error: \ return -1; \ default: /* External */ \ break; \ } \ } #define GKFS_PATH_OPERATION1(name, dirfd, path) \ if(CTX->interception_enabled()) { \ std::string resolved; \ switch(resolve_gkfs_path(dirfd, path, resolved)) { \ case PathStatus::Internal: \ fuse_log(FUSE_LOG_DEBUG, "[GKFS] {}(path='{}')\n", #name, \ resolved.c_str()); \ gkfs::syscall::gkfs_##name(resolved); \ case PathStatus::Error: \ fuse_reply_err(req, -1); \ default: /* External */ \ fuse_reply_err(req, -1); \ } \ } struct GkfsDir { // Hypothetical structure that might be used if DIR is cast int fd; long int tell_pos; // for telldir/seekdir Loading @@ -216,73 +104,6 @@ struct GkfsDir { // Hypothetical structure that might be used if DIR is cast // other members libc DIR might have }; static inline std::pair<int, std::string> lol_path(int dfd, const char* path, int flags) { std::string resolved = ""; int err = 0; if(CTX->interception_enabled()) { // AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior. bool follow_link = !(flags & AT_SYMLINK_NOFOLLOW); // Path resolution needs to know if it's for lstat or stat context for // the final component. resolve_gkfs_path's `resolve_last_link` // parameter handles this. switch(resolve_gkfs_path(dfd, path, resolved, flags, follow_link)) { case PathStatus::Internal: break; case PathStatus::Error: err = -1; break; default: // External break; } } return std::make_pair(err, resolved); } static inline int lol_fstatat(int dfd, const char* path, struct stat* buf, int flags) { if(CTX->interception_enabled()) { std::string resolved; // AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior. bool follow_link = !(flags & AT_SYMLINK_NOFOLLOW); // Path resolution needs to know if it's for lstat or stat context for // the final component. resolve_gkfs_path's `resolve_last_link` // parameter handles this. switch(resolve_gkfs_path(dfd, path, resolved, flags, follow_link)) { case PathStatus::Internal: return gkfs::syscall::gkfs_stat(resolved, buf, follow_link); case PathStatus::Error: return -1; // errno set default: // External break; } } return -1; } static inline int lol_openat(int dfd, const char* path, mode_t mode, int flags) { if(CTX->interception_enabled()) { std::string resolved; // AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior. bool follow_link = !(flags & AT_SYMLINK_NOFOLLOW); // Path resolution needs to know if it's for lstat or stat context for // the final component. resolve_gkfs_path's `resolve_last_link` // parameter handles this. switch(resolve_gkfs_path(dfd, path, resolved, flags, follow_link)) { case PathStatus::Internal: fuse_log(FUSE_LOG_DEBUG, "lol_openat internal\n"); return gkfs::syscall::gkfs_open(resolved, mode, follow_link); case PathStatus::Error: return -1; // errno set default: // External break; } } return -1; } /* * Creates files on the underlying file system in response to a FUSE_MKNOD * operation Loading @@ -294,12 +115,12 @@ mknod_wrapper(int dirfd, const char* path, const char* link, int mode, int res = -1; if(S_ISREG(mode)) { res = lol_openat(dirfd, path, mode, O_CREAT | O_EXCL | O_WRONLY); //res = lol_openat(dirfd, path, mode, O_CREAT | O_EXCL | O_WRONLY); fuse_log(FUSE_LOG_DEBUG, "lol_openat internal %s\n", res); if(res >= 0) res = gkfs::syscall::gkfs_close(res); } else if(S_ISDIR(mode)) { GKFS_PATH_OPERATION(create, dirfd, path, mode | S_IFDIR) //GKFS_PATH_OPERATION(create, dirfd, path, mode | S_IFDIR) // res = gkfs::syscall::gkfs_create(resolved, mode | S_IFDIR); // res = mkdirat(dirfd, path, mode); } else if(S_ISLNK(mode) && link != NULL) { Loading src/client/fuse/fuse_client.cpp +2 −8 Original line number Diff line number Diff line Loading @@ -37,14 +37,7 @@ SPDX-License-Identifier: LGPL-3.0-or-later */ #include "client/env.hpp" #include "common/env_util.hpp" #include <cerrno> #include <client/fuse/fuse_client.hpp> #include <cstdio> #include <cstdlib> #include <dirent.h> #include <iostream> struct lo_inode { struct lo_inode* next; /* protected by lo->mutex */ Loading Loading @@ -532,7 +525,7 @@ main(int argc, char* argv[]) { int ret = -1; /* Don't mask creation mode, kernel already did that */ umask(0); umask(0); // TODO do we need this and why? pthread_mutex_init(&lo.mutex, NULL); lo.root.next = lo.root.prev = &lo.root; Loading Loading @@ -634,6 +627,7 @@ main(int argc, char* argv[]) { exit(1); } // TODO do we still want this? what do we want? fuse_log(FUSE_LOG_DEBUG, "hier 1\n"); lo.root.fd = gkfs::syscall::gkfs_open(lo.source, 755, O_PATH); if(lo.root.fd == -1) { Loading Loading
.gitlab-ci.yml +5 −2 Original line number Diff line number Diff line Loading @@ -62,6 +62,9 @@ gkfs: - sed -i 's/constexpr bool use_dentry_cache = false;/constexpr bool use_dentry_cache = true;/g' "${CI_PROJECT_DIR}/include/config.hpp" #- sed -i 's/constexpr auto zero_buffer_before_read = false;/constexpr auto zero_buffer_before_read = true;/g' "${CI_PROJECT_DIR}/include/config.hpp" #- sed -i 's/constexpr auto implicit_data_removal = true;/constexpr auto implicit_data_removal = false;/g' "${CI_PROJECT_DIR}/include/config.hpp" # install libfuse - apt update - apt install libfuse3-dev fuse3 # use ccache - ccache --zero-stats -M 750MiB -F 800 --evict-older-than 10d - /usr/sbin/update-ccache-symlinks Loading
include/client/fuse/fuse_client.hpp +3 −182 Original line number Diff line number Diff line Loading @@ -46,8 +46,7 @@ extern "C" { #define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 12) #include <fuse3/fuse_lowlevel.h> // TODO do we really need this? Now its to replace the libc.hpp def for the // sizeof(DIR) statement // TODO do we really need this? sizeof(DIR) statement, copied from gkfs_libc.hpp struct __dirstream { int fd; // File descriptor. //__libc_lock_define (, lock) // Mutex lock for this structure. //TODO Loading Loading @@ -75,29 +74,10 @@ struct __dirstream { #include <pthread.h> #include <sys/file.h> #include <sys/xattr.h> /* We are re-using pointers to our `struct lo_inode` and `struct lo_dirp` elements as inodes. This means that we must be able to store uintptr_t values in a fuse_ino_t variable. The following incantation checks this condition at compile time. */ #if defined(__GNUC__) && \ (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && \ !defined __cplusplus _Static_assert(sizeof(fuse_ino_t) >= sizeof(uintptr_t), "fuse_ino_t too small to hold uintptr_t values!"); #else struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct { unsigned _uintptr_to_must_hold_fuse_ino_t : ((sizeof(fuse_ino_t) >= sizeof(uintptr_t)) ? 1 : -1); }; #endif #include <errno.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> #include <filesystem> #include <unordered_map> #include <string> #include <mutex> Loading @@ -117,98 +97,6 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct { #include <client/preload_context.hpp> #include <client/user_functions.hpp> static inline int do_fallocate(int fd, int mode, off_t offset, off_t length) { #ifdef HAVE_FALLOCATE if(fallocate(fd, mode, offset, length) == -1) return -errno; return 0; #else // HAVE_FALLOCATE #ifdef HAVE_POSIX_FALLOCATE if(mode == 0) return -posix_fallocate(fd, offset, length); #endif #ifdef HAVE_FSPACECTL // 0x3 == FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE if(mode == 0x3) { struct spacectl_range sr; sr.r_offset = offset; sr.r_len = length; if(fspacectl(fd, SPACECTL_DEALLOC, &sr, 0, NULL) == -1) return -errno; return 0; } #endif return -EOPNOTSUPP; #endif // HAVE_FALLOCATE } // all from the gkfs_libc enum class PathStatus { External, Internal, Error }; /** * @brief Resolves a path in the context of GekkoFS. * (Details as in original comment) */ static inline PathStatus resolve_gkfs_path(int dirfd, const char* path, std::string& resolved, int flags = 0, bool resolve_last_link = true) { const auto status = CTX->relativize_fd_path(dirfd, path, resolved, flags, resolve_last_link); switch(status) { case gkfs::preload::RelativizeStatus::internal: return PathStatus::Internal; case gkfs::preload::RelativizeStatus::fd_not_a_dir: errno = ENOTDIR; return PathStatus::Error; case gkfs::preload::RelativizeStatus::fd_unknown: errno = EBADF; return PathStatus::Error; default: // Assuming other statuses mean external or not applicable return PathStatus::External; } } #define DEBUG_INFO(...) \ do { \ if(CTX->interception_enabled()) \ LOG(DEBUG, __VA_ARGS__); \ } while(0) #define GKFS_PATH_OPERATION(name, dirfd, path, ...) \ if(CTX->interception_enabled()) { \ std::string resolved; \ switch(resolve_gkfs_path(dirfd, path, resolved)) { \ case PathStatus::Internal: \ fuse_log(FUSE_LOG_DEBUG, "[GKFS] {}(path='{}')\n", #name, \ resolved.c_str()); \ return gkfs::syscall::gkfs_##name(resolved, __VA_ARGS__); \ case PathStatus::Error: \ return -1; \ default: /* External */ \ break; \ } \ } #define GKFS_PATH_OPERATION1(name, dirfd, path) \ if(CTX->interception_enabled()) { \ std::string resolved; \ switch(resolve_gkfs_path(dirfd, path, resolved)) { \ case PathStatus::Internal: \ fuse_log(FUSE_LOG_DEBUG, "[GKFS] {}(path='{}')\n", #name, \ resolved.c_str()); \ gkfs::syscall::gkfs_##name(resolved); \ case PathStatus::Error: \ fuse_reply_err(req, -1); \ default: /* External */ \ fuse_reply_err(req, -1); \ } \ } struct GkfsDir { // Hypothetical structure that might be used if DIR is cast int fd; long int tell_pos; // for telldir/seekdir Loading @@ -216,73 +104,6 @@ struct GkfsDir { // Hypothetical structure that might be used if DIR is cast // other members libc DIR might have }; static inline std::pair<int, std::string> lol_path(int dfd, const char* path, int flags) { std::string resolved = ""; int err = 0; if(CTX->interception_enabled()) { // AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior. bool follow_link = !(flags & AT_SYMLINK_NOFOLLOW); // Path resolution needs to know if it's for lstat or stat context for // the final component. resolve_gkfs_path's `resolve_last_link` // parameter handles this. switch(resolve_gkfs_path(dfd, path, resolved, flags, follow_link)) { case PathStatus::Internal: break; case PathStatus::Error: err = -1; break; default: // External break; } } return std::make_pair(err, resolved); } static inline int lol_fstatat(int dfd, const char* path, struct stat* buf, int flags) { if(CTX->interception_enabled()) { std::string resolved; // AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior. bool follow_link = !(flags & AT_SYMLINK_NOFOLLOW); // Path resolution needs to know if it's for lstat or stat context for // the final component. resolve_gkfs_path's `resolve_last_link` // parameter handles this. switch(resolve_gkfs_path(dfd, path, resolved, flags, follow_link)) { case PathStatus::Internal: return gkfs::syscall::gkfs_stat(resolved, buf, follow_link); case PathStatus::Error: return -1; // errno set default: // External break; } } return -1; } static inline int lol_openat(int dfd, const char* path, mode_t mode, int flags) { if(CTX->interception_enabled()) { std::string resolved; // AT_SYMLINK_NOFOLLOW means lstat behavior, otherwise stat behavior. bool follow_link = !(flags & AT_SYMLINK_NOFOLLOW); // Path resolution needs to know if it's for lstat or stat context for // the final component. resolve_gkfs_path's `resolve_last_link` // parameter handles this. switch(resolve_gkfs_path(dfd, path, resolved, flags, follow_link)) { case PathStatus::Internal: fuse_log(FUSE_LOG_DEBUG, "lol_openat internal\n"); return gkfs::syscall::gkfs_open(resolved, mode, follow_link); case PathStatus::Error: return -1; // errno set default: // External break; } } return -1; } /* * Creates files on the underlying file system in response to a FUSE_MKNOD * operation Loading @@ -294,12 +115,12 @@ mknod_wrapper(int dirfd, const char* path, const char* link, int mode, int res = -1; if(S_ISREG(mode)) { res = lol_openat(dirfd, path, mode, O_CREAT | O_EXCL | O_WRONLY); //res = lol_openat(dirfd, path, mode, O_CREAT | O_EXCL | O_WRONLY); fuse_log(FUSE_LOG_DEBUG, "lol_openat internal %s\n", res); if(res >= 0) res = gkfs::syscall::gkfs_close(res); } else if(S_ISDIR(mode)) { GKFS_PATH_OPERATION(create, dirfd, path, mode | S_IFDIR) //GKFS_PATH_OPERATION(create, dirfd, path, mode | S_IFDIR) // res = gkfs::syscall::gkfs_create(resolved, mode | S_IFDIR); // res = mkdirat(dirfd, path, mode); } else if(S_ISLNK(mode) && link != NULL) { Loading
src/client/fuse/fuse_client.cpp +2 −8 Original line number Diff line number Diff line Loading @@ -37,14 +37,7 @@ SPDX-License-Identifier: LGPL-3.0-or-later */ #include "client/env.hpp" #include "common/env_util.hpp" #include <cerrno> #include <client/fuse/fuse_client.hpp> #include <cstdio> #include <cstdlib> #include <dirent.h> #include <iostream> struct lo_inode { struct lo_inode* next; /* protected by lo->mutex */ Loading Loading @@ -532,7 +525,7 @@ main(int argc, char* argv[]) { int ret = -1; /* Don't mask creation mode, kernel already did that */ umask(0); umask(0); // TODO do we need this and why? pthread_mutex_init(&lo.mutex, NULL); lo.root.next = lo.root.prev = &lo.root; Loading Loading @@ -634,6 +627,7 @@ main(int argc, char* argv[]) { exit(1); } // TODO do we still want this? what do we want? fuse_log(FUSE_LOG_DEBUG, "hier 1\n"); lo.root.fd = gkfs::syscall::gkfs_open(lo.source, 755, O_PATH); if(lo.root.fd == -1) { Loading