From f64ff9ca1eb4541ebe9fe32a1ef84ce382cb781b Mon Sep 17 00:00:00 2001 From: trapexit Date: Sat, 6 Sep 2025 12:03:51 -0400 Subject: [PATCH] Revert removal of readdir init setup, simplify cfg usage (#1520) --- src/config.cpp | 3 +- src/config.hpp | 58 +-------------------- src/fuse_access.cpp | 5 +- src/fuse_chmod.cpp | 7 ++- src/fuse_chown.cpp | 7 ++- src/fuse_create.cpp | 36 +++++++------ src/fuse_fgetattr.cpp | 9 ++-- src/fuse_getattr.cpp | 17 +++---- src/fuse_getxattr.cpp | 16 +++--- src/fuse_init.cpp | 72 +++++++++++++------------- src/fuse_ioctl.cpp | 5 +- src/fuse_link.cpp | 33 ++++++------ src/fuse_listxattr.cpp | 10 ++-- src/fuse_mkdir.cpp | 15 +++--- src/fuse_mknod.cpp | 15 +++--- src/fuse_open.cpp | 34 ++++++------- src/fuse_opendir.cpp | 29 +++++------ src/fuse_readdir.cpp | 33 ++++++------ src/fuse_readdir.hpp | 9 ++++ src/fuse_readdir_cor.cpp | 3 +- src/fuse_readdir_cosr.cpp | 3 +- src/fuse_readdir_factory.cpp | 13 +++++ src/fuse_readdir_factory.hpp | 1 + src/fuse_readdir_seq.cpp | 3 +- src/fuse_readlink.cpp | 9 ++-- src/fuse_release.cpp | 3 +- src/fuse_removexattr.cpp | 12 ++--- src/fuse_rename.cpp | 88 ++++++++++++++++---------------- src/fuse_rmdir.cpp | 7 ++- src/fuse_setxattr.cpp | 21 ++++---- src/fuse_statfs.cpp | 7 ++- src/fuse_statx_supported.icpp | 17 +++---- src/fuse_symlink.cpp | 23 ++++----- src/fuse_truncate.cpp | 7 ++- src/fuse_unlink.cpp | 5 +- src/fuse_utimens.cpp | 7 ++- src/fuse_write.cpp | 14 +++-- src/mergerfs.cpp | 25 +++++---- src/option_parser.cpp | 96 +++++++++++++++++------------------ src/state.cpp | 13 +++++ src/state.hpp | 3 ++ src/thread_info.hpp | 21 ++++++++ 42 files changed, 388 insertions(+), 426 deletions(-) create mode 100644 src/thread_info.hpp diff --git a/src/config.cpp b/src/config.cpp index 25ff30e9..d3644ee9 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -44,8 +44,7 @@ constexpr static const char CACHE_FILES_PROCESS_NAMES_DEFAULT[] = "rtorrent|" "qbittorrent-nox"; - -Config Config::_singleton; +Config cfg; namespace l { diff --git a/src/config.hpp b/src/config.hpp index 21b784d9..17c657fb 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -75,32 +75,6 @@ public: typedef std::vector ErrVec; -public: - class Read - { - public: - Read(); - - public: - inline const Config* operator->() const; - - private: - const Config &_cfg; - }; - -public: - class Write - { - public: - Write(); - - public: - Config* operator->(); - - private: - Config &_cfg; - }; - public: Config(); @@ -209,9 +183,6 @@ public: private: Str2TFStrMap _map; -private: - static Config _singleton; - public: friend class Read; friend class Write; @@ -219,31 +190,4 @@ public: std::ostream& operator<<(std::ostream &s,const Config::ErrVec &ev); -inline -Config::Read::Read() - : _cfg(Config::_singleton) -{ - -} - -inline -const -Config* -Config::Read::operator->() const -{ - return &_cfg; -} - -inline -Config::Write::Write() - : _cfg(Config::_singleton) -{ - -} - -inline -Config* -Config::Write::operator->() -{ - return &_cfg; -} +extern Config cfg; diff --git a/src/fuse_access.cpp b/src/fuse_access.cpp index d7f9c861..a2983fdf 100644 --- a/src/fuse_access.cpp +++ b/src/fuse_access.cpp @@ -59,12 +59,11 @@ namespace FUSE access(const char *fusepath_, int mask_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::access(cfg->func.access.policy, - cfg->branches, + return l::access(cfg.func.access.policy, + cfg.branches, fusepath_, mask_); } diff --git a/src/fuse_chmod.cpp b/src/fuse_chmod.cpp index a53294ac..1714d432 100644 --- a/src/fuse_chmod.cpp +++ b/src/fuse_chmod.cpp @@ -96,13 +96,12 @@ int _chmod(const char *fusepath_, const mode_t mode_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::chmod(cfg->func.chmod.policy, - cfg->func.getattr.policy, - cfg->branches, + return l::chmod(cfg.func.chmod.policy, + cfg.func.getattr.policy, + cfg.branches, fusepath_, mode_); } diff --git a/src/fuse_chown.cpp b/src/fuse_chown.cpp index f458ebaa..cfbc1528 100644 --- a/src/fuse_chown.cpp +++ b/src/fuse_chown.cpp @@ -100,13 +100,12 @@ namespace FUSE uid_t uid_, gid_t gid_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::chown(cfg->func.chown.policy, - cfg->func.getattr.policy, - cfg->branches, + return l::chown(cfg.func.chown.policy, + cfg.func.getattr.policy, + cfg.branches, fusepath_, uid_, gid_); diff --git a/src/fuse_create.cpp b/src/fuse_create.cpp index 11fc0495..2b6b4ee3 100644 --- a/src/fuse_create.cpp +++ b/src/fuse_create.cpp @@ -79,16 +79,16 @@ _calculate_flush(FlushOnClose const flushonclose_, static void -_config_to_ffi_flags(Config::Read &cfg_, +_config_to_ffi_flags(Config &cfg_, const int tid_, fuse_file_info_t *ffi_) { - switch(cfg_->cache_files) + switch(cfg_.cache_files) { case CacheFiles::ENUM::LIBFUSE: - ffi_->direct_io = cfg_->direct_io; - ffi_->keep_cache = cfg_->kernel_cache; - ffi_->auto_cache = cfg_->auto_cache; + ffi_->direct_io = cfg_.direct_io; + ffi_->keep_cache = cfg_.kernel_cache; + ffi_->auto_cache = cfg_.auto_cache; break; case CacheFiles::ENUM::OFF: ffi_->direct_io = 1; @@ -114,7 +114,7 @@ _config_to_ffi_flags(Config::Read &cfg_, std::string proc_name; proc_name = procfs::get_name(tid_); - if(cfg_->cache_files_process_names.count(proc_name) == 0) + if(cfg_.cache_files_process_names.count(proc_name) == 0) { ffi_->direct_io = 1; ffi_->keep_cache = 0; @@ -129,7 +129,7 @@ _config_to_ffi_flags(Config::Read &cfg_, break; } - if(cfg_->parallel_direct_writes == true) + if(cfg_.parallel_direct_writes == true) ffi_->parallel_direct_writes = ffi_->direct_io; } @@ -229,28 +229,27 @@ _create_for_insert_lambda(const fuse_context *fc_, { int rv; FileInfo *fi; - Config::Read cfg; const ugid::Set ugid(fc_->uid,fc_->gid); ::_config_to_ffi_flags(cfg,fc_->pid,ffi_); - if(cfg->writeback_cache) + if(cfg.writeback_cache) ::_tweak_flags_writeback_cache(&ffi_->flags); - ffi_->noflush = !::_calculate_flush(cfg->flushonclose, + ffi_->noflush = !::_calculate_flush(cfg.flushonclose, ffi_->flags); - rv = ::_create(cfg->func.getattr.policy, - cfg->func.create.policy, - cfg->branches, + rv = ::_create(cfg.func.getattr.policy, + cfg.func.create.policy, + cfg.branches, fusepath_, ffi_, mode_, fc_->umask); if(rv == -EROFS) { - Config::Write()->branches.find_and_set_mode_ro(); - rv = ::_create(cfg->func.getattr.policy, - cfg->func.create.policy, - cfg->branches, + cfg.branches.find_and_set_mode_ro(); + rv = ::_create(cfg.func.getattr.policy, + cfg.func.create.policy, + cfg.branches, fusepath_, ffi_, mode_, @@ -265,7 +264,7 @@ _create_for_insert_lambda(const fuse_context *fc_, of_->ref_count = 1; of_->fi = fi; - switch(_(cfg->passthrough,ffi_->flags)) + switch(_(cfg.passthrough,ffi_->flags)) { case _(Passthrough::ENUM::RO,O_RDONLY): case _(Passthrough::ENUM::WO,O_WRONLY): @@ -359,7 +358,6 @@ namespace FUSE mode_t mode_, fuse_file_info_t *ffi_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); return ::_create(fc,fusepath_,mode_,ffi_); diff --git a/src/fuse_fgetattr.cpp b/src/fuse_fgetattr.cpp index 7b9413a5..b38c437c 100644 --- a/src/fuse_fgetattr.cpp +++ b/src/fuse_fgetattr.cpp @@ -52,7 +52,6 @@ FUSE::fgetattr(const uint64_t fh_, { int rv; uint64_t fh; - Config::Read cfg; const fuse_context *fc = fuse_get_context(); fh = fh_; @@ -67,7 +66,7 @@ FUSE::fgetattr(const uint64_t fh_, if(fh == 0) { - timeout_->entry = cfg->cache_negative_entry; + timeout_->entry = cfg.cache_negative_entry; return -ENOENT; } @@ -76,9 +75,9 @@ FUSE::fgetattr(const uint64_t fh_, rv = ::_fgetattr(fi,st_); timeout_->entry = ((rv >= 0) ? - cfg->cache_entry : - cfg->cache_negative_entry); - timeout_->attr = cfg->cache_attr; + cfg.cache_entry : + cfg.cache_negative_entry); + timeout_->attr = cfg.cache_attr; return rv; } diff --git a/src/fuse_getattr.cpp b/src/fuse_getattr.cpp index a97ffe95..e5ff20cf 100644 --- a/src/fuse_getattr.cpp +++ b/src/fuse_getattr.cpp @@ -177,24 +177,23 @@ _getattr(const char *fusepath_, fuse_timeouts_t *timeout_) { int rv; - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - rv = ::_getattr(cfg->func.getattr.policy, - cfg->branches, + rv = ::_getattr(cfg.func.getattr.policy, + cfg.branches, fusepath_, st_, - cfg->symlinkify, - cfg->symlinkify_timeout, - cfg->follow_symlinks); + cfg.symlinkify, + cfg.symlinkify_timeout, + cfg.follow_symlinks); if((rv < 0) && Config::is_rootdir(fusepath_)) return ::_getattr_fake_root(st_); timeout_->entry = ((rv >= 0) ? - cfg->cache_entry : - cfg->cache_negative_entry); - timeout_->attr = cfg->cache_attr; + cfg.cache_entry : + cfg.cache_negative_entry); + timeout_->attr = cfg.cache_attr; return rv; } diff --git a/src/fuse_getxattr.cpp b/src/fuse_getxattr.cpp index 43eb3feb..a1ff14e6 100644 --- a/src/fuse_getxattr.cpp +++ b/src/fuse_getxattr.cpp @@ -47,7 +47,7 @@ _is_attrname_security_capability(const char *attrname_) static int -_getxattr_ctrl_file(Config::Read &cfg_, +_getxattr_ctrl_file(Config &cfg_, const char *attrname_, char *buf_, const size_t count_) @@ -60,7 +60,7 @@ _getxattr_ctrl_file(Config::Read &cfg_, return -ENOATTR; key = Config::prune_ctrl_xattr(attrname_); - rv = cfg_->get(key,&val); + rv = cfg_.get(key,&val); if(rv < 0) return rv; @@ -177,26 +177,24 @@ FUSE::getxattr(const char *fusepath_, char *attrvalue_, size_t attrvalue_size_) { - Config::Read cfg; - if(Config::is_ctrl_file(fusepath_)) return ::_getxattr_ctrl_file(cfg, attrname_, attrvalue_, attrvalue_size_); - if((cfg->security_capability == false) && + if((cfg.security_capability == false) && ::_is_attrname_security_capability(attrname_)) return -ENOATTR; - if(cfg->xattr.to_int()) - return -cfg->xattr.to_int(); + if(cfg.xattr.to_int()) + return -cfg.xattr.to_int(); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_getxattr(cfg->func.getxattr.policy, - cfg->branches, + return ::_getxattr(cfg.func.getxattr.policy, + cfg.branches, fusepath_, attrname_, attrvalue_, diff --git a/src/fuse_init.cpp b/src/fuse_init.cpp index 7c9c7795..c174af64 100644 --- a/src/fuse_init.cpp +++ b/src/fuse_init.cpp @@ -79,19 +79,19 @@ static const char MAX_PAGES_LIMIT_FILEPATH[] = "/proc/sys/fs/fuse/max_pages_limi static void _want_if_capable_max_pages(fuse_conn_info *conn_, - Config::Write &cfg_) + Config &cfg_) { std::fstream f; uint64_t max_pages_limit; if(fs::exists(MAX_PAGES_LIMIT_FILEPATH)) { - if(cfg_->fuse_msg_size > MAX_FUSE_MSG_SIZE) + if(cfg_.fuse_msg_size > MAX_FUSE_MSG_SIZE) SysLog::info("fuse_msg_size > {}: setting it to {}", MAX_FUSE_MSG_SIZE, MAX_FUSE_MSG_SIZE); - cfg_->fuse_msg_size = std::min((uint64_t)cfg_->fuse_msg_size, - (uint64_t)MAX_FUSE_MSG_SIZE); + cfg_.fuse_msg_size = std::min((uint64_t)cfg_.fuse_msg_size, + (uint64_t)MAX_FUSE_MSG_SIZE); f.open(MAX_PAGES_LIMIT_FILEPATH,f.in|f.out); if(f.is_open()) @@ -100,44 +100,44 @@ _want_if_capable_max_pages(fuse_conn_info *conn_, SysLog::info("{} currently set to {}", MAX_PAGES_LIMIT_FILEPATH, max_pages_limit); - if(cfg_->fuse_msg_size > max_pages_limit) + if(cfg_.fuse_msg_size > max_pages_limit) { f.seekp(0); - f << (uint64_t)cfg_->fuse_msg_size; + f << (uint64_t)cfg_.fuse_msg_size; f.flush(); SysLog::info("{} changed to {}", MAX_PAGES_LIMIT_FILEPATH, - (uint64_t)cfg_->fuse_msg_size); + (uint64_t)cfg_.fuse_msg_size); } f.close(); } else { - if(cfg_->fuse_msg_size != FUSE_DEFAULT_MAX_MAX_PAGES) + if(cfg_.fuse_msg_size != FUSE_DEFAULT_MAX_MAX_PAGES) SysLog::info("unable to open {}",MAX_PAGES_LIMIT_FILEPATH); } } else { - if(cfg_->fuse_msg_size > FUSE_DEFAULT_MAX_MAX_PAGES) + if(cfg_.fuse_msg_size > FUSE_DEFAULT_MAX_MAX_PAGES) SysLog::info("fuse_msg_size request {} > {}: setting it to {}", - (uint64_t)cfg_->fuse_msg_size, + (uint64_t)cfg_.fuse_msg_size, FUSE_DEFAULT_MAX_MAX_PAGES, FUSE_DEFAULT_MAX_MAX_PAGES); - cfg_->fuse_msg_size = std::min((uint64_t)cfg_->fuse_msg_size, - (uint64_t)FUSE_DEFAULT_MAX_MAX_PAGES); + cfg_.fuse_msg_size = std::min((uint64_t)cfg_.fuse_msg_size, + (uint64_t)FUSE_DEFAULT_MAX_MAX_PAGES); } if(::_capable(conn_,FUSE_CAP_MAX_PAGES)) { ::_want(conn_,FUSE_CAP_MAX_PAGES); - conn_->max_pages = cfg_->fuse_msg_size; + conn_->max_pages = cfg_.fuse_msg_size; SysLog::info("requesting max pages size of {}", - (uint64_t)cfg_->fuse_msg_size); + (uint64_t)cfg_.fuse_msg_size); } else { - cfg_->fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ; + cfg_.fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ; } } @@ -159,17 +159,16 @@ static void _set_readahead_on_mount_and_branches() { - Config::Read cfg; Branches::Ptr branches; - if((uint64_t)cfg->readahead == 0) + if((uint64_t)cfg.readahead == 0) return; - ::_readahead(cfg->mountpoint,cfg->readahead); + ::_readahead(cfg.mountpoint,cfg.readahead); - branches = cfg->branches; + branches = cfg.branches; for(auto const &branch : *branches) - ::_readahead(branch.path,cfg->readahead); + ::_readahead(branch.path,cfg.readahead); } // Spawn a thread to do this because before init returns calls to @@ -187,27 +186,26 @@ _spawn_thread_to_set_readahead() void * FUSE::init(fuse_conn_info *conn_) { - Config::Write cfg; - procfs::init(); ugid::init(); + cfg.readdir.initialize(); ::_want_if_capable(conn_,FUSE_CAP_ASYNC_DIO); - ::_want_if_capable(conn_,FUSE_CAP_ASYNC_READ,&cfg->async_read); + ::_want_if_capable(conn_,FUSE_CAP_ASYNC_READ,&cfg.async_read); ::_want_if_capable(conn_,FUSE_CAP_ATOMIC_O_TRUNC); ::_want_if_capable(conn_,FUSE_CAP_BIG_WRITES); - ::_want_if_capable(conn_,FUSE_CAP_CACHE_SYMLINKS,&cfg->cache_symlinks); - ::_want_if_capable(conn_,FUSE_CAP_DIRECT_IO_ALLOW_MMAP,&cfg->direct_io_allow_mmap); + ::_want_if_capable(conn_,FUSE_CAP_CACHE_SYMLINKS,&cfg.cache_symlinks); + ::_want_if_capable(conn_,FUSE_CAP_DIRECT_IO_ALLOW_MMAP,&cfg.direct_io_allow_mmap); ::_want_if_capable(conn_,FUSE_CAP_DONT_MASK); - ::_want_if_capable(conn_,FUSE_CAP_EXPORT_SUPPORT,&cfg->export_support); - ::_want_if_capable(conn_,FUSE_CAP_HANDLE_KILLPRIV,&cfg->handle_killpriv); - ::_want_if_capable(conn_,FUSE_CAP_HANDLE_KILLPRIV_V2,&cfg->handle_killpriv_v2); + ::_want_if_capable(conn_,FUSE_CAP_EXPORT_SUPPORT,&cfg.export_support); + ::_want_if_capable(conn_,FUSE_CAP_HANDLE_KILLPRIV,&cfg.handle_killpriv); + ::_want_if_capable(conn_,FUSE_CAP_HANDLE_KILLPRIV_V2,&cfg.handle_killpriv_v2); ::_want_if_capable(conn_,FUSE_CAP_IOCTL_DIR); ::_want_if_capable(conn_,FUSE_CAP_PARALLEL_DIROPS); ::_want_if_capable(conn_,FUSE_CAP_PASSTHROUGH); - ::_want_if_capable(conn_,FUSE_CAP_POSIX_ACL,&cfg->posix_acl); - ::_want_if_capable(conn_,FUSE_CAP_READDIR_PLUS,&cfg->readdirplus); - ::_want_if_capable(conn_,FUSE_CAP_WRITEBACK_CACHE,&cfg->writeback_cache); + ::_want_if_capable(conn_,FUSE_CAP_POSIX_ACL,&cfg.posix_acl); + ::_want_if_capable(conn_,FUSE_CAP_READDIR_PLUS,&cfg.readdirplus); + ::_want_if_capable(conn_,FUSE_CAP_WRITEBACK_CACHE,&cfg.writeback_cache); // ::_want_if_capable(conn_,FUSE_CAP_READDIR_PLUS_AUTO); ::_want_if_capable_max_pages(conn_,cfg); conn_->want &= ~FUSE_CAP_POSIX_LOCKS; @@ -215,21 +213,21 @@ FUSE::init(fuse_conn_info *conn_) ::_spawn_thread_to_set_readahead(); - if(!(conn_->capable & FUSE_CAP_PASSTHROUGH) && (cfg->passthrough != Passthrough::ENUM::OFF)) + if(!(conn_->capable & FUSE_CAP_PASSTHROUGH) && (cfg.passthrough != Passthrough::ENUM::OFF)) { SysLog::warning("passthrough enabled but not supported by kernel. disabling."); - cfg->passthrough = Passthrough::ENUM::OFF; + cfg.passthrough = Passthrough::ENUM::OFF; } - if((cfg->passthrough != Passthrough::ENUM::OFF) && - (cfg->cache_files == CacheFiles::ENUM::OFF)) + if((cfg.passthrough != Passthrough::ENUM::OFF) && + (cfg.cache_files == CacheFiles::ENUM::OFF)) { SysLog::warning("passthrough enabled and cache.files disabled:" " passthrough will not function"); } - if((cfg->passthrough != Passthrough::ENUM::OFF) && - (cfg->writeback_cache == true)) + if((cfg.passthrough != Passthrough::ENUM::OFF) && + (cfg.writeback_cache == true)) { SysLog::warning("passthrough and cache.writeback are incompatible."); } diff --git a/src/fuse_ioctl.cpp b/src/fuse_ioctl.cpp index 235bbb19..f372b76f 100644 --- a/src/fuse_ioctl.cpp +++ b/src/fuse_ioctl.cpp @@ -161,13 +161,12 @@ _ioctl_dir(const fuse_file_info_t *ffi_, void *data_, uint32_t *out_bufsz_) { - Config::Read cfg; DirInfo *di = reinterpret_cast(ffi_->fh); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_ioctl_dir_base(cfg->func.open.policy, - cfg->branches, + return ::_ioctl_dir_base(cfg.func.open.policy, + cfg.branches, di->fusepath.c_str(), cmd_, data_, diff --git a/src/fuse_link.cpp b/src/fuse_link.cpp index eb882652..5d8b48a8 100644 --- a/src/fuse_link.cpp +++ b/src/fuse_link.cpp @@ -166,28 +166,28 @@ _link_preserve_path(const Policy::Action &actionFunc_, static int -_link(Config::Read &cfg_, - const char *oldpath_, - const char *newpath_, - struct stat *st_) +_link(Config &cfg_, + const char *oldpath_, + const char *newpath_, + struct stat *st_) { - if(cfg_->func.create.policy.path_preserving() && !cfg_->ignorepponrename) - return ::_link_preserve_path(cfg_->func.link.policy, - cfg_->branches, + if(cfg_.func.create.policy.path_preserving() && !cfg_.ignorepponrename) + return ::_link_preserve_path(cfg_.func.link.policy, + cfg_.branches, oldpath_, newpath_, st_); - return ::_link_create_path(cfg_->func.getattr.policy, - cfg_->func.link.policy, - cfg_->branches, + return ::_link_create_path(cfg_.func.getattr.policy, + cfg_.func.link.policy, + cfg_.branches, oldpath_, newpath_); } static int -_link(Config::Read &cfg_, +_link(Config &cfg_, const char *oldpath_, const char *newpath_, struct stat *st_, @@ -283,13 +283,13 @@ _link_exdev_abs_pool_symlink(const fs::Path mount_, static int -_link_exdev(Config::Read &cfg_, +_link_exdev(Config &cfg_, const char *oldpath_, const char *newpath_, struct stat *st_, fuse_timeouts_t *timeouts_) { - switch(cfg_->link_exdev) + switch(cfg_.link_exdev) { case LinkEXDEV::ENUM::PASSTHROUGH: return -EXDEV; @@ -299,14 +299,14 @@ _link_exdev(Config::Read &cfg_, st_, timeouts_); case LinkEXDEV::ENUM::ABS_BASE_SYMLINK: - return ::_link_exdev_abs_base_symlink(cfg_->func.open.policy, - cfg_->branches, + return ::_link_exdev_abs_base_symlink(cfg_.func.open.policy, + cfg_.branches, oldpath_, newpath_, st_, timeouts_); case LinkEXDEV::ENUM::ABS_POOL_SYMLINK: - return ::_link_exdev_abs_pool_symlink(cfg_->mountpoint, + return ::_link_exdev_abs_pool_symlink(cfg_.mountpoint, oldpath_, newpath_, st_, @@ -323,7 +323,6 @@ FUSE::link(const char *oldpath_, fuse_timeouts_t *timeouts_) { int rv; - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); diff --git a/src/fuse_listxattr.cpp b/src/fuse_listxattr.cpp index 5f390673..a50387c0 100644 --- a/src/fuse_listxattr.cpp +++ b/src/fuse_listxattr.cpp @@ -127,12 +127,10 @@ FUSE::listxattr(const char *fusepath_, char *list_, size_t size_) { - Config::Read cfg; - if(Config::is_ctrl_file(fusepath_)) - return cfg->keys_listxattr(list_,size_); + return cfg.keys_listxattr(list_,size_); - switch(cfg->xattr) + switch(cfg.xattr) { case XAttr::ENUM::PASSTHROUGH: break; @@ -145,8 +143,8 @@ FUSE::listxattr(const char *fusepath_, const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_listxattr(cfg->func.listxattr.policy, - cfg->branches, + return ::_listxattr(cfg.func.listxattr.policy, + cfg.branches, fusepath_, list_, size_); diff --git a/src/fuse_mkdir.cpp b/src/fuse_mkdir.cpp index 9324d60c..80a4056d 100644 --- a/src/fuse_mkdir.cpp +++ b/src/fuse_mkdir.cpp @@ -129,22 +129,21 @@ FUSE::mkdir(const char *fusepath_, mode_t mode_) { int rv; - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - rv = ::_mkdir(cfg->func.getattr.policy, - cfg->func.mkdir.policy, - cfg->branches, + rv = ::_mkdir(cfg.func.getattr.policy, + cfg.func.mkdir.policy, + cfg.branches, fusepath_, mode_, fc->umask); if(rv == -EROFS) { - Config::Write()->branches.find_and_set_mode_ro(); - rv = ::_mkdir(cfg->func.getattr.policy, - cfg->func.mkdir.policy, - cfg->branches, + cfg.branches.find_and_set_mode_ro(); + rv = ::_mkdir(cfg.func.getattr.policy, + cfg.func.mkdir.policy, + cfg.branches, fusepath_, mode_, fc->umask); diff --git a/src/fuse_mknod.cpp b/src/fuse_mknod.cpp index e3806fbf..d7af33b2 100644 --- a/src/fuse_mknod.cpp +++ b/src/fuse_mknod.cpp @@ -137,23 +137,22 @@ FUSE::mknod(const char *fusepath_, dev_t rdev_) { int rv; - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - rv = ::_mknod(cfg->func.getattr.policy, - cfg->func.mknod.policy, - cfg->branches, + rv = ::_mknod(cfg.func.getattr.policy, + cfg.func.mknod.policy, + cfg.branches, fusepath_, mode_, fc->umask, rdev_); if(rv == -EROFS) { - Config::Write()->branches.find_and_set_mode_ro(); - rv = ::_mknod(cfg->func.getattr.policy, - cfg->func.mknod.policy, - cfg->branches, + cfg.branches.find_and_set_mode_ro(); + rv = ::_mknod(cfg.func.getattr.policy, + cfg.func.mknod.policy, + cfg.branches, fusepath_, mode_, fc->umask, diff --git a/src/fuse_open.cpp b/src/fuse_open.cpp index 91d513a9..78a73ebd 100644 --- a/src/fuse_open.cpp +++ b/src/fuse_open.cpp @@ -138,16 +138,16 @@ _calculate_flush(FlushOnClose const flushonclose_, static void -_config_to_ffi_flags(Config::Read &cfg_, +_config_to_ffi_flags(Config &cfg_, const int tid_, fuse_file_info_t *ffi_) { - switch(cfg_->cache_files) + switch(cfg.cache_files) { case CacheFiles::ENUM::LIBFUSE: - ffi_->direct_io = cfg_->direct_io; - ffi_->keep_cache = cfg_->kernel_cache; - ffi_->auto_cache = cfg_->auto_cache; + ffi_->direct_io = cfg.direct_io; + ffi_->keep_cache = cfg.kernel_cache; + ffi_->auto_cache = cfg.auto_cache; break; case CacheFiles::ENUM::OFF: ffi_->direct_io = 1; @@ -173,7 +173,7 @@ _config_to_ffi_flags(Config::Read &cfg_, std::string proc_name; proc_name = procfs::get_name(tid_); - if(cfg_->cache_files_process_names.count(proc_name) == 0) + if(cfg.cache_files_process_names.count(proc_name) == 0) { ffi_->direct_io = 1; ffi_->keep_cache = 0; @@ -188,7 +188,7 @@ _config_to_ffi_flags(Config::Read &cfg_, break; } - if(cfg_->parallel_direct_writes == true) + if(cfg.parallel_direct_writes == true) ffi_->parallel_direct_writes = ffi_->direct_io; } @@ -286,23 +286,22 @@ _open_for_insert_lambda(const fuse_context *fc_, { int rv; FileInfo *fi; - Config::Read cfg; const ugid::Set ugid(fc_->uid,fc_->gid); ::_config_to_ffi_flags(cfg,fc_->pid,ffi_); - if(cfg->writeback_cache) + if(cfg.writeback_cache) ::_tweak_flags_writeback_cache(&ffi_->flags); - ffi_->noflush = !::_calculate_flush(cfg->flushonclose, + ffi_->noflush = !::_calculate_flush(cfg.flushonclose, ffi_->flags); - rv = ::_open(cfg->func.open.policy, - cfg->branches, + rv = ::_open(cfg.func.open.policy, + cfg.branches, fusepath_, ffi_, - cfg->link_cow, - cfg->nfsopenhack); + cfg.link_cow, + cfg.nfsopenhack); if(rv < 0) return rv; @@ -312,7 +311,7 @@ _open_for_insert_lambda(const fuse_context *fc_, of_->ref_count = 1; of_->fi = fi; - switch(_(cfg->passthrough,ffi_->flags)) + switch(_(cfg.passthrough,ffi_->flags)) { case _(Passthrough::ENUM::RO,O_RDONLY): case _(Passthrough::ENUM::WO,O_WRONLY): @@ -343,15 +342,14 @@ _open_for_update_lambda(const fuse_context *fc_, State::OpenFile *of_) { int rv; - Config::Read cfg; const ugid::Set ugid(fc_->uid,fc_->gid); ::_config_to_ffi_flags(cfg,fc_->pid,ffi_); - if(cfg->writeback_cache) + if(cfg.writeback_cache) ::_tweak_flags_writeback_cache(&ffi_->flags); - ffi_->noflush = !::_calculate_flush(cfg->flushonclose, + ffi_->noflush = !::_calculate_flush(cfg.flushonclose, ffi_->flags); rv = ::_open_fd(of_->fi->fd, diff --git a/src/fuse_opendir.cpp b/src/fuse_opendir.cpp index 54265b52..b0262e41 100644 --- a/src/fuse_opendir.cpp +++ b/src/fuse_opendir.cpp @@ -14,30 +14,27 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "fuse_opendir.hpp" + #include "config.hpp" #include "dirinfo.hpp" #include "fuse.h" -namespace FUSE +int +FUSE::opendir(const char *fusepath_, + fuse_file_info_t *ffi_) { - int - opendir(const char *fusepath_, - fuse_file_info_t *ffi_) - { - Config::Read cfg; - - ffi_->fh = reinterpret_cast(new DirInfo(fusepath_)); + ffi_->fh = reinterpret_cast(new DirInfo(fusepath_)); - ffi_->noflush = true; + ffi_->noflush = true; - if(cfg->cache_readdir) - { - ffi_->keep_cache = true; - ffi_->cache_readdir = true; - } + if(cfg.cache_readdir) + { + ffi_->keep_cache = true; + ffi_->cache_readdir = true; + } - return 0; - } + return 0; } diff --git a/src/fuse_readdir.cpp b/src/fuse_readdir.cpp index 69e2f06f..af12504e 100644 --- a/src/fuse_readdir.cpp +++ b/src/fuse_readdir.cpp @@ -29,23 +29,16 @@ #include -/* - The _initialized stuff is not pretty but easiest way to deal with - the fact that mergerfs is doing arg parsing and setting up of things - (including thread pools) before the daemonizing - */ int FUSE::readdir(const fuse_file_info_t *ffi_, fuse_dirents_t *buf_) { - Config::Write cfg; - - return cfg->readdir(ffi_,buf_); + return cfg.readdir(ffi_,buf_); } FUSE::ReadDir::ReadDir(const std::string_view s_) - : _str(new std::string()) + : _str() { from_string(s_); } @@ -71,8 +64,11 @@ FUSE::ReadDir::from_string(const std::string_view str_) return -EINVAL; tmp_str = std::make_shared(str_); - std::atomic_store(&_str,tmp_str); + + if(_initialized == false) + return 0; + std::atomic_store(&_impl,tmp_readdir); return 0; @@ -102,11 +98,6 @@ _handle_ENOENT(const fuse_file_info_t *ffi_, return 0; } -/* - Yeah... if not initialized it will crash... ¯\_(ツ)_/¯ - This will be resolved once initialization of internal objects and - handling of input is better separated. -*/ int FUSE::ReadDir::operator()(const fuse_file_info_t *ffi_, fuse_dirents_t *buf_) @@ -115,6 +106,7 @@ FUSE::ReadDir::operator()(const fuse_file_info_t *ffi_, std::shared_ptr readdir; readdir = std::atomic_load(&_impl); + assert(readdir); rv = (*readdir)(ffi_,buf_); if(rv == -ENOENT) @@ -122,3 +114,14 @@ FUSE::ReadDir::operator()(const fuse_file_info_t *ffi_, return rv; } + +void +FUSE::ReadDir::initialize() +{ + std::shared_ptr str; + + str = std::atomic_load(&_str); + _initialized = true; + + from_string(*str); +} diff --git a/src/fuse_readdir.hpp b/src/fuse_readdir.hpp index e332b9e3..abc800aa 100644 --- a/src/fuse_readdir.hpp +++ b/src/fuse_readdir.hpp @@ -32,6 +32,11 @@ namespace FUSE fuse_dirents_t *buf); } +// The 'initialize' feature is ugly but required currently as when +// using mount.mergerfs the process will fork so if readdir needs to +// spawn threads it needs to do so after the fork. Longer term need to +// do argument/config file validation in main() and actual resource +// initialization in fuse_init(). namespace FUSE { class ReadDir : public ToFromString @@ -47,7 +52,11 @@ namespace FUSE int operator()(fuse_file_info_t const *ffi, fuse_dirents_t *buf); + public: + void initialize(); + private: + bool _initialized = false; std::shared_ptr _str; std::shared_ptr _impl; }; diff --git a/src/fuse_readdir_cor.cpp b/src/fuse_readdir_cor.cpp index afc1ad7a..82684e6e 100644 --- a/src/fuse_readdir_cor.cpp +++ b/src/fuse_readdir_cor.cpp @@ -206,12 +206,11 @@ int FUSE::ReadDirCOR::operator()(const fuse_file_info_t *ffi_, fuse_dirents_t *buf_) { - Config::Read cfg; DirInfo *di = reinterpret_cast(ffi_->fh); const fuse_context *fc = fuse_get_context(); return l::concurrent_readdir(_tp, - cfg->branches, + cfg.branches, di->fusepath, buf_, fc->uid, diff --git a/src/fuse_readdir_cosr.cpp b/src/fuse_readdir_cosr.cpp index 7e03e1d0..7246b242 100644 --- a/src/fuse_readdir_cosr.cpp +++ b/src/fuse_readdir_cosr.cpp @@ -210,12 +210,11 @@ int FUSE::ReadDirCOSR::operator()(fuse_file_info_t const *ffi_, fuse_dirents_t *buf_) { - Config::Read cfg; DirInfo *di = reinterpret_cast(ffi_->fh); const fuse_context *fc = fuse_get_context(); return l::readdir(_tp, - cfg->branches, + cfg.branches, di->fusepath, buf_, fc->uid, diff --git a/src/fuse_readdir_factory.cpp b/src/fuse_readdir_factory.cpp index 1d8b09a6..f0ed63d1 100644 --- a/src/fuse_readdir_factory.cpp +++ b/src/fuse_readdir_factory.cpp @@ -87,6 +87,19 @@ _read_cfg(const std::string_view str_, max_queue_depth_ = max_queue_depth; } +bool +FUSE::ReadDirFactory::valid(const std::string_view str_) +{ + int concurrency; + int max_queue_depth; + std::string type; + + ::_read_cfg(str_,type,concurrency,max_queue_depth); + + return ((type == "seq") || + (type == "cosr") || + (type == "cor")); +} std::shared_ptr FUSE::ReadDirFactory::make(const std::string_view str_) diff --git a/src/fuse_readdir_factory.hpp b/src/fuse_readdir_factory.hpp index c085695e..8b19531d 100644 --- a/src/fuse_readdir_factory.hpp +++ b/src/fuse_readdir_factory.hpp @@ -29,6 +29,7 @@ namespace FUSE class ReadDirFactory { public: + static bool valid(const std::string_view str); static std::shared_ptr make(const std::string_view str); }; } diff --git a/src/fuse_readdir_seq.cpp b/src/fuse_readdir_seq.cpp index 4382f4f6..9def08cd 100644 --- a/src/fuse_readdir_seq.cpp +++ b/src/fuse_readdir_seq.cpp @@ -111,12 +111,11 @@ int FUSE::ReadDirSeq::operator()(fuse_file_info_t const *ffi_, fuse_dirents_t *buf_) { - Config::Read cfg; DirInfo *di = reinterpret_cast(ffi_->fh); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_readdir(cfg->branches, + return ::_readdir(cfg.branches, di->fusepath, buf_); } diff --git a/src/fuse_readlink.cpp b/src/fuse_readlink.cpp index 263dd0fb..42f9d71d 100644 --- a/src/fuse_readlink.cpp +++ b/src/fuse_readlink.cpp @@ -121,15 +121,14 @@ FUSE::readlink(const char *fusepath_, char *buf_, size_t size_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_readlink(cfg->func.readlink.policy, - cfg->branches, + return ::_readlink(cfg.func.readlink.policy, + cfg.branches, fusepath_, buf_, size_, - cfg->symlinkify, - cfg->symlinkify_timeout); + cfg.symlinkify, + cfg.symlinkify_timeout); } diff --git a/src/fuse_release.cpp b/src/fuse_release.cpp index 32c1e607..c39deb2b 100644 --- a/src/fuse_release.cpp +++ b/src/fuse_release.cpp @@ -93,10 +93,9 @@ int _release(const fuse_context *fc_, const fuse_file_info_t *ffi_) { - Config::Read cfg; FileInfo *fi = reinterpret_cast(ffi_->fh); - return ::_release(fc_,fi,cfg->dropcacheonclose); + return ::_release(fc_,fi,cfg.dropcacheonclose); } int diff --git a/src/fuse_removexattr.cpp b/src/fuse_removexattr.cpp index 350b2c7c..ad189492 100644 --- a/src/fuse_removexattr.cpp +++ b/src/fuse_removexattr.cpp @@ -96,20 +96,18 @@ int FUSE::removexattr(const char *fusepath_, const char *attrname_) { - Config::Read cfg; - if(Config::is_ctrl_file(fusepath_)) return -ENOATTR; - if(cfg->xattr.to_int()) - return -cfg->xattr.to_int(); + if(cfg.xattr.to_int()) + return -cfg.xattr.to_int(); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_removexattr(cfg->func.removexattr.policy, - cfg->func.getxattr.policy, - cfg->branches, + return ::_removexattr(cfg.func.removexattr.policy, + cfg.func.getxattr.policy, + cfg.branches, fusepath_, attrname_); } diff --git a/src/fuse_rename.cpp b/src/fuse_rename.cpp index eb1b122f..321958bf 100644 --- a/src/fuse_rename.cpp +++ b/src/fuse_rename.cpp @@ -36,6 +36,7 @@ #include #include +namespace stdfs = std::filesystem; static bool @@ -72,16 +73,16 @@ int _rename_create_path(const Policy::Search &searchPolicy_, const Policy::Action &actionPolicy_, const Branches::Ptr &branches_, - const std::filesystem::path &oldfusepath_, - const std::filesystem::path &newfusepath_) + const stdfs::path &oldfusepath_, + const stdfs::path &newfusepath_) { int rv; Err err; StrVec toremove; std::vector newbranches; std::vector oldbranches; - std::filesystem::path oldfullpath; - std::filesystem::path newfullpath; + stdfs::path oldfullpath; + stdfs::path newfullpath; rv = actionPolicy_(branches_,oldfusepath_,oldbranches); if(rv < 0) @@ -130,15 +131,15 @@ static int _rename_preserve_path(const Policy::Action &actionPolicy_, const Branches::Ptr &branches_, - const std::filesystem::path &oldfusepath_, - const std::filesystem::path &newfusepath_) + const stdfs::path &oldfusepath_, + const stdfs::path &newfusepath_) { int rv; bool success; StrVec toremove; std::vector oldbranches; - std::filesystem::path oldfullpath; - std::filesystem::path newfullpath; + stdfs::path oldfullpath; + stdfs::path newfullpath; rv = actionPolicy_(branches_,oldfusepath_,oldbranches); if(rv < 0) @@ -181,10 +182,10 @@ _rename_preserve_path(const Policy::Action &actionPolicy_, static void _rename_exdev_rename_back(const std::vector &branches_, - const std::filesystem::path &oldfusepath_) + const stdfs::path &oldfusepath_) { - std::filesystem::path oldpath; - std::filesystem::path newpath; + stdfs::path oldpath; + stdfs::path newpath; for(auto &branch : branches_) { @@ -203,12 +204,12 @@ static int _rename_exdev_rename_target(const Policy::Action &actionPolicy_, const Branches::Ptr &ibranches_, - const std::filesystem::path &oldfusepath_, + const stdfs::path &oldfusepath_, std::vector &obranches_) { int rv; - std::filesystem::path clonesrc; - std::filesystem::path clonetgt; + stdfs::path clonesrc; + stdfs::path clonetgt; rv = actionPolicy_(ibranches_,oldfusepath_,obranches_); if(rv < 0) @@ -251,12 +252,12 @@ static int _rename_exdev_rel_symlink(const Policy::Action &actionPolicy_, const Branches::Ptr &branches_, - const std::filesystem::path &oldfusepath_, - const std::filesystem::path &newfusepath_) + const stdfs::path &oldfusepath_, + const stdfs::path &newfusepath_) { int rv; - std::filesystem::path target; - std::filesystem::path linkpath; + stdfs::path target; + stdfs::path linkpath; std::vector branches; rv = ::_rename_exdev_rename_target(actionPolicy_,branches_,oldfusepath_,branches); @@ -279,13 +280,13 @@ static int _rename_exdev_abs_symlink(const Policy::Action &actionPolicy_, const Branches::Ptr &branches_, - const std::filesystem::path &mount_, - const std::filesystem::path &oldfusepath_, - const std::filesystem::path &newfusepath_) + const stdfs::path &mount_, + const stdfs::path &oldfusepath_, + const stdfs::path &newfusepath_) { int rv; - std::filesystem::path target; - std::filesystem::path linkpath; + stdfs::path target; + stdfs::path linkpath; std::vector branches; rv = ::_rename_exdev_rename_target(actionPolicy_,branches_,oldfusepath_,branches); @@ -306,23 +307,23 @@ _rename_exdev_abs_symlink(const Policy::Action &actionPolicy_, static int -_rename_exdev(Config::Read &cfg_, - const std::filesystem::path &oldfusepath_, - const std::filesystem::path &newfusepath_) +_rename_exdev(Config &cfg_, + const stdfs::path &oldfusepath_, + const stdfs::path &newfusepath_) { - switch(cfg_->rename_exdev) + switch(cfg_.rename_exdev) { case RenameEXDEV::ENUM::PASSTHROUGH: return -EXDEV; case RenameEXDEV::ENUM::REL_SYMLINK: - return ::_rename_exdev_rel_symlink(cfg_->func.rename.policy, - cfg_->branches, + return ::_rename_exdev_rel_symlink(cfg_.func.rename.policy, + cfg_.branches, oldfusepath_, newfusepath_); case RenameEXDEV::ENUM::ABS_SYMLINK: - return ::_rename_exdev_abs_symlink(cfg_->func.rename.policy, - cfg_->branches, - cfg_->mountpoint, + return ::_rename_exdev_abs_symlink(cfg_.func.rename.policy, + cfg_.branches, + cfg_.mountpoint, oldfusepath_, newfusepath_); } @@ -332,19 +333,19 @@ _rename_exdev(Config::Read &cfg_, static int -_rename(Config::Read &cfg_, - const std::filesystem::path &oldpath_, - const std::filesystem::path &newpath_) +_rename(Config &cfg_, + const stdfs::path &oldpath_, + const stdfs::path &newpath_) { - if(cfg_->func.create.policy.path_preserving() && !cfg_->ignorepponrename) - return ::_rename_preserve_path(cfg_->func.rename.policy, - cfg_->branches, + if(cfg_.func.create.policy.path_preserving() && !cfg_.ignorepponrename) + return ::_rename_preserve_path(cfg_.func.rename.policy, + cfg_.branches, oldpath_, newpath_); - return ::_rename_create_path(cfg_->func.getattr.policy, - cfg_->func.rename.policy, - cfg_->branches, + return ::_rename_create_path(cfg_.func.getattr.policy, + cfg_.func.rename.policy, + cfg_.branches, oldpath_, newpath_); } @@ -354,9 +355,8 @@ FUSE::rename(const char *oldfusepath_, const char *newfusepath_) { int rv; - Config::Read cfg; - std::filesystem::path oldfusepath(oldfusepath_); - std::filesystem::path newfusepath(newfusepath_); + stdfs::path oldfusepath(oldfusepath_); + stdfs::path newfusepath(newfusepath_); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); diff --git a/src/fuse_rmdir.cpp b/src/fuse_rmdir.cpp index 96af78e7..560fb464 100644 --- a/src/fuse_rmdir.cpp +++ b/src/fuse_rmdir.cpp @@ -97,12 +97,11 @@ _rmdir(const Policy::Action &actionFunc_, int FUSE::rmdir(const char *fusepath_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_rmdir(cfg->func.rmdir.policy, - cfg->branches, - cfg->follow_symlinks, + return ::_rmdir(cfg.func.rmdir.policy, + cfg.branches, + cfg.follow_symlinks, fusepath_); } diff --git a/src/fuse_setxattr.cpp b/src/fuse_setxattr.cpp index 82b93fcf..a9d7d350 100644 --- a/src/fuse_setxattr.cpp +++ b/src/fuse_setxattr.cpp @@ -80,7 +80,6 @@ _setxattr_ctrl_file(const char *attrname_, { int rv; std::string key; - Config::Write cfg; if(!Config::is_mergerfs_xattr(attrname_)) return -ENOATTR; @@ -91,17 +90,17 @@ _setxattr_ctrl_file(const char *attrname_, key = Config::prune_ctrl_xattr(attrname_); - if(cfg->has_key(key) == false) + if(cfg.has_key(key) == false) return -ENOATTR; if((flags_ & XATTR_CREATE) == XATTR_CREATE) return -EEXIST; - rv = cfg->set(key,std::string{attrval_,attrvalsize_}); + rv = cfg.set(key,std::string{attrval_,attrvalsize_}); if(rv < 0) return rv; - fs::statvfs_cache_timeout(cfg->cache_statfs); + fs::statvfs_cache_timeout(cfg.cache_statfs); return rv; } @@ -188,21 +187,19 @@ _setxattr(const char *fusepath_, size_t attrvalsize_, int flags_) { - Config::Read cfg; - - if((cfg->security_capability == false) && + if((cfg.security_capability == false) && ::_is_attrname_security_capability(attrname_)) return -ENOATTR; - if(cfg->xattr.to_int()) - return -cfg->xattr.to_int(); + if(cfg.xattr.to_int()) + return -cfg.xattr.to_int(); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_setxattr(cfg->func.setxattr.policy, - cfg->func.getxattr.policy, - cfg->branches, + return ::_setxattr(cfg.func.setxattr.policy, + cfg.func.getxattr.policy, + cfg.branches, fusepath_, attrname_, attrval_, diff --git a/src/fuse_statfs.cpp b/src/fuse_statfs.cpp index 3869f3f6..9339ac53 100644 --- a/src/fuse_statfs.cpp +++ b/src/fuse_statfs.cpp @@ -148,13 +148,12 @@ int FUSE::statfs(const char *fusepath_, struct statvfs *st_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_statfs(cfg->branches, + return ::_statfs(cfg.branches, fusepath_, - cfg->statfs, - cfg->statfs_ignore, + cfg.statfs, + cfg.statfs_ignore, st_); } diff --git a/src/fuse_statx_supported.icpp b/src/fuse_statx_supported.icpp index 9a1773c6..69d2f6b9 100644 --- a/src/fuse_statx_supported.icpp +++ b/src/fuse_statx_supported.icpp @@ -176,26 +176,25 @@ _statx(const char *fusepath_, fuse_timeouts_t *timeout_) { int rv; - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - rv = ::_statx(cfg->func.getattr.policy, - cfg->branches, + rv = ::_statx(cfg.func.getattr.policy, + cfg.branches, fusepath_, flags_, mask_, st_, - cfg->symlinkify, - cfg->symlinkify_timeout, - cfg->follow_symlinks); + cfg.symlinkify, + cfg.symlinkify_timeout, + cfg.follow_symlinks); if((rv < 0) && Config::is_rootdir(fusepath_)) return ::_statx_fake_root(st_); timeout_->entry = ((rv >= 0) ? - cfg->cache_entry : - cfg->cache_negative_entry); - timeout_->attr = cfg->cache_attr; + cfg.cache_entry : + cfg.cache_negative_entry); + timeout_->attr = cfg.cache_attr; return rv; } diff --git a/src/fuse_symlink.cpp b/src/fuse_symlink.cpp index a09fd87e..b3161966 100644 --- a/src/fuse_symlink.cpp +++ b/src/fuse_symlink.cpp @@ -128,22 +128,21 @@ FUSE::symlink(const char *target_, fuse_timeouts_t *timeouts_) { int rv; - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - rv = ::_symlink(cfg->func.getattr.policy, - cfg->func.symlink.policy, - cfg->branches, + rv = ::_symlink(cfg.func.getattr.policy, + cfg.func.symlink.policy, + cfg.branches, target_, linkpath_, st_); if(rv == -EROFS) { - Config::Write()->branches.find_and_set_mode_ro(); - rv = ::_symlink(cfg->func.getattr.policy, - cfg->func.symlink.policy, - cfg->branches, + cfg.branches.find_and_set_mode_ro(); + rv = ::_symlink(cfg.func.getattr.policy, + cfg.func.symlink.policy, + cfg.branches, target_, linkpath_, st_); @@ -151,13 +150,13 @@ FUSE::symlink(const char *target_, if(timeouts_ != NULL) { - switch(cfg->follow_symlinks) + switch(cfg.follow_symlinks) { case FollowSymlinks::ENUM::NEVER: timeouts_->entry = ((rv >= 0) ? - cfg->cache_entry : - cfg->cache_negative_entry); - timeouts_->attr = cfg->cache_attr; + cfg.cache_entry : + cfg.cache_negative_entry); + timeouts_->attr = cfg.cache_attr; break; default: timeouts_->entry = 0; diff --git a/src/fuse_truncate.cpp b/src/fuse_truncate.cpp index ec645069..3b33485c 100644 --- a/src/fuse_truncate.cpp +++ b/src/fuse_truncate.cpp @@ -97,13 +97,12 @@ int FUSE::truncate(const char *fusepath_, off_t size_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_truncate(cfg->func.truncate.policy, - cfg->func.getattr.policy, - cfg->branches, + return ::_truncate(cfg.func.truncate.policy, + cfg.func.getattr.policy, + cfg.branches, fusepath_, size_); } diff --git a/src/fuse_unlink.cpp b/src/fuse_unlink.cpp index 0069dfa3..1f549693 100644 --- a/src/fuse_unlink.cpp +++ b/src/fuse_unlink.cpp @@ -68,11 +68,10 @@ _unlink(const Policy::Action &unlinkPolicy_, int FUSE::unlink(const char *fusepath_) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_unlink(cfg->func.unlink.policy, - cfg->branches, + return ::_unlink(cfg.func.unlink.policy, + cfg.branches, fusepath_); } diff --git a/src/fuse_utimens.cpp b/src/fuse_utimens.cpp index a936dd32..2a24b3d9 100644 --- a/src/fuse_utimens.cpp +++ b/src/fuse_utimens.cpp @@ -96,13 +96,12 @@ int FUSE::utimens(const char *fusepath_, const timespec ts_[2]) { - Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return ::_utimens(cfg->func.utimens.policy, - cfg->func.getattr.policy, - cfg->branches, + return ::_utimens(cfg.func.utimens.policy, + cfg.func.getattr.policy, + cfg.branches, fusepath_, ts_); } diff --git a/src/fuse_write.cpp b/src/fuse_write.cpp index d8301f97..2d827f6d 100644 --- a/src/fuse_write.cpp +++ b/src/fuse_write.cpp @@ -46,13 +46,12 @@ _move_and_pwrite(const char *buf_, { int err; ssize_t rv; - Config::Read cfg; - if(cfg->moveonenospc.enabled == false) + if(cfg.moveonenospc.enabled == false) return err_; - rv = fs::movefile_and_open_as_root(cfg->moveonenospc.policy, - cfg->branches, + rv = fs::movefile_and_open_as_root(cfg.moveonenospc.policy, + cfg.branches, fi_->branch.path, fi_->fusepath, fi_->fd); @@ -78,13 +77,12 @@ _move_and_pwriten(char const *buf_, { int err; ssize_t rv; - Config::Read cfg; - if(cfg->moveonenospc.enabled == false) + if(cfg.moveonenospc.enabled == false) return err_; - rv = fs::movefile_and_open_as_root(cfg->moveonenospc.policy, - cfg->branches, + rv = fs::movefile_and_open_as_root(cfg.moveonenospc.policy, + cfg.branches, fi_->branch.path, fi_->fusepath, fi_->fd); diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index 7385056f..b4a02852 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -189,31 +189,31 @@ namespace l static bool - wait_for_mount(const Config::Read &cfg_) + wait_for_mount(const Config &cfg_) { int failures; fs::PathVector paths; std::chrono::milliseconds timeout; - paths = cfg_->branches->to_paths(); + paths = cfg_.branches->to_paths(); SysLog::info("Waiting {} seconds for {} branches to mount", - (uint64_t)cfg_->branches_mount_timeout, + (uint64_t)cfg_.branches_mount_timeout, paths.size()); - timeout = std::chrono::milliseconds(cfg_->branches_mount_timeout * 1000); - failures = fs::wait_for_mount(cfg_->mountpoint, + timeout = std::chrono::milliseconds(cfg_.branches_mount_timeout * 1000); + failures = fs::wait_for_mount(cfg_.mountpoint, paths, timeout); if(failures) { - if(cfg_->branches_mount_timeout_fail) + if(cfg_.branches_mount_timeout_fail) { SysLog::error("{} of {} branches were not mounted" " within the timeout of {}s. Exiting", failures, paths.size(), - (uint64_t)cfg_->branches_mount_timeout); + (uint64_t)cfg_.branches_mount_timeout); return true; } @@ -301,7 +301,6 @@ namespace l char **argv_) { int rv; - Config::Read cfg; Config::ErrVec errs; fuse_args args; fuse_operations ops; @@ -321,7 +320,7 @@ namespace l return 1; } - if(cfg->branches_mount_timeout > 0) + if(cfg.branches_mount_timeout > 0) { bool failure; @@ -339,13 +338,13 @@ namespace l if((count_ % 60) == 0) GIDCache::clear_unused(); }); - l::setup_resources(cfg->scheduling_priority); + l::setup_resources(cfg.scheduling_priority); l::setup_signal_handlers(); l::set_oom_score_adj(); - l::get_fuse_operations(ops,cfg->nullrw); + l::get_fuse_operations(ops,cfg.nullrw); - if(cfg->lazy_umount_mountpoint) - l::lazy_umount(cfg->mountpoint); + if(cfg.lazy_umount_mountpoint) + l::lazy_umount(cfg.mountpoint); rv = fuse_main(args.argc, args.argv, diff --git a/src/option_parser.cpp b/src/option_parser.cpp index 4e6b86ce..ea3df578 100644 --- a/src/option_parser.cpp +++ b/src/option_parser.cpp @@ -82,30 +82,30 @@ _set_kv_option(const std::string &key_, static void -_set_fuse_threads(Config::Write &cfg_) +_set_fuse_threads(Config &cfg_) { - fuse_config_set_read_thread_count(cfg_->fuse_read_thread_count); - fuse_config_set_process_thread_count(cfg_->fuse_process_thread_count); - fuse_config_set_process_thread_queue_depth(cfg_->fuse_process_thread_queue_depth); - fuse_config_set_pin_threads(cfg_->fuse_pin_threads); + fuse_config_set_read_thread_count(cfg_.fuse_read_thread_count); + fuse_config_set_process_thread_count(cfg_.fuse_process_thread_count); + fuse_config_set_process_thread_queue_depth(cfg_.fuse_process_thread_queue_depth); + fuse_config_set_pin_threads(cfg_.fuse_pin_threads); } static void -_set_fsname(Config::Write &cfg_, - fuse_args *args_) +_set_fsname(Config &cfg_, + fuse_args *args_) { - if(cfg_->fsname->empty()) + if(cfg_.fsname->empty()) { vector paths; - cfg_->branches->to_paths(paths); + cfg_.branches->to_paths(paths); if(paths.size() > 0) - cfg_->fsname = str::remove_common_prefix_and_join(paths,':'); + cfg_.fsname = str::remove_common_prefix_and_join(paths,':'); } - ::_set_kv_option("fsname",cfg_->fsname,args_); + ::_set_kv_option("fsname",cfg_.fsname,args_); } static @@ -117,10 +117,10 @@ _set_subtype(fuse_args *args_) static void -_set_default_options(fuse_args *args_, - Config::Write &cfg_) +_set_default_options(fuse_args *args_, + Config &cfg_) { - if(cfg_->kernel_permissions_check) + if(cfg_.kernel_permissions_check) ::_set_option("default_permissions",args_); if(geteuid() == 0) @@ -161,7 +161,7 @@ _should_ignore(const std::string &key_) static int -_parse_and_process_kv_arg(Config::Write &cfg_, +_parse_and_process_kv_arg(Config &cfg_, Config::ErrVec *errs_, const std::string &key_, const std::string &val_) @@ -172,7 +172,7 @@ _parse_and_process_kv_arg(Config::Write &cfg_, rv = 0; if(key == "config") - return ((cfg_->from_file(val_,errs_) < 0) ? 1 : 0); + return ((cfg_.from_file(val_,errs_) < 0) ? 1 : 0); ef(key == "attr_timeout") key = "cache.attr"; ef(key == "entry_timeout") @@ -192,10 +192,10 @@ _parse_and_process_kv_arg(Config::Write &cfg_, ef(::_should_ignore(key_)) return 0; - if(cfg_->has_key(key) == false) + if(cfg_.has_key(key) == false) return 1; - rv = cfg_->set_raw(key,val); + rv = cfg_.set_raw(key,val); if(rv) errs_->push_back({rv,key+'='+val}); @@ -204,7 +204,7 @@ _parse_and_process_kv_arg(Config::Write &cfg_, static int -_process_opt(Config::Write &cfg_, +_process_opt(Config &cfg_, Config::ErrVec *errs_, const std::string &arg_) { @@ -220,7 +220,7 @@ _process_opt(Config::Write &cfg_, static int -_process_branches(Config::Write &cfg_, +_process_branches(Config &cfg_, Config::ErrVec *errs_, const char *arg_) { @@ -228,7 +228,7 @@ _process_branches(Config::Write &cfg_, string arg; arg = arg_; - rv = cfg_->set_raw("branches",arg); + rv = cfg_.set_raw("branches",arg); if(rv) errs_->push_back({rv,"branches="+arg}); @@ -237,7 +237,7 @@ _process_branches(Config::Write &cfg_, static int -_process_mount(Config::Write &cfg_, +_process_mount(Config &cfg_, Config::ErrVec *errs_, const char *arg_) { @@ -245,7 +245,7 @@ _process_mount(Config::Write &cfg_, string arg; arg = arg_; - rv = cfg_->set_raw("mount",arg); + rv = cfg_.set_raw("mount",arg); if(rv) errs_->push_back({rv,"mount="+arg}); @@ -254,26 +254,26 @@ _process_mount(Config::Write &cfg_, static void -_postprocess_passthrough(Config::Write &cfg_) +_postprocess_passthrough(Config &cfg_) { - if(cfg_->passthrough == Passthrough::ENUM::OFF) + if(cfg_.passthrough == Passthrough::ENUM::OFF) return; - if(cfg_->cache_files == CacheFiles::ENUM::OFF) + if(cfg_.cache_files == CacheFiles::ENUM::OFF) { SysLog::warning("'cache.files' can not be 'off' when using 'passthrough'." " Setting 'cache.files=full'"); - cfg_->cache_files = CacheFiles::ENUM::FULL; + cfg_.cache_files = CacheFiles::ENUM::FULL; } - if(cfg_->writeback_cache == true) + if(cfg_.writeback_cache == true) { SysLog::warning("'cache.writeback' can not be enabled when using 'passthrough'." " Setting 'cache.writeback=false'"); - cfg_->writeback_cache = false; + cfg_.writeback_cache = false; } - if(cfg_->moveonenospc.enabled == true) + if(cfg_.moveonenospc.enabled == true) { SysLog::warning("`moveonenospc` will not function when `passthrough` is enabled"); } @@ -295,7 +295,6 @@ _option_processor(void *data_, int key_, fuse_args *outargs_) { - Config::Write cfg; Config::ErrVec *errs = (Config::ErrVec*)data_; switch(key_) @@ -304,7 +303,7 @@ _option_processor(void *data_, return ::_process_opt(cfg,errs,arg_); case FUSE_OPT_KEY_NONOPT: - if(cfg->branches->empty()) + if(cfg.branches->empty()) return ::_process_branches(cfg,errs,arg_); else return ::_process_mount(cfg,errs,arg_); @@ -345,15 +344,15 @@ _option_processor(void *data_, static void -_check_for_mount_loop(Config::Write &cfg_, +_check_for_mount_loop(Config &cfg_, Config::ErrVec *errs_) { fs::Path mount; fs::PathVector branches; std::error_code ec; - mount = *cfg_->mountpoint; - branches = cfg_->branches->to_paths(); + mount = *cfg_.mountpoint; + branches = cfg_.branches->to_paths(); for(const auto &branch : branches) { if(std::filesystem::equivalent(branch,mount,ec)) @@ -369,25 +368,25 @@ _check_for_mount_loop(Config::Write &cfg_, static void -_print_warnings(Config::Write &cfg_) +_print_warnings(Config &cfg_) { - if(cfg_->passthrough != Passthrough::ENUM::OFF) + if(cfg_.passthrough != Passthrough::ENUM::OFF) { - if(cfg_->cache_files == CacheFiles::ENUM::OFF) + if(cfg_.cache_files == CacheFiles::ENUM::OFF) { SysLog::warning("'cache.files' can not be 'off' when using 'passthrough'." " Setting 'cache.files=auto-full'"); - cfg_->cache_files = CacheFiles::ENUM::AUTO_FULL; + cfg_.cache_files = CacheFiles::ENUM::AUTO_FULL; } - if(cfg_->writeback_cache == true) + if(cfg_.writeback_cache == true) { SysLog::warning("'cache.writeback' can not be enabled when using 'passthrough'." " Setting 'cache.writeback=false'"); - cfg_->writeback_cache = false; + cfg_.writeback_cache = false; } - if(cfg_->moveonenospc.enabled == true) + if(cfg_.moveonenospc.enabled == true) { SysLog::warning("`moveonenospc` will not function when `passthrough` is enabled"); } @@ -396,10 +395,10 @@ _print_warnings(Config::Write &cfg_) static void -_cleanup_options(Config::Write &cfg_) +_cleanup_options(Config &cfg_) { - if(!cfg_->symlinkify) - cfg_->symlinkify_timeout = -1; + if(!cfg_.symlinkify) + cfg_.symlinkify_timeout = -1; } namespace options @@ -408,7 +407,6 @@ namespace options parse(fuse_args *args_, Config::ErrVec *errs_) { - Config::Write cfg; const struct fuse_opt opts[] = { FUSE_OPT_KEY("-h",MERGERFS_OPT_HELP), @@ -424,9 +422,9 @@ namespace options opts, ::_option_processor); - if(cfg->branches->empty()) + if(cfg.branches->empty()) errs_->push_back({0,"branches not set"}); - if(cfg->mountpoint->empty()) + if(cfg.mountpoint->empty()) errs_->push_back({0,"mountpoint not set"}); ::_postprocess_passthrough(cfg); @@ -438,6 +436,6 @@ namespace options ::_print_warnings(cfg); ::_cleanup_options(cfg); - cfg->finish_initializing(); + cfg.finish_initializing(); } } diff --git a/src/state.cpp b/src/state.cpp index 30a01f2e..1614fea6 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -64,3 +64,16 @@ State::set(const std::string &key_, return i->second.set(val_); } + +int +State::valid(const std::string &key_, + const std::string_view val_) +{ + std::map::iterator i; + + i = _getset.find(key_); + if((i == _getset.end()) || (!i->second.valid)) + return -ENOATTR; + + return i->second.valid(val_); +} diff --git a/src/state.hpp b/src/state.hpp index 97e338f0..6fb8e504 100644 --- a/src/state.hpp +++ b/src/state.hpp @@ -36,6 +36,7 @@ public: { std::function get; std::function set; + std::function valid; }; void set_getset(const std::string &name, @@ -45,6 +46,8 @@ public: std::string &val); int set(const std::string &key, const std::string_view val); + int valid(const std::string &key, + const std::string_view val); public: using OpenFileMap = boost::concurrent_flat_map; diff --git a/src/thread_info.hpp b/src/thread_info.hpp new file mode 100644 index 00000000..eb0dc52a --- /dev/null +++ b/src/thread_info.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "fs_lstat.hpp" + +namespace thread_info +{ + static + inline + int + process_count() + { + int rv; + struct stat st; + + rv = fs::lstat("/proc/self/task",&st); + if(rv < 0) + return rv; + + return (st.st_nlink - 2); + } +}