Browse Source

Add ability to set readahead of mergerfs and branches

pull/1149/head
Antonio SJ Musumeci 2 years ago
parent
commit
486c5d3734
  1. 5
      README.md
  2. 10
      man/mergerfs.1
  3. 2
      src/config.cpp
  4. 1
      src/config.hpp
  5. 86
      src/fs_readahead.cpp
  6. 39
      src/fs_readahead.hpp
  7. 51
      src/fuse_init.cpp
  8. 1
      src/mergerfs.cpp

5
README.md

@ -211,6 +211,8 @@ These options are the same regardless of whether you use them with the
* **rename-exdev=passthrough|rel-symlink|abs-symlink**: When a rename * **rename-exdev=passthrough|rel-symlink|abs-symlink**: When a rename
fails with EXDEV optionally move the file to a special directory and fails with EXDEV optionally move the file to a special directory and
symlink to it. symlink to it.
* **readahead=UINT**: Set readahead (in kilobytes) for mergerfs and
branches if greater than 0. (default: 0)
* **posix_acl=BOOL**: Enable POSIX ACL support (if supported by kernel * **posix_acl=BOOL**: Enable POSIX ACL support (if supported by kernel
and underlying filesystem). (default: false) and underlying filesystem). (default: false)
* **async_read=BOOL**: Perform reads asynchronously. If disabled or * **async_read=BOOL**: Perform reads asynchronously. If disabled or
@ -1528,8 +1530,7 @@ understand what behaviors it may impact
* use `symlinkify` if your data is largely static and read-only * use `symlinkify` if your data is largely static and read-only
* use tiered cache drives * use tiered cache drives
* use LVM and LVM cache to place a SSD in front of your HDDs * use LVM and LVM cache to place a SSD in front of your HDDs
* if `cache.files` is enabled increase readahead: `echo "1024" > /sys/class/bdi/0:$(stat -c%d /MOUNT)/read_ahead_kb`
* increase readahead on all devices: `ls -1 /sys/class/bdi/*/read_ahead_kb | xargs -n1 -I{} sh -c "echo 1024 > {}"`
* increase readahead: `readahead=1024`
If you come across a setting that significantly impacts performance If you come across a setting that significantly impacts performance
please contact trapexit so he may investigate further. Please test please contact trapexit so he may investigate further. Please test

10
man/mergerfs.1

