Add ability to set readahead of mergerfs and branches

This commit is contained in:
Antonio SJ Musumeci 2023-02-28 23:10:36 -05:00
parent 6e845b337a
commit 486c5d3734
8 changed files with 188 additions and 7 deletions

View File

@ -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
fails with EXDEV optionally move the file to a special directory and
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
and underlying filesystem). (default: false)
* **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 tiered cache drives
* 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
please contact trapexit so he may investigate further. Please test

View File

@ -265,6 +265,10 @@ instead.
rename fails with EXDEV optionally move the file to a special directory
and symlink to it.
.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
kernel and underlying filesystem).
(default: false)
@ -1982,11 +1986,7 @@ use tiered cache drives
.IP \[bu] 2
use LVM and LVM cache to place a SSD in front of your HDDs
.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
If you come across a setting that significantly impacts performance
please contact trapexit so he may investigate further.

View File

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

View File

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

86
src/fs_readahead.cpp Normal file
View File

@ -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 Normal file
View File

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

View File

@ -16,9 +16,15 @@
#include "config.hpp"
#include "ugid.hpp"
#include "fs_readahead.hpp"
#include "syslog.hpp"
#include "fmt/core.h"
#include "fuse.h"
#include <thread>
namespace l
{
@ -77,6 +83,49 @@ namespace l
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
@ -104,6 +153,8 @@ namespace FUSE
conn_->want &= ~FUSE_CAP_POSIX_LOCKS;
conn_->want &= ~FUSE_CAP_FLOCK_LOCKS;
l::spawn_thread_to_set_readahead();
return NULL;
}
}

View File

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