diff --git a/CHANGELOG.md b/CHANGELOG.md index b55389c2b59d8ba47ee190304db17504ced4e48a..cfa921829567a98e2a6448d0af8de72e84911f4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed - Disabled at_parent/at_fork/at_child as it seems unneded now + - Moved some CMAKE options to config.hpp and env variables ([!285](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/285)) + - LIBGKFS/ GKFS _SYMLINK_SUPPORT, _RENAME_SUPPORT and _CREATE_CHECK_PARENTS. + - Now all the performance options are in config.hpp and env variables. ### Fixed - SYS_lstat does not exists on some architectures, change to newfstatat ([!269](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/269)) diff --git a/CMake/gkfs-options.cmake b/CMake/gkfs-options.cmake index 597a460eab38e64532cc3beed66a812abf95939a..32500a5980f2a453871485f770387f698a544c63 100644 --- a/CMake/gkfs-options.cmake +++ b/CMake/gkfs-options.cmake @@ -269,29 +269,7 @@ cmake_dependent_option(GKFS_INSTALL_TESTS "Install GekkoFS self tests" OFF "GKFS # Variables and options controlling POSIX semantics ################################################################################ -## check before create -gkfs_define_option( - GKFS_CREATE_CHECK_PARENTS - HELP_TEXT "Enable checking parent directory for existence before creating children" - DEFAULT_VALUE ON - DESCRIPTION "Verify that a parent directory exists before creating new files or directories" -) - -## symbolic link support -gkfs_define_option( - GKFS_SYMLINK_SUPPORT - HELP_TEXT "Enable support for symlinks" - DEFAULT_VALUE OFF - DESCRIPTION "Enable support for symbolic links in paths" -) -## rename support -gkfs_define_option( - GKFS_RENAME_SUPPORT - HELP_TEXT "Enable support for rename" - DEFAULT_VALUE OFF - DESCRIPTION "Compile with support for rename ops (experimental)" -) ## external link support gkfs_define_option( diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a4843f27e6b92bb7cf627778c1074dc342d1d94..ebd19b8d7bec72efaeebd0ccffbcc6b091206673 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -299,10 +299,6 @@ if (GKFS_BUILD_DOCUMENTATION) add_subdirectory(docs) endif () -if (GKFS_SYMLINK_SUPPORT) - add_definitions(-DHAS_SYMLINKS) -endif () - if (GKFS_USE_LEGACY_PATH_RESOLVE) add_definitions(-DGKFS_USE_LEGACY_PATH_RESOLVE) endif () @@ -311,13 +307,6 @@ if (GKFS_FOLLOW_EXTERNAL_SYMLINKS) add_definitions(-DGKFS_FOLLOW_EXTERNAL_SYMLINKS) endif () -if (GKFS_RENAME_SUPPORT) - # Rename depends on symlink support - add_definitions(-DHAS_SYMLINKS) - set(GKFS_SYMLINK_SUPPORT ON) - add_definitions(-DHAS_RENAME) -endif () - if (GKFS_MAX_INTERNAL_FDS) add_definitions(-DGKFS_MAX_INTERNAL_FDS=${GKFS_MAX_INTERNAL_FDS}) endif () diff --git a/CMakePresets.json b/CMakePresets.json index 9ee07c5099771f671cc08288a37843adbf00ba75..1177583438cec2e121262f91455b25b61b0f6baf 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -19,8 +19,7 @@ "GKFS_BUILD_TESTS": false, "GKFS_INSTALL_TESTS": false, "GKFS_ENABLE_CLIENT_LOG": true, - "GKFS_CLIENT_LOG_MESSAGE_SIZE": "1024", - "GKFS_SYMLINK_SUPPORT": false + "GKFS_CLIENT_LOG_MESSAGE_SIZE": "1024" }, "warnings": { "dev": true, @@ -75,9 +74,7 @@ "GKFS_BUILD_TOOLS": true, "GKFS_BUILD_TESTS": true, "GKFS_INSTALL_TESTS": true, - "GKFS_SYMLINK_SUPPORT": true, "GKFS_ENABLE_PROMETHEUS": true, - "GKFS_RENAME_SUPPORT": true, "GKFS_FOLLOW_EXTERNAL_SYMLINKS": true, "GKFS_MAX_OPEN_FDS": "10000", "GKFS_MAX_INTERNAL_FDS": "1024" diff --git a/README.md b/README.md index e78670a3450b33b0cace675f11219e44528c6a09..c48f77ceada2abd8da06c6f2930f15a8d05417e5 100644 --- a/README.md +++ b/README.md @@ -577,11 +577,8 @@ Once it is enabled, `--dbbackend` option will be functional. #### Core - `GKFS_BUILD_TOOLS` - Build tools (default: OFF) - `GKFS_BUILD_TESTS` - Build tests (default: OFF) -- `GKFS_CREATE_CHECK_PARENTS` - Enable checking parent directory for existence before creating children (default: ON) - `GKFS_MAX_INTERNAL_FDS` - Number of file descriptors reserved for internal use (default: 256) - `GKFS_MAX_OPEN_FDS` - Maximum number of open file descriptors supported (default: 1024) -- `GKFS_SYMLINK_SUPPORT` - Enable support for rename (default: OFF) -- `GKFS_RENAME_SUPPORT` - Enable support for rename (default: OFF) - `GKFS_FOLLOW_EXTERNAL_SYMLINKS` - Enable support for following external links into the GekkoFS namespace (default: OFF) - `GKFS_USE_LEGACY_PATH_RESOLVE` - Use the legacy implementation of the resolve function, deprecated (default: OFF) - `GKFS_USE_GUIDED_DISTRIBUTION` - Use guided data distributor (default: OFF) @@ -607,6 +604,9 @@ The GekkoFS daemon, client, and proxy support a number of environment variables ### Client #### Core - `LIBGKFS_HOSTS_FILE` - Path to the hostsfile (created by the daemon and mandatory for the client). +- `LIBGKFS_CREATE_CHECK_PARENTS` - Enable checking parent directory for existence before creating children. +- `LIBGKFS_SYMLINK_SUPPORT` - Enable support for symbolic links. +- `LIBGKFS_RENAME_SUPPORT` - Enable support for rename. #### Logging - `LIBGKFS_LOG` - Log module of the client. Available modules are: `none`, `syscalls`, `syscalls_at_entry`, `info`, `critical`, `errors`, `warnings`, `mercury`, `debug`, `most`, `all`, `trace_reads`, `help`. @@ -660,6 +660,10 @@ Using two environment variables - `LIBGKFS_PROTECT_FILES_CONSUMER=1` enables the application as consumer, so a open will wait until the .lockgekko dissapears. The wait is limited to ~40 seconds. ### Daemon +#### Core +- `GKFS_DAEMON_CREATE_CHECK_PARENTS` - Enable checking parent directory for existence before creating children. +- `GKFS_DAEMON_SYMLINK_SUPPORT` - Enable support for symbolic links. +- `GKFS_DAEMON_RENAME_SUPPORT` - Enable support for rename. #### Logging - `GKFS_DAEMON_LOG_PATH` - Path to the log file of the daemon. - `GKFS_DAEMON_LOG_LEVEL` - Log level of the daemon. Available levels are: `off`, `critical`, `err`, `warn`, `info`, `debug`, `trace`. diff --git a/include/client/env.hpp b/include/client/env.hpp index 2555b67d809f44dcc6b57e40145fe9414173897f..279640976eff3c77ac138e824a879d0564f4b848 100644 --- a/include/client/env.hpp +++ b/include/client/env.hpp @@ -87,6 +87,14 @@ static constexpr auto WRITE_SIZE_THRESHOLD = ADD_PREFIX("WRITE_SIZE_CACHE_THRESHOLD"); } // namespace cache +static constexpr auto CREATE_CHECK_PARENTS = ADD_PREFIX("CREATE_CHECK_PARENTS"); +static constexpr auto SYMLINK_SUPPORT = ADD_PREFIX("SYMLINK_SUPPORT"); +static constexpr auto RENAME_SUPPORT = ADD_PREFIX("RENAME_SUPPORT"); +static constexpr auto USE_INLINE_DATA = ADD_PREFIX("USE_INLINE_DATA"); +static constexpr auto CREATE_WRITE_OPTIMIZATION = + ADD_PREFIX("CREATE_WRITE_OPTIMIZATION"); +static constexpr auto READ_INLINE_PREFETCH = ADD_PREFIX("READ_INLINE_PREFETCH"); + } // namespace gkfs::env #undef ADD_PREFIX diff --git a/include/client/gkfs_functions.hpp b/include/client/gkfs_functions.hpp index 1faf1064fe15c13c93b8b7da8165f584ef53b55c..b1056c7c272ce73f9cfbc81e14a7fc39d1de13db 100644 --- a/include/client/gkfs_functions.hpp +++ b/include/client/gkfs_functions.hpp @@ -108,16 +108,12 @@ gkfs_dup(int oldfd); int gkfs_dup2(int oldfd, int newfd); -#ifdef HAS_SYMLINKS - int gkfs_mk_symlink(const std::string& path, const std::string& target_path); int gkfs_readlink(const std::string& path, char* buf, int bufsize); -#endif - ssize_t gkfs_do_write(gkfs::filemap::OpenFile& file, const char* buf, size_t count, off64_t offset, bool update_pos); @@ -180,10 +176,8 @@ gkfs_close(unsigned int fd); std::vector gkfs_get_file_list(const std::string& path); -#ifdef HAS_RENAME int gkfs_rename(const std::string& old_path, const std::string& new_path); -#endif // HAS_RENAME int gkfs_utimensat(const std::string& path, const struct timespec times[2]); diff --git a/include/client/gkfs_libc.hpp b/include/client/gkfs_libc.hpp index 8543538eb99a5103ea108f64e381f362c0350ad1..28763c5184a6d0954094def5cc616d73c77a74ae 100644 --- a/include/client/gkfs_libc.hpp +++ b/include/client/gkfs_libc.hpp @@ -220,12 +220,10 @@ symlink(const char* target_path, int symlinkat(const char* target_path, int newdirfd, const char* link_path) throw(); -#ifdef HAS_SYMLINKS ssize_t readlink(const char* path, char* buf, size_t bufsize); ssize_t readlinkat(int dfd, const char* path, char* buf, size_t bufsize); -#endif char* realpath(const char* path, char* resolved_path) throw(); diff --git a/include/client/rpc/forward_metadata.hpp b/include/client/rpc/forward_metadata.hpp index eaa816d21e65ca5f64dea5914461ecc6ee5f0bdd..e26b25c2d982885c3ff4d47bb682713b8fb8ea9d 100644 --- a/include/client/rpc/forward_metadata.hpp +++ b/include/client/rpc/forward_metadata.hpp @@ -72,11 +72,9 @@ int forward_stat(const std::string& path, std::string& attr, std::string& inline_data, int copy, bool include_inline = false); -#ifdef HAS_RENAME int forward_rename(const std::string& oldpath, const std::string& newpath, const gkfs::metadata::Metadata& md); -#endif // HAS_RENAME int forward_remove(const std::string& path, bool rm_dir, const int8_t num_copies); @@ -107,13 +105,9 @@ forward_get_dirents_single(const std::string& path, int server, const std::string& start_key = "", bool get_all = true); -#ifdef HAS_SYMLINKS - int forward_mk_symlink(const std::string& path, const std::string& target_path); -#endif - /** * @brief Send an RPC request to write a small amount of data directly * to the metadata server (inline). diff --git a/include/client/user_functions.hpp b/include/client/user_functions.hpp index 5df0b771075ef8a94d20a0386975c24161b1362f..29ab4a3240ddd6ea8f920b7a4ae7ca5c6c02135c 100644 --- a/include/client/user_functions.hpp +++ b/include/client/user_functions.hpp @@ -132,16 +132,13 @@ gkfs_getdents64(unsigned int fd, struct linux_dirent64* dirp, int gkfs_truncate(const std::string& path, off_t offset); -#ifdef HAS_SYMLINKS int gkfs_mk_symlink(const std::string& path, const std::string& target); int gkfs_readlink(const std::string& path, char* buf, int bufsize); -#endif -#ifdef HAS_RENAME + int gkfs_rename(const std::string& old_path, const std::string& new_path); -#endif int gkfs_fsync(unsigned int fd); diff --git a/include/common/cmake_configure.hpp.in b/include/common/cmake_configure.hpp.in index 9d7cb25cdc39ac63784ed34bbbb314d76f263077..5d6d3e270ec7a630e1a8898d3a777578fbd8426b 100644 --- a/include/common/cmake_configure.hpp.in +++ b/include/common/cmake_configure.hpp.in @@ -23,7 +23,7 @@ #ifndef GKFS_CMAKE_CONFIGURE_HPP #define GKFS_CMAKE_CONFIGURE_HPP -#cmakedefine01 GKFS_CREATE_CHECK_PARENTS + #cmakedefine01 LOG_SYSCALLS #cmakedefine GKFS_USE_GUIDED_DISTRIBUTION #define GKFS_USE_GUIDED_DISTRIBUTION_PATH "@GKFS_USE_GUIDED_DISTRIBUTION_PATH@" diff --git a/include/common/common_defs.hpp b/include/common/common_defs.hpp index 682fb58e70212c0d79a79ec584bb0ad4efff5b18..edde5cc5487f2b8e3c1998919be2b09ce04724fe 100644 --- a/include/common/common_defs.hpp +++ b/include/common/common_defs.hpp @@ -70,12 +70,8 @@ constexpr auto update_metadentry_size = "rpc_srv_update_metadentry_size"; constexpr auto get_dirents = "rpc_srv_get_dirents"; constexpr auto get_dirents_extended = "rpc_srv_get_dirents_extended"; constexpr auto get_dirents_filtered = "rpc_srv_get_dirents_filtered"; -#ifdef HAS_SYMLINKS constexpr auto mk_symlink = "rpc_srv_mk_symlink"; -#endif -#ifdef HAS_RENAME constexpr auto rename = "rpc_srv_rename"; -#endif constexpr auto write = "rpc_srv_write_data"; constexpr auto read = "rpc_srv_read_data"; diff --git a/include/common/metadata.hpp b/include/common/metadata.hpp index 4fbadd24cea57e58cf1b90f54e77ccb5cc50c694..75396aa855f31e8670802835250793609cf2d659 100644 --- a/include/common/metadata.hpp +++ b/include/common/metadata.hpp @@ -67,13 +67,9 @@ private: nlink_t link_count_{}; // number of names for this inode (hardlinks) size_t size_{}; // size_ in bytes, might be computed instead of stored blkcnt_t blocks_{}; // allocated file system blocks_ -#ifdef HAS_SYMLINKS std::string target_path_; // For links this is the path of the target file -#ifdef HAS_RENAME std::string rename_path_; // In some cases fd is maintained so we need the // renamed path -#endif -#endif std::string inline_data_; void init_time(); @@ -83,16 +79,10 @@ public: explicit Metadata(mode_t mode); -#ifdef HAS_SYMLINKS - Metadata(mode_t mode, const std::string& target_path); -#ifdef HAS_RENAME Metadata(mode_t mode, const std::string& target_path, const std::string& rename_path); -#endif - -#endif // Construct from a binary representation of the object explicit Metadata(const std::string& binary_str); @@ -150,8 +140,6 @@ public: void blocks(blkcnt_t blocks_); -#ifdef HAS_SYMLINKS - std::string target_path() const; @@ -161,15 +149,11 @@ public: bool is_link() const; -#ifdef HAS_RENAME std::string rename_path() const; void rename_path(const std::string& rename_path); -#endif // HAS_RENAME - -#endif // HAS_SYMLINKS std::string inline_data() const; diff --git a/include/common/rpc/rpc_types_thallium.hpp b/include/common/rpc/rpc_types_thallium.hpp index 8bb91713f3a4255dc14f03b55589d71079a11783..433d1dbaf9a56cd97497791dcc176bdafd3a5a85 100644 --- a/include/common/rpc/rpc_types_thallium.hpp +++ b/include/common/rpc/rpc_types_thallium.hpp @@ -204,7 +204,6 @@ struct rpc_get_metadentry_size_out_t { } }; -#ifdef HAS_SYMLINKS struct rpc_mk_symlink_in_t { std::string path; std::string target_path; @@ -215,9 +214,7 @@ struct rpc_mk_symlink_in_t { ar(path, target_path); } }; -#endif -#ifdef HAS_RENAME struct rpc_rename_in_t { std::string path; std::string target_path; @@ -229,7 +226,6 @@ struct rpc_rename_in_t { ar(path, target_path, renamed_stub); } }; -#endif // data struct rpc_read_data_in_t { diff --git a/include/config.hpp b/include/config.hpp index 3ce43ff6292f1e720040a9cdb35f130bf9b9f3f5..1eac9404082dfdb5a4e06136342ff9b3924e069e 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -114,14 +114,10 @@ constexpr auto dir = "metadata"; // which metadata should be considered apart from size and mode // Blocks are used to store the rename status (-1 is a renamed file) constexpr auto use_atime = false; -constexpr auto use_ctime = false; +constexpr auto use_ctime = true; constexpr auto use_mtime = false; constexpr auto use_link_cnt = false; -#ifdef HAS_RENAME constexpr auto use_blocks = true; -#else -constexpr auto use_blocks = false; -#endif // HAS_RENAME /* * If true, all chunks on the same host are removed during a metadata remove * rpc. This is a technical optimization that reduces the number of RPCs for @@ -134,6 +130,13 @@ constexpr auto implicit_data_removal = true; // Check for existence of file metadata before create. This done on RocksDB // level constexpr auto create_exist_check = true; +// Verify that a parent directory exists before creating new files or +// directories +inline bool create_check_parents = true; +// Enable support for symbolic links in paths +inline bool symlink_support = true; +inline bool rename_support = true; + // Use inline data for small files // Use inline data for small files inline bool use_inline_data = true; diff --git a/include/daemon/env.hpp b/include/daemon/env.hpp index 827809425089254e1f6fe041bade21b6749b369a..4e141a5283c46e83239d391d607b9c9520351573 100644 --- a/include/daemon/env.hpp +++ b/include/daemon/env.hpp @@ -54,6 +54,14 @@ static constexpr auto METADATA_DB_PATH = ADD_PREFIX("METADATA_DB_PATH"); static constexpr auto USE_DIRENTS_COMPRESSION = ADD_PREFIX("DAEMON_USE_DIRENTS_COMPRESSION"); static constexpr auto HOSTS_FILE = ADD_PREFIX("HOSTS_FILE"); +static constexpr auto DAEMON_CREATE_CHECK_PARENTS = + ADD_PREFIX("DAEMON_CREATE_CHECK_PARENTS"); +static constexpr auto DAEMON_SYMLINK_SUPPORT = + ADD_PREFIX("DAEMON_SYMLINK_SUPPORT"); +static constexpr auto DAEMON_RENAME_SUPPORT = + ADD_PREFIX("DAEMON_RENAME_SUPPORT"); +static constexpr auto DAEMON_USE_INLINE_DATA = + ADD_PREFIX("DAEMON_USE_INLINE_DATA"); } // namespace gkfs::env diff --git a/include/daemon/handler/rpc_defs.hpp b/include/daemon/handler/rpc_defs.hpp index e54490af657b1f583749847fcd1456fe8f9f835f..d5c19e2b776dc450463fd89439808217156d57a1 100644 --- a/include/daemon/handler/rpc_defs.hpp +++ b/include/daemon/handler/rpc_defs.hpp @@ -89,15 +89,12 @@ rpc_srv_get_dirents_filtered( const std::shared_ptr& engine, const tl::request& req, const gkfs::rpc::rpc_get_dirents_filtered_in_t& in); -#ifdef HAS_SYMLINKS void rpc_srv_mk_symlink(const tl::request& req, const gkfs::rpc::rpc_mk_symlink_in_t& in); -#endif -#ifdef HAS_RENAME + void rpc_srv_rename(const tl::request& req, const gkfs::rpc::rpc_rename_in_t& in); -#endif // data void diff --git a/src/client/fuse/fuse_client.cpp b/src/client/fuse/fuse_client.cpp index 23f592b077a41fd1d400115ee05edfe519a5ff3f..6470233290a1d274e2600a163371f516ad882c2b 100644 --- a/src/client/fuse/fuse_client.cpp +++ b/src/client/fuse/fuse_client.cpp @@ -645,7 +645,7 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, static void statfs_handler(fuse_req_t req, fuse_ino_t ino) { auto* ud = udata(req); - DEBUG_INFO(ud, "statfs handler ino %u", ino); + DEBUG_INFO(ud, "statfs handler ino %lu", ino); struct statfs stfs{}; int rc = gkfs::syscall::gkfs_statfs(&stfs); if(rc < 0) { @@ -928,7 +928,10 @@ rmdir_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { static void readlink_handler(fuse_req_t req, fuse_ino_t ino) { -#ifdef HAS_SYMLINKS + if(!gkfs::config::metadata::symlink_support) { + fuse_reply_err(req, ENOTSUP); + return; + } auto* inode = get_inode(ino); if(!inode) { fuse_reply_err(req, ENOENT); @@ -942,15 +945,15 @@ readlink_handler(fuse_req_t req, fuse_ino_t ino) { } link[rc] = '\0'; fuse_reply_readlink(req, link); -#else - fuse_reply_err(req, ENOTSUP); -#endif } static void symlink_handler(fuse_req_t req, const char* linkname, fuse_ino_t parent, const char* name) { -#ifdef HAS_SYMLINKS + if(!gkfs::config::metadata::symlink_support) { + fuse_reply_err(req, ENOTSUP); + return; + } auto* ud = udata(req); auto* parent_inode = get_inode(parent); if(!parent_inode) { @@ -986,9 +989,6 @@ symlink_handler(fuse_req_t req, const char* linkname, fuse_ino_t parent, e.attr.st_size = strlen(target.c_str()); // DEBUG_INFO(ud, "stat mode %i, iflink %i", e.attr.st_mode, S_IFLNK); fuse_reply_entry(req, &e); -#else - fuse_reply_err(req, ENOTSUP); -#endif } static void @@ -996,7 +996,10 @@ rename_handler(fuse_req_t req, fuse_ino_t old_parent, const char* old_name, fuse_ino_t new_parent, const char* new_name, unsigned int flags) { -#ifdef HAS_RENAME + if(!gkfs::config::metadata::rename_support) { + fuse_reply_err(req, ENOTSUP); + return; + } auto* old_parent_inode = get_inode(old_parent); if(!old_parent_inode) { fuse_reply_err(req, ENOENT); @@ -1071,9 +1074,6 @@ rename_handler(fuse_req_t req, fuse_ino_t old_parent, const char* old_name, } fuse_reply_err(req, 0); -#else - fuse_reply_err(req, ENOTSUP); -#endif } void diff --git a/src/client/gkfs_libc.cpp b/src/client/gkfs_libc.cpp index 59b0dc68af6a50e71ecf6e294e826d67ee5319de..434e991f213e00196e1d2395cbb337a93aba33a9 100644 --- a/src/client/gkfs_libc.cpp +++ b/src/client/gkfs_libc.cpp @@ -1747,12 +1747,12 @@ rename(const char* oldpath, const char* newpath) throw() { new_status == PathStatus::Internal) { DEBUG_INFO("[GKFS] rename(old='{}', new='{}')", resolved_old, resolved_new); -#ifdef HAS_RENAME - return gkfs::syscall::gkfs_rename(resolved_old, resolved_new); -#else - errno = ENOTSUP; - return -1; -#endif + if(gkfs::config::metadata::rename_support) { + return gkfs::syscall::gkfs_rename(resolved_old, resolved_new); + } else { + errno = ENOTSUP; + return -1; + } } // Cross-filesystem/scope renames if(old_status == PathStatus::Internal || @@ -1785,14 +1785,14 @@ renameat(int olddirfd, const char* oldpath, int newdirfd, new_status == PathStatus::Internal) { DEBUG_INFO("[GKFS] renameat(old='{}', new='{}')", resolved_old, resolved_new); -#ifdef HAS_RENAME - return gkfs::syscall::gkfs_rename( - resolved_old, - resolved_new); // Assuming gkfs_rename handles this -#else - errno = ENOTSUP; - return -1; -#endif + if(gkfs::config::metadata::rename_support) { + return gkfs::syscall::gkfs_rename( + resolved_old, + resolved_new); // Assuming gkfs_rename handles this + } else { + errno = ENOTSUP; + return -1; + } } if(old_status == PathStatus::Internal || new_status == PathStatus::Internal) { @@ -1823,21 +1823,23 @@ renameat2(int olddirfd, const char* oldpath, int newdirfd, const char* newpath, new_status == PathStatus::Internal) { DEBUG_INFO("[GKFS] renameat2(old='{}', new='{}', flags={})", resolved_old, resolved_new, flags); -#ifdef HAS_RENAME - // gkfs_rename might need to be enhanced to gkfs_renameat2 to handle - // flags - if(flags == 0) { // Simple rename - return gkfs::syscall::gkfs_rename(resolved_old, resolved_new); + if(gkfs::config::metadata::rename_support) { + // gkfs_rename might need to be enhanced to gkfs_renameat2 to + // handle flags + if(flags == 0) { // Simple rename + return gkfs::syscall::gkfs_rename(resolved_old, + resolved_new); + } else { + DEBUG_INFO( + "[GKFS] renameat2 flags not fully supported by GekkoFS."); + errno = ENOTSUP; // Or EINVAL if flags are + // unknown/unsupported + return -1; + } } else { - DEBUG_INFO( - "[GKFS] renameat2 flags not fully supported by GekkoFS."); - errno = ENOTSUP; // Or EINVAL if flags are unknown/unsupported + errno = ENOTSUP; return -1; } -#else - errno = ENOTSUP; - return -1; -#endif } if(old_status == PathStatus::Internal || new_status == PathStatus::Internal) { @@ -1864,14 +1866,14 @@ symlink(const char* path1, const char* path2) throw() { if(resolve_gkfs_path(AT_FDCWD, path2, resolved2) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 2 internal {}", resolved2); -#ifdef HAS_SYMLINKS - // In Gekko we invert the parameters. - return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); -#else - DEBUG_INFO("[GKFS] symlinks not supported/compiled"); - errno = ENOTSUP; - return -1; -#endif + if(gkfs::config::metadata::symlink_support) { + // In Gekko we invert the parameters. + return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); + } else { + DEBUG_INFO("[GKFS] symlinks not supported/compiled"); + errno = ENOTSUP; + return -1; + } } } } @@ -1891,21 +1893,20 @@ symlinkat(const char* path1, int newdirfd, const char* path2) throw() { if(resolve_gkfs_path(newdirfd, path2, resolved2) == PathStatus::Internal) { DEBUG_INFO("[GKFS] path 2 internal {}", resolved2); -#ifdef HAS_SYMLINKS - // In Gekko we invert the parameters. - return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); -#else - DEBUG_INFO("[GKFS] symlinks not supported/compiled"); - errno = ENOTSUP; - return -1; -#endif + if(gkfs::config::metadata::symlink_support) { + // In Gekko we invert the parameters. + return gkfs::syscall::gkfs_mk_symlink(resolved2, resolved); + } else { + DEBUG_INFO("[GKFS] symlinks not supported/compiled"); + errno = ENOTSUP; + return -1; + } } } } GKFS_FALLBACK(symlinkat, path1, newdirfd, path2); } -#ifdef HAS_SYMLINKS ssize_t readlink(const char* path, char* buf, size_t bufsize) { gkfs_init_routine_placeholder(); @@ -1914,9 +1915,7 @@ readlink(const char* path, char* buf, size_t bufsize) { bufsize) // Pass AT_FDCWD, path, buf, bufsize GKFS_FALLBACK(readlink, path, buf, bufsize); } -#endif -#ifdef HAS_SYMLINKS ssize_t readlinkat(int dfd, const char* path, char* buf, size_t bufsize) { gkfs_init_routine_placeholder(); @@ -1926,7 +1925,6 @@ readlinkat(int dfd, const char* path, char* buf, size_t bufsize) { GKFS_FALLBACK(readlinkat, dfd, path, buf, bufsize); } -#endif char* realpath(const char* path, char* resolved_path) throw() { diff --git a/src/client/gkfs_metadata.cpp b/src/client/gkfs_metadata.cpp index 5be1ab7879f8734363af07757b9a2c4e2992a8a6..13b71fa84413df5516b4b982b3a6dea792de474d 100644 --- a/src/client/gkfs_metadata.cpp +++ b/src/client/gkfs_metadata.cpp @@ -100,24 +100,25 @@ namespace { */ int check_parent_dir(const std::string& path) { -#if GKFS_CREATE_CHECK_PARENTS - auto p_comp = gkfs::path::dirname(path); - auto md = gkfs::utils::get_metadata(p_comp); - if(!md) { - if(errno == ENOENT) { - LOG(DEBUG, "Parent component does not exist: '{}'", p_comp); - } else { - LOG(ERROR, "Failed to get metadata for parent component '{}': {}", - path, strerror(errno)); + if(gkfs::config::metadata::create_check_parents) { + auto p_comp = gkfs::path::dirname(path); + auto md = gkfs::utils::get_metadata(p_comp); + if(!md) { + if(errno == ENOENT) { + LOG(DEBUG, "Parent component does not exist: '{}'", p_comp); + } else { + LOG(ERROR, + "Failed to get metadata for parent component '{}': {}", + path, strerror(errno)); + } + return -1; + } + if(!S_ISDIR(md->mode())) { + LOG(DEBUG, "Parent component is not a directory: '{}'", p_comp); + errno = ENOTDIR; + return -1; } - return -1; - } - if(!S_ISDIR(md->mode())) { - LOG(DEBUG, "Parent component is not a directory: '{}'", p_comp); - errno = ENOTDIR; - return -1; } -#endif // GKFS_CREATE_CHECK_PARENTS return 0; } @@ -244,15 +245,14 @@ gkfs_open(const std::string& path, mode_t mode, int flags) { return -1; } md = *md_; -#ifdef HAS_RENAME // This is an old file that was renamed which we do not open - if(md.blocks() == -1) { + if(gkfs::config::metadata::rename_support && + md.blocks() == -1) { LOG(DEBUG, "This file was renamed and we do not open. path '{}'", path); return -1; } -#endif // HAS_RENAME } else { LOG(ERROR, "Error creating file: '{}'", strerror(errno)); return -1; @@ -281,8 +281,7 @@ gkfs_open(const std::string& path, mode_t mode, int flags) { } -#ifdef HAS_SYMLINKS - if(md.is_link()) { + if(gkfs::config::metadata::symlink_support && md.is_link()) { if(flags & O_NOFOLLOW) { LOG(WARNING, "Symlink found and O_NOFOLLOW flag was specified"); errno = ELOOP; @@ -290,52 +289,53 @@ gkfs_open(const std::string& path, mode_t mode, int flags) { } return gkfs_open(md.target_path(), mode, flags); } -#ifdef HAS_RENAME - - if(md.blocks() == -1) { - // This is an old file that was renamed and essentially no longer exists - errno = ENOENT; - return -1; - } else { - if(!md.target_path().empty()) { - // get renamed path from target and retrieve metadata from it - auto md_ = gkfs::utils::get_metadata( - md.target_path(), false, - gkfs::config::metadata::read_inline_prefetch); - auto new_path = md.target_path(); - while(!md_.value().target_path().empty() and - md_.value().blocks() != -1) { - new_path = md_.value().target_path(); - md_ = gkfs::utils::get_metadata( - md_.value().target_path(), false, + if(gkfs::config::metadata::rename_support) { + if(md.blocks() == -1) { + // This is an old file that was renamed and essentially no longer + // exists + errno = ENOENT; + return -1; + } else { + if(!md.target_path().empty()) { + // get renamed path from target and retrieve metadata from it + auto md_ = gkfs::utils::get_metadata( + md.target_path(), false, gkfs::config::metadata::read_inline_prefetch); - if(!md_) { - return -1; + auto new_path = md.target_path(); + while(!md_.value().target_path().empty() and + md_.value().blocks() != -1) { + new_path = md_.value().target_path(); + md_ = gkfs::utils::get_metadata( + md_.value().target_path(), false, + gkfs::config::metadata::read_inline_prefetch); + if(!md_) { + return -1; + } + } + md = *md_; + if(S_ISDIR(md.mode())) { + return gkfs_opendir(new_path); } - } - md = *md_; - if(S_ISDIR(md.mode())) { - return gkfs_opendir(new_path); - } - /*** Regular file exists ***/ - assert(S_ISREG(md.mode())); + /*** Regular file exists ***/ + assert(S_ISREG(md.mode())); - if((flags & O_TRUNC) && ((flags & O_RDWR) || (flags & O_WRONLY))) { - if(gkfs_truncate(new_path, md.size(), 0)) { - LOG(ERROR, "Error truncating file"); - return -1; + if((flags & O_TRUNC) && + ((flags & O_RDWR) || (flags & O_WRONLY))) { + if(gkfs_truncate(new_path, md.size(), 0)) { + LOG(ERROR, "Error truncating file"); + return -1; + } + md.size(0); + md.inline_data(""); } - md.size(0); - md.inline_data(""); + // RENAMED OR SYMLINK NOT PROTECTED + return CTX->file_map()->add( + std::make_shared(new_path, + flags)); } - // RENAMED OR SYMLINK NOT PROTECTED - return CTX->file_map()->add( - std::make_shared(new_path, flags)); } } -#endif // HAS_RENAME -#endif // HAS_SYMLINKS if(S_ISDIR(md.mode())) { return gkfs_opendir(path); } @@ -385,9 +385,13 @@ gkfs_create(const std::string& path, mode_t mode) { case 0: mode |= S_IFREG; break; -#ifdef HAS_SYMLINKS - case S_IFLNK: -#endif + case S_IFLNK: // add symlink case + if(!gkfs::config::metadata::symlink_support) { + LOG(WARNING, "Symlink not supported"); + errno = ENOTSUP; + return -1; + } + break; case S_IFREG: // intentionally fall-through case S_IFDIR: break; @@ -462,45 +466,46 @@ gkfs_libcremove(const std::string& path) { int gkfs_remove(const std::string& path) { -#ifdef HAS_RENAME - auto md = gkfs::utils::get_metadata(path); - if(!md) { - return -1; - } + if(gkfs::config::metadata::rename_support) { + auto md = gkfs::utils::get_metadata(path); + if(!md) { + return -1; + } - if(S_ISDIR(md->mode())) { - LOG(ERROR, "Cannot remove directory '{}'", path); - errno = EISDIR; - return -1; - } + if(S_ISDIR(md->mode())) { + LOG(ERROR, "Cannot remove directory '{}'", path); + errno = EISDIR; + return -1; + } - if(md.value().blocks() == -1) { - errno = ENOENT; - return -1; - } else { - if(!md->is_link()) { - if(!md.value().target_path().empty()) { - auto md_ = gkfs::utils::get_metadata(md.value().target_path()); - std::string new_path = md.value().target_path(); - while(!md.value().target_path().empty() and - md.value().blocks() != -1) { - new_path = md.value().target_path(); - md = gkfs::utils::get_metadata(md.value().target_path(), - false); - if(!md) { + if(md.value().blocks() == -1) { + errno = ENOENT; + return -1; + } else { + if(!md->is_link()) { + if(!md.value().target_path().empty()) { + auto md_ = + gkfs::utils::get_metadata(md.value().target_path()); + std::string new_path = md.value().target_path(); + while(!md.value().target_path().empty() and + md.value().blocks() != -1) { + new_path = md.value().target_path(); + md = gkfs::utils::get_metadata(md.value().target_path(), + false); + if(!md) { + return -1; + } + } + auto err = gkfs::rpc::forward_remove(new_path, false, + CTX->get_replicas()); + if(err) { + errno = err; return -1; } } - auto err = gkfs::rpc::forward_remove(new_path, false, - CTX->get_replicas()); - if(err) { - errno = err; - return -1; - } } } } -#endif // HAS_RENAME int err = 0; if(gkfs::config::proxy::fwd_remove && CTX->use_proxy()) { @@ -531,43 +536,33 @@ gkfs_access(const std::string& path, const int mask, bool follow_links) { return -1; } -#ifdef HAS_RENAME - LOG(DEBUG, "Checking for renamed file '{}'", path); - if(md.value().blocks() == -1) { - errno = ENOENT; - LOG(DEBUG, "File exist but it is renamed '{}'", path); - return -1; + if(gkfs::config::metadata::rename_support) { + LOG(DEBUG, "Checking for renamed file '{}'", path); + if(md.value().blocks() == -1) { + errno = ENOENT; + LOG(DEBUG, "File exist but it is renamed '{}'", path); + return -1; - } else { + } else { - while(!md.value().target_path().empty() and md.value().blocks() != -1) { - LOG(DEBUG, "File exist but it is renamed '{} -> {}'", path, - md.value().target_path()); - md = gkfs::utils::get_metadata(md.value().target_path(), false); - if(!md) { - LOG(DEBUG, "File does not exist but it is renamed '{} -> {}'", - path, md.value().target_path()); - return -1; + while(!md.value().target_path().empty() and + md.value().blocks() != -1) { + LOG(DEBUG, "File exist but it is renamed '{} -> {}'", path, + md.value().target_path()); + md = gkfs::utils::get_metadata(md.value().target_path(), false); + if(!md) { + LOG(DEBUG, + "File does not exist but it is renamed '{} -> {}'", + path, md.value().target_path()); + return -1; + } } } } -#endif // HAS_RENAME return 0; } -#ifdef HAS_RENAME -/** - * gkfs wrapper for rename() system calls - * errno may be set - * We use blocks to determine if the file is a renamed file. - * If the file is re-renamed (a->b->a) a recovers the block of b - * and we delete b. - * There is no support for replication in rename - * @param old_path - * @param new_path - * @return 0 on success, -1 on failure - */ int gkfs_rename(const string& old_path, const string& new_path) { auto md_old = gkfs::utils::get_metadata(old_path, false); @@ -656,7 +651,6 @@ gkfs_rename(const string& old_path, const string& new_path) { fprintf(stderr, "GKFS_RENAME: success returning 0\n"); return 0; } -#endif /** @@ -683,30 +677,31 @@ gkfs_stat(const string& path, struct stat* buf, bool follow_links, } std::string new_path = path; -#ifdef HAS_RENAME - if(md->is_link() == false) { - if(md.value().blocks() == -1) { - // This may not be correct in the case of fstat, - // then we will check bypass_rename - if(!bypass_rename) { - errno = ENOENT; - return -1; - } - } else { - while(!md.value().target_path().empty() and - md.value().blocks() != -1) { - new_path = md.value().target_path(); - md = gkfs::utils::get_metadata(md.value().target_path(), false); - - if(!md) { + if(gkfs::config::metadata::rename_support) { + if(md->is_link() == false) { + if(md.value().blocks() == -1) { + // This may not be correct in the case of fstat, + // then we will check bypass_rename + if(!bypass_rename) { + errno = ENOENT; return -1; } + } else { + while(!md.value().target_path().empty() and + md.value().blocks() != -1) { + new_path = md.value().target_path(); + md = gkfs::utils::get_metadata(md.value().target_path(), + false); + + if(!md) { + return -1; + } + } + if(md.value().blocks() == -1) + md.value().blocks(md->size() / 4096); } - if(md.value().blocks() == -1) - md.value().blocks(md->size() / 4096); } } -#endif // Stat should use new_path in order that the inode of a renamed file is // equal to the original gkfs::utils::metadata_to_stat(new_path, *md, *buf); @@ -741,25 +736,26 @@ gkfs_statx(int dirfs, const std::string& path, int flags, unsigned int mask, return -1; } -#ifdef HAS_RENAME - if(md->is_link() == false) { - if(md.value().blocks() == -1) { - errno = ENOENT; - return -1; - } else { - while(!md.value().target_path().empty() and - md.value().blocks() != -1) { - md = gkfs::utils::get_metadata(md.value().target_path(), false); + if(gkfs::config::metadata::rename_support) { + if(md->is_link() == false) { + if(md.value().blocks() == -1) { + errno = ENOENT; + return -1; + } else { + while(!md.value().target_path().empty() and + md.value().blocks() != -1) { + md = gkfs::utils::get_metadata(md.value().target_path(), + false); - if(!md) { - return -1; + if(!md) { + return -1; + } } + if(md.value().blocks() == -1) + md.value().blocks(md->size() / 4096); } - if(md.value().blocks() == -1) - md.value().blocks(md->size() / 4096); } } -#endif struct stat tmp{}; @@ -1038,32 +1034,32 @@ gkfs_truncate(const std::string& path, off_t length) { // If rename is enabled we need to check if the file is renamed -#ifdef HAS_RENAME - if(md.value().blocks() == -1) { - errno = ENOENT; - return -1; - } else if(!md.value().target_path().empty()) { - std::string new_path; - while(!md.value().target_path().empty() and md.value().blocks() != -1) { - new_path = md.value().target_path(); - md = gkfs::utils::get_metadata(md.value().target_path()); - if(!md) { + if(gkfs::config::metadata::rename_support) { + if(md.value().blocks() == -1) { + errno = ENOENT; + return -1; + } else if(!md.value().target_path().empty()) { + std::string new_path; + while(!md.value().target_path().empty() and + md.value().blocks() != -1) { + new_path = md.value().target_path(); + md = gkfs::utils::get_metadata(md.value().target_path()); + if(!md) { + return -1; + } + } + // This could be optimized + auto size = md->size(); + if(static_cast(length) > size) { + LOG(DEBUG, "Length is greater then file size: {} > {}", length, + size); + errno = EINVAL; return -1; } + return gkfs_truncate(new_path, size, length); } - // This could be optimized - auto size = md->size(); - if(static_cast(length) > size) { - LOG(DEBUG, "Length is greater then file size: {} > {}", length, - size); - errno = EINVAL; - return -1; - } - return gkfs_truncate(new_path, size, length); } -#endif - auto size = md->size(); if(static_cast(length) > size) { LOG(DEBUG, "Length is greater then file size: '{}' > '{}'", length, @@ -1209,32 +1205,31 @@ gkfs_rmdir(const std::string& path) { int err; // check that directory is empty if a strict dir hierarchy is // enforced - // TODO rename #define -#if GKFS_CREATE_CHECK_PARENTS - auto md = gkfs::utils::get_metadata(path); - if(!md) { - LOG(DEBUG, "Error: Path '{}' err code '{}' ", path, strerror(errno)); - return -1; - } - if(!S_ISDIR(md->mode())) { - LOG(DEBUG, "{}() Path is not a directory", __func__); - errno = ENOTDIR; - return -1; - } - auto ret = gkfs::rpc::forward_get_dirents(path); - err = ret.first; - if(err) { - errno = err; - return -1; - } - assert(ret.second); - auto open_dir = ret.second; - if(open_dir->size() != 2) { - errno = ENOTEMPTY; - return -1; + if(gkfs::config::metadata::create_check_parents) { + auto md = gkfs::utils::get_metadata(path); + if(!md) { + LOG(DEBUG, "Error: Path '{}' err code '{}' ", path, + strerror(errno)); + return -1; + } + if(!S_ISDIR(md->mode())) { + LOG(DEBUG, "{}() Path is not a directory", __func__); + errno = ENOTDIR; + return -1; + } + auto ret = gkfs::rpc::forward_get_dirents(path); + err = ret.first; + if(err) { + errno = err; + return -1; + } + assert(ret.second); + auto open_dir = ret.second; + if(open_dir->size() != 2) { + errno = ENOTEMPTY; + return -1; + } } - -#endif if(gkfs::config::proxy::fwd_remove && CTX->use_proxy()) { err = gkfs::rpc::forward_remove_proxy(path, true); } else { @@ -1441,7 +1436,6 @@ gkfs_getdents64(unsigned int fd, struct linux_dirent64* dirp, return written; } -#ifdef HAS_SYMLINKS /** * gkfs wrapper for make symlink() system calls * errno may be set @@ -1532,7 +1526,6 @@ gkfs_readlink(const std::string& path, char* buf, int bufsize) { std::strcpy(buf + CTX->mountdir().size(), md->target_path().c_str()); return path_size; } -#endif std::vector diff --git a/src/client/hooks.cpp b/src/client/hooks.cpp index a228e993edea1cbfa35127f86bf0fd96e285a9ac..3d658bf2bd5a94c5ce5520ce2175bf1965b2e75b 100644 --- a/src/client/hooks.cpp +++ b/src/client/hooks.cpp @@ -216,14 +216,14 @@ hook_fstat(unsigned int fd, struct stat* buf) { if(CTX->file_map()->exist(fd)) { auto path = CTX->file_map()->get(fd)->path(); -#ifdef HAS_RENAME - // Special case for fstat and rename, fd points to new file... - // We can change file_map and recall - auto md = gkfs::utils::get_metadata(path, false); - if(md.has_value() && md.value().blocks() == -1) { - path = md.value().target_path(); + if(gkfs::config::metadata::rename_support) { + // Special case for fstat and rename, fd points to new file... + // We can change file_map and recall + auto md = gkfs::utils::get_metadata(path, false); + if(md.has_value() && md.value().blocks() == -1) { + path = md.value().target_path(); + } } -#endif return with_errno(gkfs::syscall::gkfs_stat(path, buf)); } return gsl::narrow_cast( @@ -426,17 +426,14 @@ hook_symlinkat(const char* oldname, int newdfd, const char* newname) { LOG(DEBUG, "{}() called with oldname: \"{}\", newfd: {}, newname: \"{}\"", __func__, oldname, newdfd, newname); -#ifdef HAS_SYMLINKS bool internal1 = false; -#endif std::string oldname_resolved; if(CTX->relativize_path(oldname, oldname_resolved)) { -#ifdef HAS_SYMLINKS + if(!gkfs::config::metadata::symlink_support) { + LOG(WARNING, "{}() operation not supported", __func__); + return -ENOTSUP; + } internal1 = true; -#else - LOG(WARNING, "{}() operation not supported", __func__); - return -ENOTSUP; -#endif } std::string newname_resolved; @@ -455,17 +452,16 @@ hook_symlinkat(const char* oldname, int newdfd, const char* newname) { return -ENOTDIR; case gkfs::preload::RelativizeStatus::internal: -#ifdef HAS_SYMLINKS + if(!gkfs::config::metadata::symlink_support) { + LOG(WARNING, "{}() operation not supported", __func__); + return -ENOTSUP; + } if(internal1) { // Parameters are inverted return with_errno(gkfs::syscall::gkfs_mk_symlink( newname_resolved, oldname_resolved)); } LOG(WARNING, "{}() operation not supported", __func__); return -ENOTSUP; -#else - LOG(WARNING, "{}() operation not supported", __func__); - return -ENOTSUP; -#endif default: LOG(ERROR, "{}() relativize status unknown", __func__); @@ -1004,11 +1000,10 @@ hook_readlinkat(int dirfd, const char* cpath, char* buf, int bufsiz) { return -ENOTDIR; case gkfs::preload::RelativizeStatus::internal: -#ifdef HAS_SYMLINKS - return with_errno( - gkfs::syscall::gkfs_readlink(resolved, buf, bufsiz)); - -#endif + if(gkfs::config::metadata::symlink_support) { + return with_errno( + gkfs::syscall::gkfs_readlink(resolved, buf, bufsiz)); + } return -EINVAL; default: @@ -1166,16 +1161,16 @@ hook_renameat(int olddfd, const char* oldname, int newdfd, const char* newname, return -ENOTDIR; case gkfs::preload::RelativizeStatus::internal: -#ifdef HAS_RENAME - if(oldpath_status == gkfs::preload::RelativizeStatus::internal) { - return with_errno(gkfs::syscall::gkfs_rename(oldpath_resolved, - newpath_resolved)); - } else { - return -ENOTSUP; + if(gkfs::config::metadata::rename_support) { + if(oldpath_status == + gkfs::preload::RelativizeStatus::internal) { + return with_errno(gkfs::syscall::gkfs_rename( + oldpath_resolved, newpath_resolved)); + } else { + return -ENOTSUP; + } } -#else return -ENOTSUP; -#endif default: LOG(ERROR, "{}() relativize status unknown", __func__); return -EINVAL; diff --git a/src/client/preload.cpp b/src/client/preload.cpp index bb2333fef41eafdfec3294d6d3d48bdc2e825f43..9e9b80664a764c6eaebe57d6d929fca73476918e 100644 --- a/src/client/preload.cpp +++ b/src/client/preload.cpp @@ -443,17 +443,17 @@ init_preload() { // Special CONFIGURATION handling gkfs::config::metadata::use_inline_data = - gkfs::env::get_var("LIBGKFS_USE_INLINE_DATA", + gkfs::env::get_var(gkfs::env::USE_INLINE_DATA, gkfs::config::metadata::use_inline_data ? "ON" : "OFF") == "ON"; gkfs::config::metadata::create_write_optimization = - gkfs::env::get_var("LIBGKFS_CREATE_WRITE_OPTIMIZATION", + gkfs::env::get_var(gkfs::env::CREATE_WRITE_OPTIMIZATION, gkfs::config::metadata::create_write_optimization ? "ON" : "OFF") == "ON"; gkfs::config::metadata::read_inline_prefetch = - gkfs::env::get_var("LIBGKFS_READ_INLINE_PREFETCH", + gkfs::env::get_var(gkfs::env::READ_INLINE_PREFETCH, gkfs::config::metadata::read_inline_prefetch ? "ON" : "OFF") == "ON"; @@ -462,6 +462,21 @@ init_preload() { gkfs::config::rpc::use_dirents_compression ? "ON" : "OFF") == "ON"; + gkfs::config::metadata::create_check_parents = + gkfs::env::get_var(gkfs::env::CREATE_CHECK_PARENTS, + gkfs::config::metadata::create_check_parents + ? "ON" + : "OFF") == "ON"; + gkfs::config::metadata::symlink_support = + gkfs::env::get_var(gkfs::env::SYMLINK_SUPPORT, + gkfs::config::metadata::symlink_support + ? "ON" + : "OFF") == "ON"; + gkfs::config::metadata::rename_support = + gkfs::env::get_var(gkfs::env::RENAME_SUPPORT, + gkfs::config::metadata::rename_support + ? "ON" + : "OFF") == "ON"; #ifndef BYPASS_SYSCALL gkfs::preload::start_interception(); diff --git a/src/client/preload_util.cpp b/src/client/preload_util.cpp index ddcbe26d82241fc6c6e8ffcdbb9a5ce12fc082d8..a0a728837c807797a3a6bac47ee2f0a196aec7e0 100644 --- a/src/client/preload_util.cpp +++ b/src/client/preload_util.cpp @@ -294,8 +294,7 @@ get_metadata(const string& path, bool follow_links, bool include_inline) { errno = err; return {}; } -#ifdef HAS_SYMLINKS - if(follow_links) { + if(gkfs::config::metadata::symlink_support && follow_links) { gkfs::metadata::Metadata md{attr}; auto original = md; while(md.is_link()) { @@ -315,7 +314,6 @@ get_metadata(const string& path, bool follow_links, bool include_inline) { } } } -#endif gkfs::metadata::Metadata md{attr}; if(!inline_data.empty()) { md.inline_data(inline_data); @@ -351,11 +349,9 @@ metadata_to_stat(const std::string& path, const gkfs::metadata::Metadata& md, attr.st_mode = md.mode(); -#ifdef HAS_SYMLINKS - if(md.is_link()) + if(gkfs::config::metadata::symlink_support && md.is_link()) attr.st_size = md.target_path().size() + CTX->mountdir().size(); else -#endif attr.st_size = md.size(); if(CTX->fs_conf()->atime_state) { diff --git a/src/client/rpc/forward_metadata.cpp b/src/client/rpc/forward_metadata.cpp index 347a863823903c12b7d51b0bf6010076185f1a91..1a6cb357f0370d2e99d714c8c803d174b8503aa1 100644 --- a/src/client/rpc/forward_metadata.cpp +++ b/src/client/rpc/forward_metadata.cpp @@ -172,8 +172,6 @@ forward_update_metadentry(const std::string& path, return out.err; } -#ifdef HAS_SYMLINKS - int forward_mk_symlink(const std::string& path, const std::string& target_path) { auto endp = @@ -189,7 +187,6 @@ forward_mk_symlink(const std::string& path, const std::string& target_path) { return out.err; } -#endif // function matches the standard rpc_get_dirents_out_t inline std::vector> @@ -481,7 +478,6 @@ forward_get_dirents(const string& path) { } -#ifdef HAS_RENAME // forward_rename int forward_rename(const std::string& oldpath, const std::string& newpath, @@ -543,7 +539,6 @@ forward_rename(const std::string& oldpath, const std::string& newpath, return EBUSY; } } -#endif // Inline write/read diff --git a/src/common/metadata.cpp b/src/common/metadata.cpp index 99cc025c84fe9a82ca9d12a06b20baeef41d3020..2b9e41c5b291f2c828baf30104f22ff80daedcd6 100644 --- a/src/common/metadata.cpp +++ b/src/common/metadata.cpp @@ -85,11 +85,11 @@ Metadata::init_time() { Metadata::Metadata(const mode_t mode) : mode_(mode), link_count_(0), size_(0), blocks_(0) { -#ifdef HAS_SYMLINKS - assert(S_ISDIR(mode_) || S_ISREG(mode_) || S_ISLNK(mode_)); -#else - assert(S_ISDIR(mode_) || S_ISREG(mode_)); -#endif + if(gkfs::config::metadata::symlink_support) { + assert(S_ISDIR(mode_) || S_ISREG(mode_) || S_ISLNK(mode_)); + } else { + assert(S_ISDIR(mode_) || S_ISREG(mode_)); + } init_time(); } @@ -124,20 +124,18 @@ Metadata::serialize() const { s += fmt::format_int(blocks_).c_str(); } -#ifdef HAS_SYMLINKS - s += MSP; - s += target_path_; -#ifdef HAS_RENAME - s += MSP; - s += rename_path_; -#endif // HAS_RENAME -#endif // HAS_SYMLINKS + if(gkfs::config::metadata::symlink_support) { + s += MSP; + s += target_path_; + if(gkfs::config::metadata::rename_support) { + s += MSP; + s += rename_path_; + } + } return s; } -#ifdef HAS_SYMLINKS - Metadata::Metadata(const mode_t mode, const std::string& target_path) : mode_(mode), link_count_(0), size_(0), blocks_(0), target_path_(target_path) { @@ -148,10 +146,7 @@ Metadata::Metadata(const mode_t mode, const std::string& target_path) assert(target_path_.empty() || target_path_[0] == '/'); init_time(); } -#endif -#ifdef HAS_RENAME -#ifdef HAS_SYMLINKS Metadata::Metadata(const mode_t mode, const std::string& target_path, const std::string& rename_path) : mode_(mode), link_count_(0), size_(0), blocks_(0), @@ -161,8 +156,6 @@ Metadata::Metadata(const mode_t mode, const std::string& target_path, assert(target_path_.empty() || target_path_[0] == '/'); init_time(); } -#endif -#endif Metadata::Metadata(const std::string& binary_str) { try { @@ -226,24 +219,24 @@ Metadata::Metadata(const std::string& binary_str) { } // symlink target -#ifdef HAS_SYMLINKS - if(ptr < end && *ptr == MSP) { - ++ptr; // skip separator - const char* start = ptr; - const char* sep = std::find(ptr, end, MSP); - target_path_.assign(start, sep - start); - ptr = sep; - } -#ifdef HAS_RENAME - if(ptr < end && *ptr == MSP) { - ++ptr; // skip separator - const char* start = ptr; - const char* sep = std::find(ptr, end, MSP); - rename_path_.assign(start, sep - start); - ptr = sep; + if(gkfs::config::metadata::symlink_support) { + if(ptr < end && *ptr == MSP) { + ++ptr; // skip separator + const char* start = ptr; + const char* sep = std::find(ptr, end, MSP); + target_path_.assign(start, sep - start); + ptr = sep; + } + if(gkfs::config::metadata::rename_support) { + if(ptr < end && *ptr == MSP) { + ++ptr; // skip separator + const char* start = ptr; + const char* sep = std::find(ptr, end, MSP); + rename_path_.assign(start, sep - start); + ptr = sep; + } + } } -#endif // HAS_RENAME -#endif // HAS_SYMLINKS // inline data if(gkfs::config::metadata::use_inline_data && ptr < end) { @@ -343,8 +336,6 @@ Metadata::blocks(blkcnt_t blocks) { blocks_ = blocks; } -#ifdef HAS_SYMLINKS - std::string Metadata::target_path() const { return target_path_; @@ -360,7 +351,6 @@ Metadata::is_link() const { return S_ISLNK(mode_); } -#ifdef HAS_RENAME std::string Metadata::rename_path() const { return rename_path_; @@ -371,9 +361,6 @@ Metadata::rename_path(const std::string& rename_path) { rename_path_ = rename_path; } -#endif // HAS_RENAME -#endif // HAS_SYMLINKS - std::string Metadata::inline_data() const { return inline_data_; diff --git a/src/daemon/backend/metadata/parallax_backend.cpp b/src/daemon/backend/metadata/parallax_backend.cpp index ec15c9f7d8a718a03c67eef268da1462a9949609..519a5af591208a55ca1476f051325405ff7a7b99 100644 --- a/src/daemon/backend/metadata/parallax_backend.cpp +++ b/src/daemon/backend/metadata/parallax_backend.cpp @@ -429,16 +429,16 @@ ParallaxBackend::get_dirents_impl(const std::string& dir) const { assert(!name.empty()); Metadata md(v); -#ifdef HAS_RENAME - // Remove entries with negative blocks (rename) - if(md.blocks() == -1) { - if(par_get_next(S) && !par_is_valid(S)) - break; - else - continue; + if(gkfs::config::metadata::rename_support) { + // Remove entries with negative blocks (rename) + if(md.blocks() == -1) { + if(par_get_next(S) && !par_is_valid(S)) + break; + else + continue; + } } -#endif // HAS_RENAME - auto is_dir = S_ISDIR(md.mode()); + entries.emplace_back(std::move(name), is_dir); @@ -512,16 +512,16 @@ ParallaxBackend::get_dirents_extended_impl(const std::string& dir) const { assert(!name.empty()); Metadata md(v); -#ifdef HAS_RENAME - // Remove entries with negative blocks (rename) - if(md.blocks() == -1) { - if(par_get_next(S) && !par_is_valid(S)) - break; - else - continue; + if(gkfs::config::metadata::rename_support) { + // Remove entries with negative blocks (rename) + if(md.blocks() == -1) { + if(par_get_next(S) && !par_is_valid(S)) + break; + else + continue; + } } -#endif // HAS_RENAME - auto is_dir = S_ISDIR(md.mode()); + entries.emplace_back(std::forward_as_tuple(std::move(name), is_dir, md.size(), md.ctime())); @@ -570,16 +570,16 @@ ParallaxBackend::get_all_dirents_extended_impl( } Metadata md(v); -#ifdef HAS_RENAME - // Remove entries with negative blocks (rename) - if(md.blocks() == -1) { - if(par_get_next(S) && !par_is_valid(S)) - break; - else - continue; + if(gkfs::config::metadata::rename_support) { + // Remove entries with negative blocks (rename) + if(md.blocks() == -1) { + if(par_get_next(S) && !par_is_valid(S)) + break; + else + continue; + } } -#endif // HAS_RENAME - auto is_dir = S_ISDIR(md.mode()); + entries.emplace_back(std::forward_as_tuple(std::move(k), is_dir, md.size(), md.ctime())); diff --git a/src/daemon/backend/metadata/rocksdb_backend.cpp b/src/daemon/backend/metadata/rocksdb_backend.cpp index 5452398e6a6ba86d50dbc6491a40f132824ed889..6a5f93e3d15eeb2a97042bcb685dd9f84e342e97 100644 --- a/src/daemon/backend/metadata/rocksdb_backend.cpp +++ b/src/daemon/backend/metadata/rocksdb_backend.cpp @@ -379,12 +379,12 @@ RocksDBBackend::get_dirents_impl(const std::string& dir) const { } Metadata md(it->value().ToString()); -#ifdef HAS_RENAME - // Remove entries with negative blocks (rename) - if(md.blocks() == -1) { - continue; + if(gkfs::config::metadata::rename_support) { + // Remove entries with negative blocks (rename) + if(md.blocks() == -1) { + continue; + } } -#endif // HAS_RENAME // 0: regular, 1: directory, 2: symlink @@ -457,12 +457,12 @@ RocksDBBackend::get_dirents_extended_impl(const std::string& dir, } Metadata md(it->value().ToString()); -#ifdef HAS_RENAME - // Remove entries with negative blocks (rename) - if(md.blocks() == -1) { - continue; + if(gkfs::config::metadata::rename_support) { + // Remove entries with negative blocks (rename) + if(md.blocks() == -1) { + continue; + } } -#endif // HAS_RENAME unsigned char type = 0; @@ -529,15 +529,14 @@ RocksDBBackend::get_all_dirents_extended_impl(const std::string& dir, } Metadata md(it->value().ToString()); -#ifdef HAS_RENAME - // Remove entries with negative blocks (rename) - if(md.blocks() == -1) { - continue; + if(gkfs::config::metadata::rename_support) { + // Remove entries with negative blocks (rename) + if(md.blocks() == -1) { + continue; + } } -#endif // HAS_RENAME - auto is_dir = S_ISDIR(md.mode()); // 0: regular, 1: directory, 2: symlink unsigned char type = 0; if(S_ISDIR(md.mode())) { @@ -629,12 +628,12 @@ RocksDBBackend::get_dirents_filtered_impl(const std::string& dir, scanned_count++; Metadata md(it->value().ToString()); -#ifdef HAS_RENAME - // Remove entries with negative blocks (rename) - if(md.blocks() == -1) { - continue; + if(gkfs::config::metadata::rename_support) { + // Remove entries with negative blocks (rename) + if(md.blocks() == -1) { + continue; + } } -#endif // HAS_RENAME bool matched = true; if(use_regex) { diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp index b845ec0b5f96b322bdf72e242e6ec40c015a3443..6d10c6305a2aaa707d4505a08a3e0e72f95284d3 100644 --- a/src/daemon/daemon.cpp +++ b/src/daemon/daemon.cpp @@ -189,12 +189,8 @@ register_server_rpcs(std::shared_ptr engine) { rpc_srv_get_dirents_filtered(engine, req, in); }); -#ifdef HAS_SYMLINKS engine->define(gkfs::rpc::tag::mk_symlink, rpc_srv_mk_symlink); -#endif -#ifdef HAS_RENAME engine->define(gkfs::rpc::tag::rename, rpc_srv_rename); -#endif // Data RPCs // Data RPCs @@ -371,7 +367,7 @@ init_environment() { // Check for environment variables for configuration gkfs::config::metadata::use_inline_data = - gkfs::env::get_var("GKFS_DAEMON_USE_INLINE_DATA", + gkfs::env::get_var(gkfs::env::DAEMON_USE_INLINE_DATA, gkfs::config::metadata::use_inline_data ? "ON" : "OFF") == "ON"; @@ -380,10 +376,29 @@ init_environment() { gkfs::config::rpc::use_dirents_compression ? "ON" : "OFF") == "ON"; + gkfs::config::metadata::create_check_parents = + gkfs::env::get_var(gkfs::env::DAEMON_CREATE_CHECK_PARENTS, + gkfs::config::metadata::create_check_parents + ? "ON" + : "OFF") == "ON"; + gkfs::config::metadata::symlink_support = + gkfs::env::get_var(gkfs::env::DAEMON_SYMLINK_SUPPORT, + gkfs::config::metadata::symlink_support + ? "ON" + : "OFF") == "ON"; + gkfs::config::metadata::rename_support = + gkfs::env::get_var(gkfs::env::DAEMON_RENAME_SUPPORT, + gkfs::config::metadata::rename_support + ? "ON" + : "OFF") == "ON"; + GKFS_DATA->spdlogger()->info( - "{}() Inline data: {} / Dirents compression: {}", __func__, - gkfs::config::metadata::use_inline_data, - gkfs::config::rpc::use_dirents_compression); + "{}() Inline data: {} / Dirents compression: {} / Create check parents: {} / Symlink support: {} / Rename support: {}", + __func__, gkfs::config::metadata::use_inline_data, + gkfs::config::rpc::use_dirents_compression, + gkfs::config::metadata::create_check_parents, + gkfs::config::metadata::symlink_support, + gkfs::config::metadata::rename_support); #ifdef GKFS_ENABLE_AGIOS // Initialize AGIOS scheduler diff --git a/src/daemon/handler/srv_metadata.cpp b/src/daemon/handler/srv_metadata.cpp index 32c741a75cfe211a91b044b1a9a5937dbc8b787f..d8790d88eba2b9cdbf0bdc1ae16f63bc24a18193 100644 --- a/src/daemon/handler/srv_metadata.cpp +++ b/src/daemon/handler/srv_metadata.cpp @@ -815,7 +815,6 @@ rpc_srv_get_dirents_filtered( } -#if defined(HAS_SYMLINKS) /** * @brief Serves a request create a symbolic link * @internal @@ -832,6 +831,12 @@ rpc_srv_mk_symlink(const tl::request& req, const gkfs::rpc::rpc_mk_symlink_in_t& in) { gkfs::rpc::rpc_err_out_t out{}; + if(!gkfs::config::metadata::symlink_support) { + out.err = ENOTSUP; + req.respond(out); + return; + } + GKFS_DATA->spdlogger()->debug( "{}() Got RPC with path '{}' and target path '{}'", __func__, in.path, in.target_path); @@ -860,9 +865,6 @@ rpc_srv_mk_symlink(const tl::request& req, req.respond(out); } -#endif // HAS_SYMLINKS - -#if defined(HAS_RENAME) /** * @brief Serves a request create a symbolic link and supports rename * @internal @@ -878,6 +880,12 @@ void rpc_srv_rename(const tl::request& req, const gkfs::rpc::rpc_rename_in_t& in) { gkfs::rpc::rpc_err_out_t out{}; + if(!gkfs::config::metadata::rename_support) { + out.err = ENOTSUP; + req.respond(out); + return; + } + GKFS_DATA->spdlogger()->debug( "{}() Got RPC with path '{}' and target path '{}'", __func__, in.path, in.target_path); @@ -910,7 +918,6 @@ rpc_srv_rename(const tl::request& req, const gkfs::rpc::rpc_rename_in_t& in) { out.err); req.respond(out); } -#endif // HAS_RENAME /** * @brief Serves a write request for inline data (stored in RocksDB). diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index d9b67b8a1bdb3a65b076c21b27bdab00288cb2dc..28ce5a90bbc5301240e9230083a9c7ade066b503 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -155,14 +155,12 @@ gkfs_add_python_test( SOURCE error_handling/ ) -if (GKFS_RENAME_SUPPORT) gkfs_add_python_test( NAME test_rename PYTHON_VERSION 3.6 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/integration SOURCE rename/ ) -endif () gkfs_add_python_test( NAME test_compatibility @@ -291,7 +289,6 @@ if (GKFS_INSTALL_TESTS) ) endif () - if (GKFS_RENAME_SUPPORT) install(DIRECTORY rename DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gkfs/tests/integration FILES_MATCHING @@ -299,7 +296,6 @@ if (GKFS_INSTALL_TESTS) PATTERN "__pycache__" EXCLUDE PATTERN ".pytest_cache" EXCLUDE ) - endif () install(DIRECTORY malleability DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/gkfs/tests/integration