mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-05-02 01:44:03 +08:00
Merge pull request #556 from trapexit/direct
set direct_io per open/create, now runtime configurable
This commit is contained in:
commit
56f7df028b
@ -70,7 +70,6 @@ struct fuse_config {
|
|||||||
int set_mode;
|
int set_mode;
|
||||||
int set_uid;
|
int set_uid;
|
||||||
int set_gid;
|
int set_gid;
|
||||||
int direct_io;
|
|
||||||
int kernel_cache;
|
int kernel_cache;
|
||||||
int auto_cache;
|
int auto_cache;
|
||||||
int intr;
|
int intr;
|
||||||
@ -3138,8 +3137,6 @@ static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
|
|||||||
fuse_fs_release(f->fs, path, fi);
|
fuse_fs_release(f->fs, path, fi);
|
||||||
forget_node(f, e.ino, 1);
|
forget_node(f, e.ino, 1);
|
||||||
} else {
|
} else {
|
||||||
if (f->conf.direct_io)
|
|
||||||
fi->direct_io = 1;
|
|
||||||
if (f->conf.kernel_cache)
|
if (f->conf.kernel_cache)
|
||||||
fi->keep_cache = 1;
|
fi->keep_cache = 1;
|
||||||
|
|
||||||
@ -3215,8 +3212,6 @@ static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
|
|||||||
fuse_prepare_interrupt(f, req, &d);
|
fuse_prepare_interrupt(f, req, &d);
|
||||||
err = fuse_fs_open(f->fs, path, fi);
|
err = fuse_fs_open(f->fs, path, fi);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (f->conf.direct_io)
|
|
||||||
fi->direct_io = 1;
|
|
||||||
if (f->conf.kernel_cache)
|
if (f->conf.kernel_cache)
|
||||||
fi->keep_cache = 1;
|
fi->keep_cache = 1;
|
||||||
|
|
||||||
@ -4385,7 +4380,6 @@ static const struct fuse_opt fuse_lib_opts[] = {
|
|||||||
FUSE_LIB_OPT("hard_remove", hard_remove, 1),
|
FUSE_LIB_OPT("hard_remove", hard_remove, 1),
|
||||||
FUSE_LIB_OPT("use_ino", use_ino, 1),
|
FUSE_LIB_OPT("use_ino", use_ino, 1),
|
||||||
FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
|
FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
|
||||||
FUSE_LIB_OPT("direct_io", direct_io, 1),
|
|
||||||
FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
|
FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
|
||||||
FUSE_LIB_OPT("auto_cache", auto_cache, 1),
|
FUSE_LIB_OPT("auto_cache", auto_cache, 1),
|
||||||
FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
|
FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
|
||||||
@ -4416,7 +4410,6 @@ static void fuse_lib_help(void)
|
|||||||
" -o hard_remove immediate removal (don't hide files)\n"
|
" -o hard_remove immediate removal (don't hide files)\n"
|
||||||
" -o use_ino let filesystem set inode numbers\n"
|
" -o use_ino let filesystem set inode numbers\n"
|
||||||
" -o readdir_ino try to fill in d_ino in readdir\n"
|
" -o readdir_ino try to fill in d_ino in readdir\n"
|
||||||
" -o direct_io use direct I/O\n"
|
|
||||||
" -o kernel_cache cache files in kernel\n"
|
" -o kernel_cache cache files in kernel\n"
|
||||||
" -o [no]auto_cache enable caching based on modification times (off)\n"
|
" -o [no]auto_cache enable caching based on modification times (off)\n"
|
||||||
" -o umask=M set file permissions (octal)\n"
|
" -o umask=M set file permissions (octal)\n"
|
||||||
|
157
src/create.cpp
157
src/create.cpp
@ -14,11 +14,6 @@
|
|||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fuse.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "errno.hpp"
|
#include "errno.hpp"
|
||||||
#include "fileinfo.hpp"
|
#include "fileinfo.hpp"
|
||||||
@ -29,81 +24,92 @@
|
|||||||
#include "rwlock.hpp"
|
#include "rwlock.hpp"
|
||||||
#include "ugid.hpp"
|
#include "ugid.hpp"
|
||||||
|
|
||||||
|
#include <fuse.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using namespace mergerfs;
|
using namespace mergerfs;
|
||||||
|
|
||||||
static
|
namespace local
|
||||||
int
|
|
||||||
_create_core(const string &fullpath,
|
|
||||||
mode_t mode,
|
|
||||||
const mode_t umask,
|
|
||||||
const int flags)
|
|
||||||
{
|
{
|
||||||
if(!fs::acl::dir_has_defaults(fullpath))
|
static
|
||||||
mode &= ~umask;
|
int
|
||||||
|
create_core(const string &fullpath_,
|
||||||
|
mode_t mode_,
|
||||||
|
const mode_t umask_,
|
||||||
|
const int flags_)
|
||||||
|
{
|
||||||
|
if(!fs::acl::dir_has_defaults(fullpath_))
|
||||||
|
mode_ &= ~umask_;
|
||||||
|
|
||||||
return fs::open(fullpath,flags,mode);
|
return fs::open(fullpath_,flags_,mode_);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_create_core(const string &createpath,
|
create_core(const string &createpath_,
|
||||||
const char *fusepath,
|
const char *fusepath_,
|
||||||
const mode_t mode,
|
const mode_t mode_,
|
||||||
const mode_t umask,
|
const mode_t umask_,
|
||||||
const int flags,
|
const int flags_,
|
||||||
uint64_t &fh)
|
uint64_t *fh_)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string fullpath;
|
string fullpath;
|
||||||
|
|
||||||
fs::path::make(&createpath,fusepath,fullpath);
|
fs::path::make(&createpath_,fusepath_,fullpath);
|
||||||
|
|
||||||
rv = _create_core(fullpath,mode,umask,flags);
|
rv = local::create_core(fullpath,mode_,umask_,flags_);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fh = reinterpret_cast<uint64_t>(new FileInfo(rv,fusepath));
|
*fh_ = reinterpret_cast<uint64_t>(new FileInfo(rv,fusepath_));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_create(Policy::Func::Search searchFunc,
|
create(Policy::Func::Search searchFunc_,
|
||||||
Policy::Func::Create createFunc,
|
Policy::Func::Create createFunc_,
|
||||||
const Branches &branches_,
|
const Branches &branches_,
|
||||||
const uint64_t minfreespace,
|
const uint64_t minfreespace_,
|
||||||
const char *fusepath,
|
const char *fusepath_,
|
||||||
const mode_t mode,
|
const mode_t mode_,
|
||||||
const mode_t umask,
|
const mode_t umask_,
|
||||||
const int flags,
|
const int flags_,
|
||||||
uint64_t &fh)
|
uint64_t *fh_)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string fullpath;
|
string fullpath;
|
||||||
string fusedirpath;
|
string fusedirpath;
|
||||||
vector<const string*> createpaths;
|
vector<const string*> createpaths;
|
||||||
vector<const string*> existingpaths;
|
vector<const string*> existingpaths;
|
||||||
|
|
||||||
fusedirpath = fs::path::dirname(fusepath);
|
fusedirpath = fs::path::dirname(fusepath_);
|
||||||
|
|
||||||
rv = searchFunc(branches_,fusedirpath,minfreespace,existingpaths);
|
rv = searchFunc_(branches_,fusedirpath,minfreespace_,existingpaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = createFunc(branches_,fusedirpath,minfreespace,createpaths);
|
rv = createFunc_(branches_,fusedirpath,minfreespace_,createpaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = fs::clonepath_as_root(*existingpaths[0],*createpaths[0],fusedirpath);
|
rv = fs::clonepath_as_root(*existingpaths[0],*createpaths[0],fusedirpath);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
return _create_core(*createpaths[0],
|
return local::create_core(*createpaths[0],
|
||||||
fusepath,
|
fusepath_,
|
||||||
mode,umask,flags,fh);
|
mode_,
|
||||||
|
umask_,
|
||||||
|
flags_,
|
||||||
|
fh_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
@ -111,24 +117,25 @@ namespace mergerfs
|
|||||||
namespace fuse
|
namespace fuse
|
||||||
{
|
{
|
||||||
int
|
int
|
||||||
create(const char *fusepath,
|
create(const char *fusepath_,
|
||||||
mode_t mode,
|
mode_t mode_,
|
||||||
fuse_file_info *ffi)
|
fuse_file_info *ffi_)
|
||||||
{
|
{
|
||||||
const fuse_context *fc = fuse_get_context();
|
const fuse_context *fc = fuse_get_context();
|
||||||
const Config &config = Config::get(fc);
|
const Config &config = Config::get(fc);
|
||||||
const ugid::Set ugid(fc->uid,fc->gid);
|
const ugid::Set ugid(fc->uid,fc->gid);
|
||||||
const rwlock::ReadGuard readlock(&config.branches_lock);
|
const rwlock::ReadGuard readlock(&config.branches_lock);
|
||||||
|
|
||||||
return _create(config.getattr,
|
ffi_->direct_io = config.direct_io;
|
||||||
config.create,
|
return local::create(config.getattr,
|
||||||
config.branches,
|
config.create,
|
||||||
config.minfreespace,
|
config.branches,
|
||||||
fusepath,
|
config.minfreespace,
|
||||||
mode,
|
fusepath_,
|
||||||
fc->umask,
|
mode_,
|
||||||
ffi->flags,
|
fc->umask,
|
||||||
ffi->fh);
|
ffi_->flags,
|
||||||
|
&ffi_->fh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,16 @@ namespace fs
|
|||||||
base += suffix;
|
base += suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
make(const string &base_,
|
||||||
|
const char *suffix_,
|
||||||
|
string *output_)
|
||||||
|
{
|
||||||
|
*output_ = base_;
|
||||||
|
*output_ += suffix_;
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
make(const string *base,
|
make(const string *base,
|
||||||
|
@ -14,17 +14,6 @@
|
|||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fuse.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <set>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "errno.hpp"
|
#include "errno.hpp"
|
||||||
#include "fs_base_getxattr.hpp"
|
#include "fs_base_getxattr.hpp"
|
||||||
@ -34,6 +23,17 @@
|
|||||||
#include "ugid.hpp"
|
#include "ugid.hpp"
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
|
||||||
|
#include <fuse.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <set>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static const char SECURITY_CAPABILITY[] = "security.capability";
|
static const char SECURITY_CAPABILITY[] = "security.capability";
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
@ -297,6 +297,8 @@ _getxattr_controlfile(const Config &config,
|
|||||||
_getxattr_controlfile_version(attrvalue);
|
_getxattr_controlfile_version(attrvalue);
|
||||||
else if(attr[2] == "pid")
|
else if(attr[2] == "pid")
|
||||||
_getxattr_pid(attrvalue);
|
_getxattr_pid(attrvalue);
|
||||||
|
else if(attr[2] == "direct_io")
|
||||||
|
_getxattr_controlfile_bool(config.direct_io,attrvalue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
@ -57,6 +57,7 @@ _listxattr_controlfile(char *list,
|
|||||||
("user.mergerfs.xattr")
|
("user.mergerfs.xattr")
|
||||||
("user.mergerfs.statfs")
|
("user.mergerfs.statfs")
|
||||||
("user.mergerfs.statfs_ignore")
|
("user.mergerfs.statfs_ignore")
|
||||||
|
("user.mergerfs.direct_io")
|
||||||
("user.mergerfs.policies")
|
("user.mergerfs.policies")
|
||||||
("user.mergerfs.version")
|
("user.mergerfs.version")
|
||||||
("user.mergerfs.pid");
|
("user.mergerfs.pid");
|
||||||
|
@ -70,7 +70,6 @@ namespace local
|
|||||||
static
|
static
|
||||||
void
|
void
|
||||||
get_fuse_operations(struct fuse_operations &ops,
|
get_fuse_operations(struct fuse_operations &ops,
|
||||||
const bool direct_io,
|
|
||||||
const bool nullrw)
|
const bool nullrw)
|
||||||
{
|
{
|
||||||
ops.flag_nullpath_ok = true;
|
ops.flag_nullpath_ok = true;
|
||||||
@ -105,9 +104,7 @@ namespace local
|
|||||||
ops.poll = NULL;
|
ops.poll = NULL;
|
||||||
ops.read = (nullrw ?
|
ops.read = (nullrw ?
|
||||||
mergerfs::fuse::read_null :
|
mergerfs::fuse::read_null :
|
||||||
(direct_io ?
|
mergerfs::fuse::read);
|
||||||
mergerfs::fuse::read_direct_io :
|
|
||||||
mergerfs::fuse::read));
|
|
||||||
ops.read_buf = (nullrw ?
|
ops.read_buf = (nullrw ?
|
||||||
NULL :
|
NULL :
|
||||||
mergerfs::fuse::read_buf);
|
mergerfs::fuse::read_buf);
|
||||||
@ -127,9 +124,7 @@ namespace local
|
|||||||
ops.utimens = mergerfs::fuse::utimens;
|
ops.utimens = mergerfs::fuse::utimens;
|
||||||
ops.write = (nullrw ?
|
ops.write = (nullrw ?
|
||||||
mergerfs::fuse::write_null :
|
mergerfs::fuse::write_null :
|
||||||
(direct_io ?
|
mergerfs::fuse::write);
|
||||||
mergerfs::fuse::write_direct_io :
|
|
||||||
mergerfs::fuse::write));
|
|
||||||
ops.write_buf = (nullrw ?
|
ops.write_buf = (nullrw ?
|
||||||
mergerfs::fuse::write_buf_null :
|
mergerfs::fuse::write_buf_null :
|
||||||
mergerfs::fuse::write_buf);
|
mergerfs::fuse::write_buf);
|
||||||
@ -168,9 +163,7 @@ namespace mergerfs
|
|||||||
mergerfs::options::parse(args,config);
|
mergerfs::options::parse(args,config);
|
||||||
|
|
||||||
local::setup_resources();
|
local::setup_resources();
|
||||||
local::get_fuse_operations(ops,
|
local::get_fuse_operations(ops,config.nullrw);
|
||||||
config.direct_io,
|
|
||||||
config.nullrw);
|
|
||||||
|
|
||||||
return fuse_main(args.argc,
|
return fuse_main(args.argc,
|
||||||
args.argv,
|
args.argv,
|
||||||
|
92
src/open.cpp
92
src/open.cpp
@ -14,8 +14,6 @@
|
|||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fuse.h>
|
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "errno.hpp"
|
#include "errno.hpp"
|
||||||
#include "fileinfo.hpp"
|
#include "fileinfo.hpp"
|
||||||
@ -25,58 +23,63 @@
|
|||||||
#include "rwlock.hpp"
|
#include "rwlock.hpp"
|
||||||
#include "ugid.hpp"
|
#include "ugid.hpp"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fuse.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using mergerfs::Policy;
|
using mergerfs::Policy;
|
||||||
|
|
||||||
static
|
namespace local
|
||||||
int
|
|
||||||
_open_core(const string *basepath_,
|
|
||||||
const char *fusepath_,
|
|
||||||
const int flags_,
|
|
||||||
const bool link_cow_,
|
|
||||||
uint64_t &fh_)
|
|
||||||
{
|
{
|
||||||
int fd;
|
static
|
||||||
string fullpath;
|
int
|
||||||
|
open_core(const string &basepath_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const int flags_,
|
||||||
|
const bool link_cow_,
|
||||||
|
uint64_t *fh_)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
fs::path::make(basepath_,fusepath_,fullpath);
|
fs::path::make(basepath_,fusepath_,&fullpath);
|
||||||
|
|
||||||
if(link_cow_ && fs::cow::is_eligible(fullpath.c_str(),flags_))
|
if(link_cow_ && fs::cow::is_eligible(fullpath.c_str(),flags_))
|
||||||
fs::cow::break_link(fullpath.c_str());
|
fs::cow::break_link(fullpath.c_str());
|
||||||
|
|
||||||
fd = fs::open(fullpath,flags_);
|
fd = fs::open(fullpath,flags_);
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fh_ = reinterpret_cast<uint64_t>(new FileInfo(fd,fusepath_));
|
*fh_ = reinterpret_cast<uint64_t>(new FileInfo(fd,fusepath_));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_open(Policy::Func::Search searchFunc_,
|
open(Policy::Func::Search searchFunc_,
|
||||||
const Branches &branches_,
|
const Branches &branches_,
|
||||||
const uint64_t minfreespace_,
|
const uint64_t minfreespace_,
|
||||||
const char *fusepath_,
|
const char *fusepath_,
|
||||||
const int flags_,
|
const int flags_,
|
||||||
const bool link_cow_,
|
const bool link_cow_,
|
||||||
uint64_t &fh_)
|
uint64_t *fh_)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
vector<const string*> basepaths;
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
rv = searchFunc_(branches_,fusepath_,minfreespace_,basepaths);
|
rv = searchFunc_(branches_,fusepath_,minfreespace_,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
return _open_core(basepaths[0],fusepath_,flags_,link_cow_,fh_);
|
return local::open_core(*basepaths[0],fusepath_,flags_,link_cow_,fh_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
@ -92,13 +95,14 @@ namespace mergerfs
|
|||||||
const ugid::Set ugid(fc->uid,fc->gid);
|
const ugid::Set ugid(fc->uid,fc->gid);
|
||||||
const rwlock::ReadGuard readlock(&config.branches_lock);
|
const rwlock::ReadGuard readlock(&config.branches_lock);
|
||||||
|
|
||||||
return _open(config.open,
|
ffi_->direct_io = config.direct_io;
|
||||||
config.branches,
|
return local::open(config.open,
|
||||||
config.minfreespace,
|
config.branches,
|
||||||
fusepath_,
|
config.minfreespace,
|
||||||
ffi_->flags,
|
fusepath_,
|
||||||
config.link_cow,
|
ffi_->flags,
|
||||||
ffi_->fh);
|
config.link_cow,
|
||||||
|
&ffi_->fh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,19 @@
|
|||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fuse.h>
|
|
||||||
|
|
||||||
#include "dirinfo.hpp"
|
#include "dirinfo.hpp"
|
||||||
|
|
||||||
|
#include <fuse.h>
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
{
|
{
|
||||||
int
|
int
|
||||||
opendir(const char *fusepath,
|
opendir(const char *fusepath_,
|
||||||
fuse_file_info *ffi)
|
fuse_file_info *ffi_)
|
||||||
{
|
{
|
||||||
ffi->fh = reinterpret_cast<uint64_t>(new DirInfo(fusepath));
|
ffi_->fh = reinterpret_cast<uint64_t>(new DirInfo(fusepath_));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -14,20 +14,6 @@
|
|||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fuse.h>
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "errno.hpp"
|
#include "errno.hpp"
|
||||||
#include "fs_glob.hpp"
|
#include "fs_glob.hpp"
|
||||||
@ -36,6 +22,20 @@
|
|||||||
#include "str.hpp"
|
#include "str.hpp"
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
|
||||||
|
#include <fuse.h>
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using namespace mergerfs;
|
using namespace mergerfs;
|
||||||
@ -211,7 +211,7 @@ parse_and_process_arg(Config &config,
|
|||||||
if(arg == "defaults")
|
if(arg == "defaults")
|
||||||
return (set_default_options(*outargs),0);
|
return (set_default_options(*outargs),0);
|
||||||
else if(arg == "direct_io")
|
else if(arg == "direct_io")
|
||||||
return (config.direct_io=true,1);
|
return (config.direct_io=true,0);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -336,7 +336,7 @@ usage(void)
|
|||||||
" splice_write, splice_move\n"
|
" splice_write, splice_move\n"
|
||||||
" -o func.<f>=<p> Set function <f> to policy <p>\n"
|
" -o func.<f>=<p> Set function <f> to policy <p>\n"
|
||||||
" -o category.<c>=<p> Set functions in category <c> to <p>\n"
|
" -o category.<c>=<p> Set functions in category <c> to <p>\n"
|
||||||
" -o direct_io Bypass additional caching, increases write\n"
|
" -o direct_io Bypass page caching, may increase write\n"
|
||||||
" speeds at the cost of reads. Please read docs\n"
|
" speeds at the cost of reads. Please read docs\n"
|
||||||
" for more details as there are tradeoffs.\n"
|
" for more details as there are tradeoffs.\n"
|
||||||
" -o use_ino Have mergerfs generate inode values rather than\n"
|
" -o use_ino Have mergerfs generate inode values rather than\n"
|
||||||
|
109
src/read.cpp
109
src/read.cpp
@ -14,50 +14,49 @@
|
|||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fuse.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "errno.hpp"
|
#include "errno.hpp"
|
||||||
#include "fileinfo.hpp"
|
#include "fileinfo.hpp"
|
||||||
#include "fs_base_read.hpp"
|
#include "fs_base_read.hpp"
|
||||||
|
|
||||||
static
|
#include <fuse.h>
|
||||||
inline
|
|
||||||
int
|
namespace local
|
||||||
_read(const int fd,
|
|
||||||
void *buf,
|
|
||||||
const size_t count,
|
|
||||||
const off_t offset)
|
|
||||||
{
|
{
|
||||||
int rv;
|
static
|
||||||
|
inline
|
||||||
|
int
|
||||||
|
read_regular(const int fd_,
|
||||||
|
void *buf_,
|
||||||
|
const size_t count_,
|
||||||
|
const off_t offset_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
rv = fs::pread(fd,buf,count,offset);
|
rv = fs::pread(fd_,buf_,count_,offset_);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
if(rv == 0)
|
if(rv == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return count;
|
return count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
inline
|
inline
|
||||||
int
|
int
|
||||||
_read_direct_io(const int fd,
|
read_direct_io(const int fd_,
|
||||||
void *buf,
|
void *buf_,
|
||||||
const size_t count,
|
const size_t count_,
|
||||||
const off_t offset)
|
const off_t offset_)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = fs::pread(fd,buf,count,offset);
|
rv = fs::pread(fd_,buf_,count_,offset_);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
@ -65,38 +64,30 @@ namespace mergerfs
|
|||||||
namespace fuse
|
namespace fuse
|
||||||
{
|
{
|
||||||
int
|
int
|
||||||
read(const char *fusepath,
|
read(const char *fusepath_,
|
||||||
char *buf,
|
char *buf_,
|
||||||
size_t count,
|
size_t count_,
|
||||||
off_t offset,
|
off_t offset_,
|
||||||
fuse_file_info *ffi)
|
fuse_file_info *ffi_)
|
||||||
{
|
{
|
||||||
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
|
FileInfo *fi;
|
||||||
|
|
||||||
return ::_read(fi->fd,buf,count,offset);
|
fi = reinterpret_cast<FileInfo*>(ffi_->fh);
|
||||||
|
|
||||||
|
if(ffi_->direct_io)
|
||||||
|
return local::read_direct_io(fi->fd,buf_,count_,offset_);
|
||||||
|
return local::read_regular(fi->fd,buf_,count_,offset_);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
read_direct_io(const char *fusepath,
|
read_null(const char *fusepath_,
|
||||||
char *buf,
|
char *buf_,
|
||||||
size_t count,
|
size_t count_,
|
||||||
off_t offset,
|
off_t offset_,
|
||||||
fuse_file_info *ffi)
|
fuse_file_info *ffi_)
|
||||||
{
|
|
||||||
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
|
|
||||||
|
|
||||||
return ::_read_direct_io(fi->fd,buf,count,offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
read_null(const char *fusepath,
|
|
||||||
char *buf,
|
|
||||||
size_t count,
|
|
||||||
off_t offset,
|
|
||||||
fuse_file_info *ffi)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
return count;
|
return count_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,6 @@
|
|||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fuse.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "errno.hpp"
|
#include "errno.hpp"
|
||||||
#include "fs_base_setxattr.hpp"
|
#include "fs_base_setxattr.hpp"
|
||||||
@ -33,6 +25,14 @@
|
|||||||
#include "str.hpp"
|
#include "str.hpp"
|
||||||
#include "ugid.hpp"
|
#include "ugid.hpp"
|
||||||
|
|
||||||
|
#include <fuse.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static const char SECURITY_CAPABILITY[] = "security.capability";
|
static const char SECURITY_CAPABILITY[] = "security.capability";
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
@ -323,6 +323,10 @@ _setxattr_controlfile(Config &config,
|
|||||||
return _setxattr_statfsignore(attrval,
|
return _setxattr_statfsignore(attrval,
|
||||||
flags,
|
flags,
|
||||||
config.statfs_ignore);
|
config.statfs_ignore);
|
||||||
|
else if(attr[2] == "direct_io")
|
||||||
|
return _setxattr_bool(attrval,
|
||||||
|
flags,
|
||||||
|
config.direct_io);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
195
src/write.cpp
195
src/write.cpp
@ -33,119 +33,116 @@ using std::vector;
|
|||||||
|
|
||||||
typedef int (*WriteFunc)(const int,const void*,const size_t,const off_t);
|
typedef int (*WriteFunc)(const int,const void*,const size_t,const off_t);
|
||||||
|
|
||||||
static
|
namespace local
|
||||||
bool
|
|
||||||
_out_of_space(const int error)
|
|
||||||
{
|
{
|
||||||
return ((error == ENOSPC) ||
|
static
|
||||||
(error == EDQUOT));
|
bool
|
||||||
|
out_of_space(const int error_)
|
||||||
|
{
|
||||||
|
return ((error_ == ENOSPC) ||
|
||||||
|
(error_ == EDQUOT));
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
write_regular(const int fd_,
|
||||||
|
const void *buf_,
|
||||||
|
const size_t count_,
|
||||||
|
const off_t offset_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = fs::pwrite(fd_,buf_,count_,offset_);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
if(rv == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
write_direct_io(const int fd_,
|
||||||
|
const void *buf_,
|
||||||
|
const size_t count_,
|
||||||
|
const off_t offset_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = fs::pwrite(fd_,buf_,count_,offset_);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
write(WriteFunc func_,
|
||||||
|
const char *buf_,
|
||||||
|
const size_t count_,
|
||||||
|
const off_t offset_,
|
||||||
|
fuse_file_info *ffi_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
FileInfo* fi;
|
||||||
|
|
||||||
|
fi = reinterpret_cast<FileInfo*>(ffi_->fh);
|
||||||
|
|
||||||
|
rv = func_(fi->fd,buf_,count_,offset_);
|
||||||
|
if(local::out_of_space(-rv))
|
||||||
|
{
|
||||||
|
const fuse_context *fc = fuse_get_context();
|
||||||
|
const Config &config = Config::get(fc);
|
||||||
|
|
||||||
|
if(config.moveonenospc)
|
||||||
|
{
|
||||||
|
vector<string> paths;
|
||||||
|
const ugid::Set ugid(0,0);
|
||||||
|
const rwlock::ReadGuard readlock(&config.branches_lock);
|
||||||
|
|
||||||
|
config.branches.to_paths(paths);
|
||||||
|
|
||||||
|
rv = fs::movefile(paths,fi->fusepath,count_,fi->fd);
|
||||||
|
if(rv == -1)
|
||||||
|
return -ENOSPC;
|
||||||
|
|
||||||
|
rv = func_(fi->fd,buf_,count_,offset_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
inline
|
|
||||||
int
|
|
||||||
_write(const int fd,
|
|
||||||
const void *buf,
|
|
||||||
const size_t count,
|
|
||||||
const off_t offset)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
rv = fs::pwrite(fd,buf,count,offset);
|
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
if(rv == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
inline
|
|
||||||
int
|
|
||||||
_write_direct_io(const int fd,
|
|
||||||
const void *buf,
|
|
||||||
const size_t count,
|
|
||||||
const off_t offset)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
rv = fs::pwrite(fd,buf,count,offset);
|
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
{
|
{
|
||||||
static
|
|
||||||
inline
|
|
||||||
int
|
int
|
||||||
write(WriteFunc func,
|
write(const char *fusepath_,
|
||||||
const char *buf,
|
const char *buf_,
|
||||||
const size_t count,
|
size_t count_,
|
||||||
const off_t offset,
|
off_t offset_,
|
||||||
fuse_file_info *ffi)
|
fuse_file_info *ffi_)
|
||||||
{
|
{
|
||||||
int rv;
|
WriteFunc wf;
|
||||||
FileInfo* fi = reinterpret_cast<FileInfo*>(ffi->fh);
|
|
||||||
|
|
||||||
rv = func(fi->fd,buf,count,offset);
|
wf = ((ffi_->direct_io) ?
|
||||||
if(_out_of_space(-rv))
|
local::write_direct_io :
|
||||||
{
|
local::write_regular);
|
||||||
const fuse_context *fc = fuse_get_context();
|
|
||||||
const Config &config = Config::get(fc);
|
|
||||||
|
|
||||||
if(config.moveonenospc)
|
return local::write(wf,buf_,count_,offset_,ffi_);
|
||||||
{
|
|
||||||
vector<string> paths;
|
|
||||||
const ugid::Set ugid(0,0);
|
|
||||||
const rwlock::ReadGuard readlock(&config.branches_lock);
|
|
||||||
|
|
||||||
config.branches.to_paths(paths);
|
|
||||||
|
|
||||||
rv = fs::movefile(paths,fi->fusepath,count,fi->fd);
|
|
||||||
if(rv == -1)
|
|
||||||
return -ENOSPC;
|
|
||||||
|
|
||||||
rv = func(fi->fd,buf,count,offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
write(const char *fusepath,
|
write_null(const char *fusepath_,
|
||||||
const char *buf,
|
const char *buf_,
|
||||||
size_t count,
|
size_t count_,
|
||||||
off_t offset,
|
off_t offset_,
|
||||||
fuse_file_info *ffi)
|
fuse_file_info *ffi_)
|
||||||
{
|
{
|
||||||
return write(_write,buf,count,offset,ffi);
|
return count_;
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
write_direct_io(const char *fusepath,
|
|
||||||
const char *buf,
|
|
||||||
size_t count,
|
|
||||||
off_t offset,
|
|
||||||
fuse_file_info *ffi)
|
|
||||||
{
|
|
||||||
return write(_write_direct_io,buf,count,offset,ffi);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
write_null(const char *fusepath,
|
|
||||||
const char *buf,
|
|
||||||
size_t count,
|
|
||||||
off_t offset,
|
|
||||||
fuse_file_info *ffi)
|
|
||||||
{
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user