Browse Source

Revert removal of readdir init setup, simplify cfg usage (#1520)

pull/1522/head
trapexit 4 weeks ago
committed by GitHub
parent
commit
f64ff9ca1e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      src/config.cpp
  2. 58
      src/config.hpp
  3. 5
      src/fuse_access.cpp
  4. 7
      src/fuse_chmod.cpp
  5. 7
      src/fuse_chown.cpp
  6. 36
      src/fuse_create.cpp
  7. 9
      src/fuse_fgetattr.cpp
  8. 17
      src/fuse_getattr.cpp
  9. 16
      src/fuse_getxattr.cpp
  10. 72
      src/fuse_init.cpp
  11. 5
      src/fuse_ioctl.cpp
  12. 33
      src/fuse_link.cpp
  13. 10
      src/fuse_listxattr.cpp
  14. 15
      src/fuse_mkdir.cpp
  15. 15
      src/fuse_mknod.cpp
  16. 34
      src/fuse_open.cpp
  17. 29
      src/fuse_opendir.cpp
  18. 33
      src/fuse_readdir.cpp
  19. 9
      src/fuse_readdir.hpp
  20. 3
      src/fuse_readdir_cor.cpp
  21. 3
      src/fuse_readdir_cosr.cpp
  22. 13
      src/fuse_readdir_factory.cpp
  23. 1
      src/fuse_readdir_factory.hpp
  24. 3
      src/fuse_readdir_seq.cpp
  25. 9
      src/fuse_readlink.cpp
  26. 3
      src/fuse_release.cpp
  27. 12
      src/fuse_removexattr.cpp
  28. 88
      src/fuse_rename.cpp
  29. 7
      src/fuse_rmdir.cpp
  30. 21
      src/fuse_setxattr.cpp
  31. 7
      src/fuse_statfs.cpp
  32. 17
      src/fuse_statx_supported.icpp
  33. 23
      src/fuse_symlink.cpp
  34. 7
      src/fuse_truncate.cpp
  35. 5
      src/fuse_unlink.cpp
  36. 7
      src/fuse_utimens.cpp
  37. 14
      src/fuse_write.cpp
  38. 25
      src/mergerfs.cpp
  39. 96
      src/option_parser.cpp
  40. 13
      src/state.cpp
  41. 3
      src/state.hpp
  42. 21
      src/thread_info.hpp

3
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
{

58
src/config.hpp

@ -75,32 +75,6 @@ public:
typedef std::vector<Err> 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;

5
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_);
}

7
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_);
}

7
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_);

36
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_);

9
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;
}

17
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;
}

16
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_,

72
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.");
}

5
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<DirInfo*>(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_,

33
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);

10
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_);

15
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);

15
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,

34
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,

29
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<uint64_t>(new DirInfo(fusepath_));
ffi_->fh = reinterpret_cast<uint64_t>(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;
}

33
src/fuse_readdir.cpp

@ -29,23 +29,16 @@
#include <dirent.h>
/*
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<std::string>(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<FUSE::ReadDirBase> 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<std::string> str;
str = std::atomic_load(&_str);
_initialized = true;
from_string(*str);
}

9
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<std::string> _str;
std::shared_ptr<FUSE::ReadDirBase> _impl;
};

3
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<DirInfo*>(ffi_->fh);
const fuse_context *fc = fuse_get_context();
return l::concurrent_readdir(_tp,
cfg->branches,
cfg.branches,
di->fusepath,
buf_,
fc->uid,

3
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<DirInfo*>(ffi_->fh);
const fuse_context *fc = fuse_get_context();
return l::readdir(_tp,
cfg->branches,
cfg.branches,
di->fusepath,
buf_,
fc->uid,

13
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::ReadDirBase>
FUSE::ReadDirFactory::make(const std::string_view str_)

1
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<ReadDirBase> make(const std::string_view str);
};
}

3
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<DirInfo*>(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_);
}

9
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);
}

3
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<FileInfo*>(ffi_->fh);
return ::_release(fc_,fi,cfg->dropcacheonclose);
return ::_release(fc_,fi,cfg.dropcacheonclose);
}
int

12
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_);
}

88
src/fuse_rename.cpp

@ -36,6 +36,7 @@
#include <string>
#include <vector>
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<Branch*> newbranches;
std::vector<Branch*> 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<Branch*> 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<Branch*> &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<Branch*> &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<Branch*> 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<Branch*> 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);

7
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_);
}

21
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_,

7
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_);
}

17
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;
}

23
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;

7
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_);
}

5
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_);
}

7
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_);
}

14
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);

25
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,

96
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<string> 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();
}
}

13
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<std::string,State::GetSet>::iterator i;
i = _getset.find(key_);
if((i == _getset.end()) || (!i->second.valid))
return -ENOATTR;
return i->second.valid(val_);
}

3
src/state.hpp

@ -36,6 +36,7 @@ public:
{
std::function<std::string()> get;
std::function<int(const std::string_view)> set;
std::function<int(const std::string_view)> 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<u64,OpenFile>;

21
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);
}
}
Loading…
Cancel
Save