mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-04-26 23:14:04 +08:00
Merge pull request #1275 from trapexit/noflush
Add flushonclose feature
This commit is contained in:
commit
7890a4996c
26
README.md
26
README.md
@ -248,7 +248,10 @@ These options are the same regardless of whether you use them with the
|
|||||||
to the same as the process thread count. (default: 0)
|
to the same as the process thread count. (default: 0)
|
||||||
* **pin-threads=STR**: Selects a strategy to pin threads to CPUs
|
* **pin-threads=STR**: Selects a strategy to pin threads to CPUs
|
||||||
(default: unset)
|
(default: unset)
|
||||||
* **scheduling-priority=INT**: Set mergerfs' scheduling
|
* **flush-on-close=never|always|opened-for-write**: Flush data cache
|
||||||
|
on file close. Mostly for when writeback is enabled or merging
|
||||||
|
network filesystems. (default: opened-for-write)
|
||||||
|
* **scheduling-priority=INT**: Set mergerfs' scheduling
|
||||||
priority. Valid values range from -20 to 19. See `setpriority` man
|
priority. Valid values range from -20 to 19. See `setpriority` man
|
||||||
page for more details. (default: -10)
|
page for more details. (default: -10)
|
||||||
* **fsname=STR**: Sets the name of the filesystem as seen in
|
* **fsname=STR**: Sets the name of the filesystem as seen in
|
||||||
@ -926,6 +929,27 @@ The options `statfs` and `statfs_ignore` can be used to modify
|
|||||||
`statfs` behavior.
|
`statfs` behavior.
|
||||||
|
|
||||||
|
|
||||||
|
#### flush-on-close
|
||||||
|
|
||||||
|
https://lkml.kernel.org/linux-fsdevel/20211024132607.1636952-1-amir73il@gmail.com/T/
|
||||||
|
|
||||||
|
By default FUSE would issue a flush before the release of a file
|
||||||
|
descriptor. This was considered a bit aggressive and a feature added
|
||||||
|
to give the FUSE server the ability to choose when that happens.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
* always
|
||||||
|
* never
|
||||||
|
* opened-for-write
|
||||||
|
|
||||||
|
For now it defaults to "opened-for-write" which is less aggressive
|
||||||
|
than the behavior before this feature was added. It should not be a
|
||||||
|
problem because the flush is really only relevant when a file is
|
||||||
|
written to. Given flush is irrelevant for many filesystems in the
|
||||||
|
future a branch specific flag may be added so only files opened on a
|
||||||
|
specific branch would be flushed on close.
|
||||||
|
|
||||||
|
|
||||||
# ERROR HANDLING
|
# ERROR HANDLING
|
||||||
|
|
||||||
POSIX filesystem functions offer a single return code meaning that
|
POSIX filesystem functions offer a single return code meaning that
|
||||||
|
@ -86,6 +86,8 @@ struct fuse_file_info_t
|
|||||||
|
|
||||||
uint32_t parallel_direct_writes:1;
|
uint32_t parallel_direct_writes:1;
|
||||||
|
|
||||||
|
uint32_t noflush:1;
|
||||||
|
|
||||||
/** File handle. May be filled in by filesystem in open().
|
/** File handle. May be filled in by filesystem in open().
|
||||||
Available in all other file operations */
|
Available in all other file operations */
|
||||||
uint64_t fh;
|
uint64_t fh;
|
||||||
|
@ -275,6 +275,8 @@ fill_open(struct fuse_open_out *arg_,
|
|||||||
arg_->open_flags |= FOPEN_CACHE_DIR;
|
arg_->open_flags |= FOPEN_CACHE_DIR;
|
||||||
if(ffi_->parallel_direct_writes)
|
if(ffi_->parallel_direct_writes)
|
||||||
arg_->open_flags |= FOPEN_PARALLEL_DIRECT_WRITES;
|
arg_->open_flags |= FOPEN_PARALLEL_DIRECT_WRITES;
|
||||||
|
if(ffi_->noflush)
|
||||||
|
arg_->open_flags |= FOPEN_NOFLUSH;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -321,11 +321,18 @@ by the number of process threads plus read thread count.
|
|||||||
\f[B]pin-threads=STR\f[R]: Selects a strategy to pin threads to CPUs
|
\f[B]pin-threads=STR\f[R]: Selects a strategy to pin threads to CPUs
|
||||||
(default: unset)
|
(default: unset)
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
|
\f[B]flush-on-close=never|always|opened-for-write\f[R]: Flush data cache
|
||||||
|
on file close.
|
||||||
|
Mostly for when writeback is enabled or merging network filesystems.
|
||||||
|
(default: opened-for-write)
|
||||||
|
.RS 2
|
||||||
|
.IP \[bu] 2
|
||||||
\f[B]scheduling-priority=INT\f[R]: Set mergerfs\[cq] scheduling
|
\f[B]scheduling-priority=INT\f[R]: Set mergerfs\[cq] scheduling
|
||||||
priority.
|
priority.
|
||||||
Valid values range from -20 to 19.
|
Valid values range from -20 to 19.
|
||||||
See \f[C]setpriority\f[R] man page for more details.
|
See \f[C]setpriority\f[R] man page for more details.
|
||||||
(default: -10)
|
(default: -10)
|
||||||
|
.RE
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
\f[B]fsname=STR\f[R]: Sets the name of the filesystem as seen in
|
\f[B]fsname=STR\f[R]: Sets the name of the filesystem as seen in
|
||||||
\f[B]mount\f[R], \f[B]df\f[R], etc.
|
\f[B]mount\f[R], \f[B]df\f[R], etc.
|
||||||
@ -1321,6 +1328,24 @@ be included when checking the mount\[cq]s stats.
|
|||||||
.PP
|
.PP
|
||||||
The options \f[C]statfs\f[R] and \f[C]statfs_ignore\f[R] can be used to
|
The options \f[C]statfs\f[R] and \f[C]statfs_ignore\f[R] can be used to
|
||||||
modify \f[C]statfs\f[R] behavior.
|
modify \f[C]statfs\f[R] behavior.
|
||||||
|
.SS flush-on-close
|
||||||
|
.PP
|
||||||
|
https://lkml.kernel.org/linux-fsdevel/20211024132607.1636952-1-amir73il\[at]gmail.com/T/
|
||||||
|
.PP
|
||||||
|
By default FUSE would issue a flush before the release of a file
|
||||||
|
descriptor.
|
||||||
|
This was considered a bit aggressive and a feature added to give the
|
||||||
|
FUSE server the ability to choose when that happens.
|
||||||
|
.PP
|
||||||
|
Options: * always * never * opened-for-write
|
||||||
|
.PP
|
||||||
|
For now it defaults to \[lq]opened-for-write\[rq] which is less
|
||||||
|
aggressive than the behavior before this feature was added.
|
||||||
|
It should not be a problem because the flush is really only relevant
|
||||||
|
when a file is written to.
|
||||||
|
Given flush is irrelevant for many filesystems in the future a branch
|
||||||
|
specific flag may be added so only files opened on a specific branch
|
||||||
|
would be flushed on close.
|
||||||
.SH ERROR HANDLING
|
.SH ERROR HANDLING
|
||||||
.PP
|
.PP
|
||||||
POSIX filesystem functions offer a single return code meaning that there
|
POSIX filesystem functions offer a single return code meaning that there
|
||||||
|
@ -94,8 +94,9 @@ Config::Config()
|
|||||||
category(func),
|
category(func),
|
||||||
direct_io(false),
|
direct_io(false),
|
||||||
dropcacheonclose(false),
|
dropcacheonclose(false),
|
||||||
fsname(),
|
flushonclose(FlushOnClose::ENUM::ALWAYS),
|
||||||
follow_symlinks(FollowSymlinks::ENUM::NEVER),
|
follow_symlinks(FollowSymlinks::ENUM::NEVER),
|
||||||
|
fsname(),
|
||||||
func(),
|
func(),
|
||||||
fuse_msg_size(FUSE_MAX_MAX_PAGES),
|
fuse_msg_size(FUSE_MAX_MAX_PAGES),
|
||||||
ignorepponrename(false),
|
ignorepponrename(false),
|
||||||
@ -149,6 +150,7 @@ Config::Config()
|
|||||||
_map["category.search"] = &category.search;
|
_map["category.search"] = &category.search;
|
||||||
_map["direct_io"] = &direct_io;
|
_map["direct_io"] = &direct_io;
|
||||||
_map["dropcacheonclose"] = &dropcacheonclose;
|
_map["dropcacheonclose"] = &dropcacheonclose;
|
||||||
|
_map["flush-on-close"] = &flushonclose;
|
||||||
_map["follow-symlinks"] = &follow_symlinks;
|
_map["follow-symlinks"] = &follow_symlinks;
|
||||||
_map["fsname"] = &fsname;
|
_map["fsname"] = &fsname;
|
||||||
_map["func.access"] = &func.access;
|
_map["func.access"] = &func.access;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "branches.hpp"
|
#include "branches.hpp"
|
||||||
#include "category.hpp"
|
#include "category.hpp"
|
||||||
#include "config_cachefiles.hpp"
|
#include "config_cachefiles.hpp"
|
||||||
|
#include "config_flushonclose.hpp"
|
||||||
#include "config_follow_symlinks.hpp"
|
#include "config_follow_symlinks.hpp"
|
||||||
#include "config_inodecalc.hpp"
|
#include "config_inodecalc.hpp"
|
||||||
#include "config_link_exdev.hpp"
|
#include "config_link_exdev.hpp"
|
||||||
@ -116,8 +117,9 @@ public:
|
|||||||
Categories category;
|
Categories category;
|
||||||
ConfigBOOL direct_io;
|
ConfigBOOL direct_io;
|
||||||
ConfigBOOL dropcacheonclose;
|
ConfigBOOL dropcacheonclose;
|
||||||
ConfigSTR fsname;
|
FlushOnClose flushonclose;
|
||||||
FollowSymlinks follow_symlinks;
|
FollowSymlinks follow_symlinks;
|
||||||
|
ConfigSTR fsname;
|
||||||
Funcs func;
|
Funcs func;
|
||||||
ConfigUINT64 fuse_msg_size;
|
ConfigUINT64 fuse_msg_size;
|
||||||
ConfigBOOL ignorepponrename;
|
ConfigBOOL ignorepponrename;
|
||||||
|
54
src/config_flushonclose.cpp
Normal file
54
src/config_flushonclose.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
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 "config_flushonclose.hpp"
|
||||||
|
#include "ef.hpp"
|
||||||
|
#include "errno.hpp"
|
||||||
|
|
||||||
|
template<>
|
||||||
|
std::string
|
||||||
|
FlushOnClose::to_string() const
|
||||||
|
{
|
||||||
|
switch(_data)
|
||||||
|
{
|
||||||
|
case FlushOnClose::ENUM::NEVER:
|
||||||
|
return "never";
|
||||||
|
case FlushOnClose::ENUM::OPENED_FOR_WRITE:
|
||||||
|
return "opened-for-write";
|
||||||
|
case FlushOnClose::ENUM::ALWAYS:
|
||||||
|
return "always";
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
int
|
||||||
|
FlushOnClose::from_string(const std::string &s_)
|
||||||
|
{
|
||||||
|
if(s_ == "never")
|
||||||
|
_data = FlushOnClose::ENUM::NEVER;
|
||||||
|
ef(s_ == "opened-for-write")
|
||||||
|
_data = FlushOnClose::ENUM::OPENED_FOR_WRITE;
|
||||||
|
ef(s_ == "always")
|
||||||
|
_data = FlushOnClose::ENUM::ALWAYS;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
31
src/config_flushonclose.hpp
Normal file
31
src/config_flushonclose.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
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 "enum.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
enum class FlushOnCloseEnum
|
||||||
|
{
|
||||||
|
NEVER,
|
||||||
|
OPENED_FOR_WRITE,
|
||||||
|
ALWAYS
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Enum<FlushOnCloseEnum> FlushOnClose;
|
@ -51,6 +51,31 @@ namespace l
|
|||||||
*flags_ &= ~O_APPEND;
|
*flags_ &= ~O_APPEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
rdonly(const int flags_)
|
||||||
|
{
|
||||||
|
return ((flags_ & O_ACCMODE) == O_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
calculate_flush(FlushOnClose const flushonclose_,
|
||||||
|
int const flags_)
|
||||||
|
{
|
||||||
|
switch(flushonclose_)
|
||||||
|
{
|
||||||
|
case FlushOnCloseEnum::NEVER:
|
||||||
|
return false;
|
||||||
|
case FlushOnCloseEnum::OPENED_FOR_WRITE:
|
||||||
|
return !l::rdonly(flags_);
|
||||||
|
case FlushOnCloseEnum::ALWAYS:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
config_to_ffi_flags(Config::Read &cfg_,
|
config_to_ffi_flags(Config::Read &cfg_,
|
||||||
@ -200,6 +225,9 @@ namespace FUSE
|
|||||||
if(cfg->writeback_cache)
|
if(cfg->writeback_cache)
|
||||||
l::tweak_flags_writeback_cache(&ffi_->flags);
|
l::tweak_flags_writeback_cache(&ffi_->flags);
|
||||||
|
|
||||||
|
ffi_->noflush = !l::calculate_flush(cfg->flushonclose,
|
||||||
|
ffi_->flags);
|
||||||
|
|
||||||
rv = l::create(cfg->func.getattr.policy,
|
rv = l::create(cfg->func.getattr.policy,
|
||||||
cfg->func.create.policy,
|
cfg->func.create.policy,
|
||||||
cfg->branches,
|
cfg->branches,
|
||||||
|
@ -114,6 +114,24 @@ namespace l
|
|||||||
*flags_ &= ~O_APPEND;
|
*flags_ &= ~O_APPEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
calculate_flush(FlushOnClose const flushonclose_,
|
||||||
|
int const flags_)
|
||||||
|
{
|
||||||
|
switch(flushonclose_)
|
||||||
|
{
|
||||||
|
case FlushOnCloseEnum::NEVER:
|
||||||
|
return false;
|
||||||
|
case FlushOnCloseEnum::OPENED_FOR_WRITE:
|
||||||
|
return !l::rdonly(flags_);
|
||||||
|
case FlushOnCloseEnum::ALWAYS:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
config_to_ffi_flags(Config::Read &cfg_,
|
config_to_ffi_flags(Config::Read &cfg_,
|
||||||
@ -236,6 +254,9 @@ namespace FUSE
|
|||||||
if(cfg->writeback_cache)
|
if(cfg->writeback_cache)
|
||||||
l::tweak_flags_writeback_cache(&ffi_->flags);
|
l::tweak_flags_writeback_cache(&ffi_->flags);
|
||||||
|
|
||||||
|
ffi_->noflush = !l::calculate_flush(cfg->flushonclose,
|
||||||
|
ffi_->flags);
|
||||||
|
|
||||||
rv = l::open(cfg->func.open.policy,
|
rv = l::open(cfg->func.open.policy,
|
||||||
cfg->branches,
|
cfg->branches,
|
||||||
fusepath_,
|
fusepath_,
|
||||||
|
@ -30,6 +30,8 @@ namespace FUSE
|
|||||||
|
|
||||||
ffi_->fh = reinterpret_cast<uint64_t>(new DirInfo(fusepath_));
|
ffi_->fh = reinterpret_cast<uint64_t>(new DirInfo(fusepath_));
|
||||||
|
|
||||||
|
ffi_->noflush = true;
|
||||||
|
|
||||||
if(cfg->cache_readdir)
|
if(cfg->cache_readdir)
|
||||||
{
|
{
|
||||||
ffi_->keep_cache = 1;
|
ffi_->keep_cache = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user