mirror of
https://github.com/trapexit/mergerfs.git
synced 2024-11-22 11:02:35 +08:00
add statfs cache
This commit is contained in:
parent
f42bd8666e
commit
5be7e007ce
|
@ -85,6 +85,7 @@ mergerfs does **not** support the copy-on-write (CoW) behavior found in **aufs**
|
|||
* **func.<func>=<policy>**: sets the specific FUSE function's policy. See below for the list of value types. Example: **func.getattr=newest**
|
||||
* **category.<category>=<policy>**: Sets policy of all FUSE functions in the provided category. Example: **category.create=mfs**
|
||||
* **cache.open=<int>**: 'open' policy cache timeout in seconds. (default: 0)
|
||||
* **cache.statfs=<int>**: 'statfs' cache timeout in seconds. (default: 0)
|
||||
|
||||
**NOTE:** Options are evaluated in the order listed so if the options are **func.rmdir=rand,category.action=ff** the **action** category setting will override the **rmdir** setting.
|
||||
|
||||
|
@ -501,6 +502,13 @@ The `open` policy cache will cache the result of an `open` policy for a particul
|
|||
This cache is useful in cases like that of **Transmission** which has a "open, read/write, close" pattern (which is much more costly due to the FUSE overhead than normal.)
|
||||
|
||||
|
||||
#### statfs caching
|
||||
|
||||
Of the syscalls used by mergerfs in policies the `statfs` / `statvfs` call is perhaps the most expensive. It's used to find out the available space of a drive and whether it is mounted read-only. Depending on the setup and usage pattern these queries can be relatively costly. When `cache.statfs` is enabled all calls to `statfs` by a policy will be cached for the number of seconds its set to.
|
||||
|
||||
Example: If the create policy is `mfs` and the timeout is 60 then for that 60 seconds the same drive will be returned as the target for creates because the available space won't be updated for that time.
|
||||
|
||||
|
||||
#### writeback caching
|
||||
|
||||
writeback caching is a technique for improving write speeds by batching writes at a faster device and then bulk writing to the slower device. With FUSE the kernel will wait for a number of writes to be made and then send it to the filesystem as one request. mergerfs currently uses a slightly modified and vendored libfuse 2.9.7 which does not support writeback caching. However, a prototype port to libfuse 3.x has been made and the writeback cache appears to work as expected (though performance improvements greatly depend on the way the client app writes data). Once the port is complete and thoroughly tested writeback caching will be available.
|
||||
|
|
|
@ -214,6 +214,9 @@ Example: \f[B]category.create=mfs\f[]
|
|||
.IP \[bu] 2
|
||||
\f[B]cache.open=\f[]: \[aq]open\[aq] policy cache timeout in seconds.
|
||||
(default: 0)
|
||||
.IP \[bu] 2
|
||||
\f[B]cache.statfs=\f[]: \[aq]statfs\[aq] cache timeout in seconds.
|
||||
(default: 0)
|
||||
.PP
|
||||
\f[B]NOTE:\f[] Options are evaluated in the order listed so if the
|
||||
options are \f[B]func.rmdir=rand,category.action=ff\f[] the
|
||||
|
@ -1054,6 +1057,20 @@ expired entries.
|
|||
This cache is useful in cases like that of \f[B]Transmission\f[] which
|
||||
has a "open, read/write, close" pattern (which is much more costly due
|
||||
to the FUSE overhead than normal.)
|
||||
.SS statfs caching
|
||||
.PP
|
||||
Of the syscalls used by mergerfs in policies the \f[C]statfs\f[] /
|
||||
\f[C]statvfs\f[] call is perhaps the most expensive.
|
||||
It\[aq]s used to find out the available space of a drive and whether it
|
||||
is mounted read\-only.
|
||||
Depending on the setup and usage pattern these queries can be relatively
|
||||
costly.
|
||||
When \f[C]cache.statfs\f[] is enabled all calls to \f[C]statfs\f[] by a
|
||||
policy will be cached for the number of seconds its set to.
|
||||
.PP
|
||||
Example: If the create policy is \f[C]mfs\f[] and the timeout is 60 then
|
||||
for that 60 seconds the same drive will be returned as the target for
|
||||
creates because the available space won\[aq]t be updated for that time.
|
||||
.SS writeback caching
|
||||
.PP
|
||||
writeback caching is a technique for improving write speeds by batching
|
||||
|
|
50
src/fs.cpp
50
src/fs.cpp
|
@ -26,11 +26,10 @@
|
|||
#include "fs_attr.hpp"
|
||||
#include "fs_base_realpath.hpp"
|
||||
#include "fs_base_stat.hpp"
|
||||
#include "fs_base_statvfs.hpp"
|
||||
#include "fs_exists.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "fs_xattr.hpp"
|
||||
#include "statvfs_util.hpp"
|
||||
#include "str.hpp"
|
||||
|
||||
using std::string;
|
||||
|
@ -38,48 +37,6 @@ using std::vector;
|
|||
|
||||
namespace fs
|
||||
{
|
||||
int
|
||||
readonly(const string *path_,
|
||||
bool *readonly_)
|
||||
{
|
||||
int rv;
|
||||
struct statvfs st;
|
||||
|
||||
rv = fs::statvfs(*path_,st);
|
||||
if(rv == 0)
|
||||
*readonly_ = StatVFS::readonly(st);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
spaceavail(const string *path_,
|
||||
uint64_t *spaceavail_)
|
||||
{
|
||||
int rv;
|
||||
struct statvfs st;
|
||||
|
||||
rv = fs::statvfs(*path_,st);
|
||||
if(rv == 0)
|
||||
*spaceavail_ = StatVFS::spaceavail(st);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
spaceused(const string *path_,
|
||||
uint64_t *spaceused_)
|
||||
{
|
||||
int rv;
|
||||
struct statvfs st;
|
||||
|
||||
rv = fs::statvfs(*path_,st);
|
||||
if(rv == 0)
|
||||
*spaceused_ = StatVFS::spaceused(st);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
findallfiles(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
|
@ -171,16 +128,13 @@ namespace fs
|
|||
int rv;
|
||||
uint64_t mfs;
|
||||
uint64_t spaceavail;
|
||||
const string *basepath;
|
||||
const string *mfsbasepath;
|
||||
|
||||
mfs = 0;
|
||||
mfsbasepath = NULL;
|
||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||
{
|
||||
basepath = &basepaths[i];
|
||||
|
||||
rv = fs::spaceavail(basepath,&spaceavail);
|
||||
rv = fs::statvfs_cache_spaceavail(basepaths[i],&spaceavail);
|
||||
if(rv == -1)
|
||||
continue;
|
||||
if(spaceavail < minfreespace)
|
||||
|
|
|
@ -27,15 +27,6 @@ namespace fs
|
|||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
int readonly(const string *path_,
|
||||
bool *readonly_);
|
||||
|
||||
int spaceavail(const string *path_,
|
||||
uint64_t *spaceavail_);
|
||||
|
||||
int spaceused(const string *path_,
|
||||
uint64_t *spaceavail_);
|
||||
|
||||
void findallfiles(const vector<string> &basepaths,
|
||||
const char *fusepath,
|
||||
vector<string> &paths);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
Copyright (c) 2019, 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
|
||||
|
@ -35,35 +35,35 @@ namespace fs
|
|||
static
|
||||
inline
|
||||
int
|
||||
statvfs(const char *path,
|
||||
struct statvfs &st)
|
||||
statvfs(const char *path_,
|
||||
struct statvfs *st_)
|
||||
{
|
||||
return ::statvfs(path,&st);
|
||||
return ::statvfs(path_,st_);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
int
|
||||
statvfs(const std::string &path,
|
||||
struct statvfs &st)
|
||||
statvfs(const std::string &path_,
|
||||
struct statvfs *st_)
|
||||
{
|
||||
return fs::statvfs(path.c_str(),st);
|
||||
return fs::statvfs(path_.c_str(),st_);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
int
|
||||
fstatvfs(const int fd_,
|
||||
struct statvfs &st_)
|
||||
struct statvfs *st_)
|
||||
{
|
||||
return ::fstatvfs(fd_,&st_);
|
||||
return ::fstatvfs(fd_,st_);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
int
|
||||
lstatvfs(const std::string &path_,
|
||||
struct statvfs &st_)
|
||||
struct statvfs *st_)
|
||||
{
|
||||
int fd;
|
||||
int rv;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "fs_base_statvfs.hpp"
|
||||
#include "fs_info_t.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "statvfs_util.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
|
@ -37,7 +38,7 @@ namespace fs
|
|||
int rv;
|
||||
struct statvfs st;
|
||||
|
||||
rv = fs::statvfs(*path_,st);
|
||||
rv = fs::statvfs_cache(path_->c_str(),&st);
|
||||
if(rv == 0)
|
||||
{
|
||||
info_->readonly = StatVFS::readonly(st);
|
||||
|
|
145
src/fs_statvfs_cache.cpp
Normal file
145
src/fs_statvfs_cache.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2016, 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_base_statvfs.hpp"
|
||||
#include "statvfs_util.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
struct Element
|
||||
{
|
||||
uint64_t time;
|
||||
struct statvfs st;
|
||||
};
|
||||
|
||||
typedef std::map<std::string,Element> statvfs_cache;
|
||||
|
||||
static uint64_t g_timeout = 0;
|
||||
static statvfs_cache g_cache;
|
||||
static pthread_mutex_t g_cache_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
namespace local
|
||||
{
|
||||
static
|
||||
uint64_t
|
||||
get_time(void)
|
||||
{
|
||||
uint64_t rv;
|
||||
struct timeval now;
|
||||
|
||||
::gettimeofday(&now,NULL);
|
||||
|
||||
rv = now.tv_sec;
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
namespace fs
|
||||
{
|
||||
uint64_t
|
||||
statvfs_cache_timeout(void)
|
||||
{
|
||||
return g_timeout;
|
||||
}
|
||||
|
||||
void
|
||||
statvfs_cache_timeout(const uint64_t timeout_)
|
||||
{
|
||||
g_timeout = timeout_;
|
||||
}
|
||||
|
||||
int
|
||||
statvfs_cache(const char *path_,
|
||||
struct statvfs *st_)
|
||||
{
|
||||
int rv;
|
||||
Element *e;
|
||||
uint64_t now;
|
||||
|
||||
if(g_timeout == 0)
|
||||
return fs::statvfs(path_,st_);
|
||||
|
||||
rv = 0;
|
||||
now = local::get_time();
|
||||
|
||||
pthread_mutex_lock(&g_cache_lock);
|
||||
|
||||
e = &g_cache[path_];
|
||||
|
||||
if((now - e->time) > g_timeout)
|
||||
{
|
||||
e->time = now;
|
||||
rv = fs::statvfs(path_,&e->st);
|
||||
}
|
||||
|
||||
*st_ = e->st;
|
||||
|
||||
pthread_mutex_unlock(&g_cache_lock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
statvfs_cache_readonly(const std::string &path_,
|
||||
bool *readonly_)
|
||||
{
|
||||
int rv;
|
||||
struct statvfs st;
|
||||
|
||||
rv = fs::statvfs_cache(path_.c_str(),&st);
|
||||
if(rv == 0)
|
||||
*readonly_ = StatVFS::readonly(st);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
statvfs_cache_spaceavail(const std::string &path_,
|
||||
uint64_t *spaceavail_)
|
||||
{
|
||||
int rv;
|
||||
struct statvfs st;
|
||||
|
||||
rv = fs::statvfs_cache(path_.c_str(),&st);
|
||||
if(rv == 0)
|
||||
*spaceavail_ = StatVFS::spaceavail(st);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
statvfs_cache_spaceused(const std::string &path_,
|
||||
uint64_t *spaceused_)
|
||||
{
|
||||
int rv;
|
||||
struct statvfs st;
|
||||
|
||||
rv = fs::statvfs_cache(path_.c_str(),&st);
|
||||
if(rv == 0)
|
||||
*spaceused_ = StatVFS::spaceused(st);
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
44
src/fs_statvfs_cache.hpp
Normal file
44
src/fs_statvfs_cache.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2019, 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 <stdint.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
namespace fs
|
||||
{
|
||||
uint64_t
|
||||
statvfs_cache_timeout(void);
|
||||
void
|
||||
statvfs_cache_timeout(const uint64_t timeout_);
|
||||
|
||||
int
|
||||
statvfs_cache(const char *path_,
|
||||
struct statvfs *st_);
|
||||
|
||||
int
|
||||
statvfs_cache_readonly(const std::string &path_,
|
||||
bool *readonly_);
|
||||
|
||||
int
|
||||
statvfs_cache_spaceavail(const std::string &path_,
|
||||
uint64_t *spaceavail_);
|
||||
|
||||
int
|
||||
statvfs_cache_spaceused(const std::string &path_,
|
||||
uint64_t *spaceused_);
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
#include "errno.hpp"
|
||||
#include "fs_base_getxattr.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "rwlock.hpp"
|
||||
#include "str.hpp"
|
||||
#include "ugid.hpp"
|
||||
|
@ -308,6 +309,8 @@ _getxattr_controlfile(const Config &config,
|
|||
_getxattr_controlfile_fusefunc_policy(config,attr[3],attrvalue);
|
||||
else if((attr[2] == "cache") && (attr[3] == "open"))
|
||||
_getxattr_controlfile_uint64_t(config.open_cache.timeout,attrvalue);
|
||||
else if((attr[2] == "cache") && (attr[3] == "statfs"))
|
||||
_getxattr_controlfile_uint64_t(fs::statvfs_cache_timeout(),attrvalue);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ _listxattr_controlfile(char *list,
|
|||
buildvector<string>
|
||||
("user.mergerfs.branches")
|
||||
("user.mergerfs.cache.open")
|
||||
("user.mergerfs.cache.statfs")
|
||||
("user.mergerfs.direct_io")
|
||||
("user.mergerfs.dropcacheonclose")
|
||||
("user.mergerfs.ignorepponrename")
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "config.hpp"
|
||||
#include "errno.hpp"
|
||||
#include "fs_glob.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "num.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "str.hpp"
|
||||
|
@ -112,12 +113,12 @@ set_default_options(fuse_args &args)
|
|||
|
||||
static
|
||||
int
|
||||
parse_and_process(const std::string &value,
|
||||
uint64_t &minfreespace)
|
||||
parse_and_process(const std::string &value_,
|
||||
uint64_t &int_)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = num::to_uint64_t(value,minfreespace);
|
||||
rv = num::to_uint64_t(value_,int_);
|
||||
if(rv == -1)
|
||||
return 1;
|
||||
|
||||
|
@ -204,12 +205,30 @@ parse_and_process_statfsignore(const std::string &value_,
|
|||
|
||||
static
|
||||
int
|
||||
parse_and_process_cache(Config &config_,
|
||||
parse_and_process_statfs_cache(const std::string &value_)
|
||||
{
|
||||
int rv;
|
||||
uint64_t timeout;
|
||||
|
||||
rv = num::to_uint64_t(value_,timeout);
|
||||
if(rv == -1)
|
||||
return 1;
|
||||
|
||||
fs::statvfs_cache_timeout(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
parse_and_process_cache(Config &config_,
|
||||
const string &func_,
|
||||
const string &value_)
|
||||
{
|
||||
if(func_ == "open")
|
||||
return parse_and_process(value_,config_.open_cache.timeout);
|
||||
else if(func_ == "statfs")
|
||||
return parse_and_process_statfs_cache(value_);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -352,6 +371,8 @@ usage(void)
|
|||
" -o category.<c>=<p> Set functions in category <c> to <p>\n"
|
||||
" -o cache.open=<int> 'open' policy cache timeout in seconds.\n"
|
||||
" default = 0 (disabled)\n"
|
||||
" -o cache.statfs=<int> 'statfs' cache timeout in seconds. Used by\n"
|
||||
" policies. default = 0 (disabled)\n"
|
||||
" -o direct_io Bypass page caching, may increase write\n"
|
||||
" speeds at the cost of reads. Please read docs\n"
|
||||
" for more details as there are tradeoffs.\n"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "policy_error.hpp"
|
||||
|
||||
|
@ -88,7 +89,7 @@ namespace epall
|
|||
error_and_continue(error,ENOENT);
|
||||
if(branch->ro())
|
||||
error_and_continue(error,EROFS);
|
||||
rv = fs::readonly(&branch->path,&readonly);
|
||||
rv = fs::statvfs_cache_readonly(branch->path,&readonly);
|
||||
if(rv == -1)
|
||||
error_and_continue(error,ENOENT);
|
||||
if(readonly)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "policy_error.hpp"
|
||||
|
||||
|
@ -87,7 +88,7 @@ namespace epff
|
|||
error_and_continue(error,ENOENT);
|
||||
if(branch->ro())
|
||||
error_and_continue(error,EROFS);
|
||||
rv = fs::readonly(&branch->path,&readonly);
|
||||
rv = fs::statvfs_cache_readonly(branch->path,&readonly);
|
||||
if(rv == -1)
|
||||
error_and_continue(error,ENOENT);
|
||||
if(readonly)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "policy_error.hpp"
|
||||
|
||||
|
@ -142,7 +143,7 @@ namespace eplfs
|
|||
|
||||
if(!fs::exists(branch->path,fusepath))
|
||||
continue;
|
||||
rv = fs::spaceavail(&branch->path,&spaceavail);
|
||||
rv = fs::statvfs_cache_spaceavail(branch->path,&spaceavail);
|
||||
if(rv == -1)
|
||||
continue;
|
||||
if(spaceavail > eplfs)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "policy_error.hpp"
|
||||
|
||||
|
@ -142,7 +143,7 @@ namespace eplus
|
|||
|
||||
if(!fs::exists(branch->path,fusepath))
|
||||
continue;
|
||||
rv = fs::spaceused(&branch->path,&spaceused);
|
||||
rv = fs::statvfs_cache_spaceused(branch->path,&spaceused);
|
||||
if(rv == -1)
|
||||
continue;
|
||||
if(spaceused >= eplus)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "policy_error.hpp"
|
||||
|
||||
|
@ -142,7 +143,7 @@ namespace epmfs
|
|||
|
||||
if(!fs::exists(branch->path,fusepath))
|
||||
continue;
|
||||
rv = fs::spaceavail(&branch->path,&spaceavail);
|
||||
rv = fs::statvfs_cache_spaceavail(branch->path,&spaceavail);
|
||||
if(rv == -1)
|
||||
continue;
|
||||
if(spaceavail < epmfs)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "policy_error.hpp"
|
||||
|
||||
|
@ -108,7 +109,7 @@ namespace newest
|
|||
error_and_continue(error,EROFS);
|
||||
if(st.st_mtime < newest)
|
||||
continue;
|
||||
rv = fs::readonly(&branch->path,&readonly);
|
||||
rv = fs::statvfs_cache_readonly(branch->path,&readonly);
|
||||
if(rv == -1)
|
||||
error_and_continue(error,ENOENT);
|
||||
if(readonly)
|
||||
|
|
|
@ -58,7 +58,8 @@ namespace mergerfs
|
|||
const Config &config = Config::get();
|
||||
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
|
||||
|
||||
config.open_cache.cleanup(10);
|
||||
if(config.open_cache.timeout)
|
||||
config.open_cache.cleanup(10);
|
||||
|
||||
return local::release(fi,config.dropcacheonclose);
|
||||
}
|
||||
|
|
|
@ -39,10 +39,7 @@ namespace mergerfs
|
|||
releasedir(const char *fusepath_,
|
||||
fuse_file_info *ffi_)
|
||||
{
|
||||
const Config &config = Config::get();
|
||||
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh);
|
||||
|
||||
config.open_cache.cleanup(10);
|
||||
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh);
|
||||
|
||||
return local::releasedir(di);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "fs_base_setxattr.hpp"
|
||||
#include "fs_glob.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "num.hpp"
|
||||
#include "rv.hpp"
|
||||
#include "rwlock.hpp"
|
||||
|
@ -260,6 +261,21 @@ _setxattr_controlfile_category_policy(Config &config,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_setxattr_statfs_timeout(const string &attrval_,
|
||||
const int flags_)
|
||||
{
|
||||
int rv;
|
||||
uint64_t timeout;
|
||||
|
||||
rv = _setxattr_uint64_t(attrval_,flags_,timeout);
|
||||
if(rv >= 0)
|
||||
fs::statvfs_cache_timeout(timeout);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_setxattr_controlfile(Config &config,
|
||||
|
@ -349,6 +365,8 @@ _setxattr_controlfile(Config &config,
|
|||
return _setxattr_uint64_t(attrval,
|
||||
flags,
|
||||
config.open_cache.timeout);
|
||||
else if((attr[2] == "cache") && (attr[3] == "statfs"))
|
||||
return _setxattr_statfs_timeout(attrval,flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -14,14 +14,6 @@
|
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <fuse.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config.hpp"
|
||||
#include "errno.hpp"
|
||||
#include "fs_base_stat.hpp"
|
||||
|
@ -31,6 +23,14 @@
|
|||
#include "statvfs_util.hpp"
|
||||
#include "ugid.hpp"
|
||||
|
||||
#include <fuse.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
using std::vector;
|
||||
|
@ -108,7 +108,7 @@ _statfs(const Branches &branches_,
|
|||
if(rv == -1)
|
||||
continue;
|
||||
|
||||
rv = fs::lstatvfs(fullpath,stvfs);
|
||||
rv = fs::lstatvfs(fullpath,&stvfs);
|
||||
if(rv == -1)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||
Copyright (c) 2019, 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
|
||||
|
@ -16,10 +16,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
namespace StatVFS
|
||||
{
|
||||
static
|
||||
|
|
Loading…
Reference in New Issue
Block a user