@ -265,6 +265,10 @@ instead.
rename fails with EXDEV optionally move the file to a special directory rename fails with EXDEV optionally move the file to a special directory
and symlink to it. and symlink to it.
.IP \[bu] 2 .IP \[bu] 2
\f[B]readahead=UINT\f[R]: Set readahead (in kilobytes) for mergerfs and
branches if greater than 0.
(default: 0)
.IP \[bu] 2
\f[B]posix_acl=BOOL\f[R]: Enable POSIX ACL support (if supported by \f[B]posix_acl=BOOL\f[R]: Enable POSIX ACL support (if supported by
kernel and underlying filesystem). kernel and underlying filesystem).
(default: false) (default: false)
@ -1982,11 +1986,7 @@ use tiered cache drives
.IP \[bu] 2 .IP \[bu] 2
use LVM and LVM cache to place a SSD in front of your HDDs use LVM and LVM cache to place a SSD in front of your HDDs
.IP \[bu] 2 .IP \[bu] 2
if \f[C]cache.files\f[R] is enabled increase readahead:
\f[C]echo \[dq]1024\[dq] > /sys/class/bdi/0:$(stat -c%d /MOUNT)/read_ahead_kb\f[R]
.IP \[bu] 2
increase readahead on all devices:
\f[C]ls -1 /sys/class/bdi/*/read_ahead_kb | xargs -n1 -I{} sh -c \[dq]echo 1024 > {}\[dq]\f[R]
increase readahead: \f[C]readahead=1024\f[R]
.PP .PP
If you come across a setting that significantly impacts performance If you come across a setting that significantly impacts performance
please contact trapexit so he may investigate further. please contact trapexit so he may investigate further.

2
src/config.cpp

@ -105,6 +105,7 @@ Config::Config()
nullrw(false), nullrw(false),
pid(::getpid()), pid(::getpid()),
posix_acl(false), posix_acl(false),
readahead(0),
readdir(ReadDir::ENUM::POSIX), readdir(ReadDir::ENUM::POSIX),
readdirplus(false), readdirplus(false),
rename_exdev(RenameEXDEV::ENUM::PASSTHROUGH), rename_exdev(RenameEXDEV::ENUM::PASSTHROUGH),
@ -176,6 +177,7 @@ Config::Config()
_map["nullrw"] = &nullrw; _map["nullrw"] = &nullrw;
_map["pid"] = &pid; _map["pid"] = &pid;
_map["posix_acl"] = &posix_acl; _map["posix_acl"] = &posix_acl;
_map["readahead"] = &readahead;
// _map["readdir"] = &readdir; // _map["readdir"] = &readdir;
_map["readdirplus"] = &readdirplus; _map["readdirplus"] = &readdirplus;
_map["rename-exdev"] = &rename_exdev; _map["rename-exdev"] = &rename_exdev;

1
src/config.hpp

@ -133,6 +133,7 @@ public:
ConfigBOOL nullrw; ConfigBOOL nullrw;
ConfigUINT64 pid; ConfigUINT64 pid;
ConfigBOOL posix_acl; ConfigBOOL posix_acl;
ConfigUINT64 readahead;
ReadDir readdir; ReadDir readdir;
ConfigBOOL readdirplus; ConfigBOOL readdirplus;
RenameEXDEV rename_exdev; RenameEXDEV rename_exdev;

86
src/fs_readahead.cpp

@ -0,0 +1,86 @@
/*
ISC License
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "fs_readahead.hpp"
#include "fmt/core.h"
#include "fs_lstat.hpp"
#include <cstdint>
#include <fstream>
#include <string>
#include <sys/sysmacros.h>
namespace l
{
static
std::string
generate_readahead_sys_path(const std::uint64_t major_,
const std::uint64_t minor_)
{
return fmt::format("/sys/class/bdi/{}:{}/read_ahead_kb",major_,minor_);
}
}
int
fs::readahead(const std::uint64_t major_dev_,
const std::uint64_t minor_dev_,
const std::uint64_t size_in_kb_)
{
std::string syspath;
std::ofstream ofs;
syspath = l::generate_readahead_sys_path(major_dev_,minor_dev_);
ofs.open(syspath);
if(ofs)
{
ofs << fmt::format("{}\n",size_in_kb_);
ofs.close();
}
return 0;
}
int
fs::readahead(const std::uint64_t dev_,
const std::uint64_t size_in_kb_)
{
std::uint32_t major_dev;
std::uint32_t minor_dev;
major_dev = major(dev_);
minor_dev = minor(dev_);
return fs::readahead(major_dev,minor_dev,size_in_kb_);
}
int
fs::readahead(const std::string path_,
const std::uint64_t size_in_kb_)
{
int rv;
struct stat st;
rv = fs::lstat(path_,&st);
if(rv == -1)
return -errno;
return fs::readahead(st.st_dev,size_in_kb_);
}

39
src/fs_readahead.hpp

@ -0,0 +1,39 @@
/*
ISC License
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <cstdint>
#include <string>
namespace fs
{
int
readahead(const std::uint64_t major_dev,
const std::uint64_t minor_dev,
const std::uint64_t size_in_kb);
int
readahead(const std::uint64_t dev,
const std::uint64_t size_in_kb);
int
readahead(const std::string path,
const std::uint64_t size_in_kb);
}

51
src/fuse_init.cpp

@ -16,9 +16,15 @@
#include "config.hpp" #include "config.hpp"
#include "ugid.hpp" #include "ugid.hpp"
#include "fs_readahead.hpp"
#include "syslog.hpp"
#include "fmt/core.h"
#include "fuse.h" #include "fuse.h"
#include <thread>
namespace l namespace l
{ {
@ -77,6 +83,49 @@ namespace l
cfg_->fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ; cfg_->fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
} }
} }
static
void
readahead(const std::string path_,
const int readahead_)
{
int rv;
rv = fs::readahead(path_,readahead_);
if(rv == 0)
syslog_info("%s - readahead set to %d",path_.c_str(),readahead_);
else
syslog_error("%s - unable to set readahead",path_.c_str());
}
static
void
set_readahead_on_mount_and_branches()
{
Config::Read cfg;
Branches::CPtr branches;
if((uint64_t)cfg->readahead == 0)
return;
l::readahead(cfg->mountpoint,cfg->readahead);
branches = cfg->branches;
for(auto const &branch : *branches)
l::readahead(branch.path,cfg->readahead);
}
// Spawn a thread to do this because before init returns calls to
// set the value will block leading to a deadlock. This is just
// easier.
static
void
spawn_thread_to_set_readahead()
{
std::thread readahead_thread(l::set_readahead_on_mount_and_branches);
readahead_thread.detach();
}
} }
namespace FUSE namespace FUSE
@ -104,6 +153,8 @@ namespace FUSE
conn_->want &= ~FUSE_CAP_POSIX_LOCKS; conn_->want &= ~FUSE_CAP_POSIX_LOCKS;
conn_->want &= ~FUSE_CAP_FLOCK_LOCKS; conn_->want &= ~FUSE_CAP_FLOCK_LOCKS;
l::spawn_thread_to_set_readahead();
return NULL; return NULL;
} }
} }

1
src/mergerfs.cpp

@ -14,6 +14,7 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "fs_readahead.hpp"
#include "fs_wait_for_mount.hpp" #include "fs_wait_for_mount.hpp"
#include "syslog.hpp" #include "syslog.hpp"

Loading…
Cancel
Save