mirror of https://github.com/trapexit/mergerfs.git
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 217 additions and 1 deletions
-
12mkdocs/docs/config/func_readdir.md
-
2mkdocs/docs/config/options.md
-
53mkdocs/docs/config/proxy-ioprio.md
-
1mkdocs/mkdocs.yml
-
2src/config.cpp
-
2src/config.hpp
-
33src/config_proxy_ioprio.cpp
-
13src/config_proxy_ioprio.hpp
-
2src/error.hpp
-
2src/fuse_read.cpp
-
3src/fuse_write.cpp
-
73src/ioprio.cpp
-
20src/ioprio.hpp
@ -0,0 +1,53 @@ |
|||
# proxy-ioprio |
|||
|
|||
* type: `BOOL` |
|||
* default: `false` |
|||
* example: `proxy-ioprio=true` |
|||
|
|||
In Linux certain process schedulers have the ability to |
|||
[prioritize](https://man7.org/linux/man-pages/man2/ioprio_set.2.html) |
|||
based on a per thread [IO |
|||
priority](https://www.kernel.org/doc/Documentation/block/ioprio.txt) |
|||
assigned to the software by users using tools such as |
|||
[ionice](https://man7.org/linux/man-pages/man1/ionice.1.html). Since |
|||
such details are not provided by the FUSE protocol, users may not use |
|||
schedulers which support IO priority, and the extra overhead to query |
|||
the priority and set it within mergerfs it does not by default attempt |
|||
to mirror/proxy the value. When enabled however, for all read and |
|||
write requests, mergerfs will query the priority of the requesting |
|||
process/thread and set the same value on the thread within mergerfs |
|||
making the read/write. |
|||
|
|||
This may be useful in situation where the system has high IO load or |
|||
processes are known to have varying priorities. See the [man |
|||
page](https://man7.org/linux/man-pages/man2/ioprio_set.2.html) for |
|||
specific details. |
|||
|
|||
Keep in mind that if no IO scheduler has been set for a thread then by |
|||
default the IO priority will match the CPU nice value which for |
|||
mergerfs is set by [scheduling-priority](options.md). [Nice |
|||
value](https://man7.org/linux/man-pages/man2/getpriority.2.html) |
|||
proxying may be added in a future release. |
|||
|
|||
|
|||
## Conflicts With Other Options |
|||
|
|||
If using [IO passthrough](passthrough.md) there is no reason to set |
|||
this value to `true`. However, since `passthrough` leads to mergerfs |
|||
IO calls being bypassed entirely will have no impact on performance or |
|||
behavior regardless. |
|||
|
|||
When using `passthrough` the IO priority of the client app would be |
|||
used directly given the IO is passed through. |
|||
|
|||
|
|||
## Supported Platforms |
|||
|
|||
Only Linux. This is not supported on FreeBSD. |
|||
|
|||
|
|||
## Performance Impact |
|||
|
|||
Despite the additional syscalls requires the impact appears |
|||
undetectable with larger buffer sizes. At very small buffer sizes |
|||
(such as 512 bytes) there is a noticable but small impact (~1.5%). |
@ -0,0 +1,33 @@ |
|||
#include "config_proxy_ioprio.hpp"
|
|||
|
|||
#include "ioprio.hpp"
|
|||
#include "from_string.hpp"
|
|||
|
|||
|
|||
ProxyIOPrio::ProxyIOPrio(const bool b_) |
|||
{ |
|||
ioprio::enable(b_); |
|||
} |
|||
|
|||
std::string |
|||
ProxyIOPrio::to_string(void) const |
|||
{ |
|||
if(ioprio::enabled()) |
|||
return "true"; |
|||
return "false"; |
|||
} |
|||
|
|||
int |
|||
ProxyIOPrio::from_string(const std::string_view s_) |
|||
{ |
|||
int rv; |
|||
bool enable; |
|||
|
|||
rv = str::from(s_,&enable); |
|||
if(rv) |
|||
return rv; |
|||
|
|||
ioprio::enable(enable); |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,13 @@ |
|||
#pragma once
|
|||
|
|||
#include "tofrom_string.hpp"
|
|||
|
|||
class ProxyIOPrio : public ToFromString |
|||
{ |
|||
public: |
|||
ProxyIOPrio(const bool); |
|||
|
|||
public: |
|||
std::string to_string(void) const final; |
|||
int from_string(const std::string_view) final; |
|||
}; |
@ -0,0 +1,73 @@ |
|||
#include "ioprio.hpp"
|
|||
|
|||
#ifdef __linux__
|
|||
# include <linux/ioprio.h>
|
|||
# include <sys/syscall.h>
|
|||
# include <unistd.h>
|
|||
# include <errno.h>
|
|||
#else
|
|||
#warning "ioprio not supported on this platform"
|
|||
#endif
|
|||
|
|||
thread_local int ioprio::SetFrom::thread_prio = -1; |
|||
bool _enabled = false; |
|||
|
|||
int |
|||
ioprio::get(const int which_, |
|||
const int who_) |
|||
{ |
|||
#ifdef SYS_ioprio_get
|
|||
int rv; |
|||
|
|||
rv = syscall(SYS_ioprio_get,which_,who_); |
|||
|
|||
return ((rv == -1) ? -errno : rv); |
|||
#else
|
|||
return -ENOSUP; |
|||
#endif
|
|||
} |
|||
|
|||
int |
|||
ioprio::set(const int which_, |
|||
const int who_, |
|||
const int ioprio_) |
|||
{ |
|||
#ifdef SYS_ioprio_set
|
|||
int rv; |
|||
|
|||
rv = syscall(SYS_ioprio_set,which_,who_,ioprio_); |
|||
|
|||
return ((rv == -1) ? -errno : rv); |
|||
#else
|
|||
return -ENOSUP; |
|||
#endif
|
|||
} |
|||
|
|||
void |
|||
ioprio::enable(const bool enable_) |
|||
{ |
|||
_enabled = enable_; |
|||
} |
|||
|
|||
bool |
|||
ioprio::enabled() |
|||
{ |
|||
return _enabled; |
|||
} |
|||
|
|||
ioprio::SetFrom::SetFrom(const pid_t pid_) |
|||
{ |
|||
int client_prio; |
|||
|
|||
if(!_enabled) |
|||
return; |
|||
|
|||
client_prio = ioprio::get(IOPRIO_WHO_PROCESS,pid_); |
|||
if(client_prio < 0) |
|||
return; |
|||
if(client_prio == thread_prio) |
|||
return; |
|||
|
|||
thread_prio = client_prio; |
|||
ioprio::set(IOPRIO_WHO_PROCESS,0,client_prio); |
|||
} |
@ -0,0 +1,20 @@ |
|||
#pragma once
|
|||
|
|||
#include <sys/types.h>
|
|||
|
|||
|
|||
namespace ioprio |
|||
{ |
|||
void enable(const bool); |
|||
bool enabled(); |
|||
|
|||
int get(const int which, const int who); |
|||
int set(const int which, const int who, const int ioprio); |
|||
|
|||
struct SetFrom |
|||
{ |
|||
static thread_local int thread_prio; |
|||
|
|||
SetFrom(const pid_t pid); |
|||
}; |
|||
}; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue