Browse Source

Merge pull request #556 from trapexit/direct

set direct_io per open/create, now runtime configurable
pull/558/head
trapexit 6 years ago
committed by GitHub
parent
commit
56f7df028b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      libfuse/lib/fuse.c
  2. 167
      src/create.cpp
  3. 10
      src/fs_path.hpp
  4. 24
      src/getxattr.cpp
  5. 1
      src/listxattr.cpp
  6. 13
      src/mergerfs.cpp
  7. 92
      src/open.cpp
  8. 10
      src/opendir.cpp
  9. 32
      src/option_parser.cpp
  10. 107
      src/read.cpp
  11. 20
      src/setxattr.cpp
  12. 177
      src/write.cpp

7
libfuse/lib/fuse.c

@ -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"

167
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
int
_create_core(const string &fullpath,
mode_t mode,
const mode_t umask,
const int flags)
namespace local
{ {
if(!fs::acl::dir_has_defaults(fullpath))
mode &= ~umask;
return fs::open(fullpath,flags,mode);
}
static
int
_create_core(const string &createpath,
const char *fusepath,
const mode_t mode,
const mode_t umask,
const int flags,
uint64_t &fh)
{
int rv;
string fullpath;
fs::path::make(&createpath,fusepath,fullpath);
rv = _create_core(fullpath,mode,umask,flags);
if(rv == -1)
return -errno;
fh = reinterpret_cast<uint64_t>(new FileInfo(rv,fusepath));
static
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 0;
}
return fs::open(fullpath_,flags_,mode_);
}
static
int
_create(Policy::Func::Search searchFunc,
Policy::Func::Create createFunc,
const Branches &branches_,
const uint64_t minfreespace,
const char *fusepath,
const mode_t mode,
const mode_t umask,
const int flags,
uint64_t &fh)
{
int rv;
string fullpath;
string fusedirpath;
vector<const string*> createpaths;
vector<const string*> existingpaths;
static
int
create_core(const string &createpath_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_,
const int flags_,
uint64_t *fh_)
{
int rv;
string fullpath;
fusedirpath = fs::path::dirname(fusepath);
fs::path::make(&createpath_,fusepath_,fullpath);
rv = searchFunc(branches_,fusedirpath,minfreespace,existingpaths);
if(rv == -1)
return -errno;
rv = local::create_core(fullpath,mode_,umask_,flags_);
if(rv == -1)
return -errno;
rv = createFunc(branches_,fusedirpath,minfreespace,createpaths);
if(rv == -1)
return -errno;
*fh_ = reinterpret_cast<uint64_t>(new FileInfo(rv,fusepath_));
rv = fs::clonepath_as_root(*existingpaths[0],*createpaths[0],fusedirpath);
if(rv == -1)
return -errno;
return 0;
}
return _create_core(*createpaths[0],
fusepath,
mode,umask,flags,fh);
static
int
create(Policy::Func::Search searchFunc_,
Policy::Func::Create createFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_,
const int flags_,
uint64_t *fh_)
{
int rv;
string fullpath;
string fusedirpath;
vector<const string*> createpaths;
vector<const string*> existingpaths;
fusedirpath = fs::path::dirname(fusepath_);
rv = searchFunc_(branches_,fusedirpath,minfreespace_,existingpaths);
if(rv == -1)
return -errno;
rv = createFunc_(branches_,fusedirpath,minfreespace_,createpaths);
if(rv == -1)
return -errno;
rv = fs::clonepath_as_root(*existingpaths[0],*createpaths[0],fusedirpath);
if(rv == -1)
return -errno;
return local::create_core(*createpaths[0],
fusepath_,
mode_,
umask_,
flags_,
fh_);
}
} }
namespace mergerfs namespace mergerfs
@ -111,24 +117,25 @@ namespace mergerfs
namespace fuse namespace fuse
{ {
int int
create(const char *fusepath,
mode_t mode,
fuse_file_info *ffi)
create(const char *fusepath_,
mode_t mode_,
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,
config.create,
config.branches,
config.minfreespace,
fusepath,
mode,
fc->umask,
ffi->flags,
ffi->fh);
ffi_->direct_io = config.direct_io;
return local::create(config.getattr,
config.create,
config.branches,
config.minfreespace,
fusepath_,
mode_,
fc->umask,
ffi_->flags,
&ffi_->fh);
} }
} }
} }

10
src/fs_path.hpp

@ -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,

24
src/getxattr.cpp

@ -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:

1
src/listxattr.cpp

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

13
src/mergerfs.cpp

@ -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_direct_io :
mergerfs::fuse::read));
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_direct_io :
mergerfs::fuse::write));
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,
config.direct_io,
config.nullrw);
local::get_fuse_operations(ops,config.nullrw);
return fuse_main(args.argc, return fuse_main(args.argc,
args.argv, args.argv,

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
int
_open_core(const string *basepath_,
const char *fusepath_,
const int flags_,
const bool link_cow_,
uint64_t &fh_)
namespace local
{ {
int fd;
string fullpath;
static
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_))
fs::cow::break_link(fullpath.c_str());
if(link_cow_ && fs::cow::is_eligible(fullpath.c_str(),flags_))
fs::cow::break_link(fullpath.c_str());
fd = fs::open(fullpath,flags_);
if(fd == -1)
return -errno;
fd = fs::open(fullpath,flags_);
if(fd == -1)
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
int
_open(Policy::Func::Search searchFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
const int flags_,
const bool link_cow_,
uint64_t &fh_)
{
int rv;
vector<const string*> basepaths;
static
int
open(Policy::Func::Search searchFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
const int flags_,
const bool link_cow_,
uint64_t *fh_)
{
int rv;
vector<const string*> basepaths;
rv = searchFunc_(branches_,fusepath_,minfreespace_,basepaths);
if(rv == -1)
return -errno;
rv = searchFunc_(branches_,fusepath_,minfreespace_,basepaths);
if(rv == -1)
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,
config.branches,
config.minfreespace,
fusepath_,
ffi_->flags,
config.link_cow,
ffi_->fh);
ffi_->direct_io = config.direct_io;
return local::open(config.open,
config.branches,
config.minfreespace,
fusepath_,
ffi_->flags,
config.link_cow,
&ffi_->fh);
} }
} }
} }

10
src/opendir.cpp

@ -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,
fuse_file_info *ffi)
opendir(const char *fusepath_,
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;
} }

32
src/option_parser.cpp

@ -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"

107
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
inline
int
_read(const int fd,
void *buf,
const size_t count,
const off_t offset)
#include <fuse.h>
namespace local
{ {
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);
if(rv == -1)
return -errno;
if(rv == 0)
return 0;
rv = fs::pread(fd_,buf_,count_,offset_);
if(rv == -1)
return -errno;
if(rv == 0)
return 0;
return count;
}
return count_;
}
static
inline
int
_read_direct_io(const int fd,
void *buf,
const size_t count,
const off_t offset)
{
int rv;
static
inline
int
read_direct_io(const int fd_,
void *buf_,
const size_t count_,
const off_t offset_)
{
int rv;
rv = fs::pread(fd,buf,count,offset);
if(rv == -1)
return -errno;
rv = fs::pread(fd_,buf_,count_,offset_);
if(rv == -1)
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,
char *buf,
size_t count,
off_t offset,
fuse_file_info *ffi)
read(const char *fusepath_,
char *buf_,
size_t count_,
off_t offset_,
fuse_file_info *ffi_)
{ {
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
FileInfo *fi;
return ::_read(fi->fd,buf,count,offset);
}
int
read_direct_io(const char *fusepath,
char *buf,
size_t count,
off_t offset,
fuse_file_info *ffi)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return ::_read_direct_io(fi->fd,buf,count,offset);
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_null(const char *fusepath,
char *buf,
size_t count,
off_t offset,
fuse_file_info *ffi)
read_null(const char *fusepath_,
char *buf_,
size_t count_,
off_t offset_,
fuse_file_info *ffi_)
{ {
return count;
return count_;
} }
} }
} }

20
src/setxattr.cpp

@ -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:

177
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
bool
_out_of_space(const int error)
namespace local
{ {
return ((error == ENOSPC) ||
(error == EDQUOT));
}
static
bool
out_of_space(const int error_)
{
return ((error_ == ENOSPC) ||
(error_ == EDQUOT));
}
static
inline
int
_write(const int fd,
const void *buf,
const size_t count,
const off_t offset)
{
int rv;
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;
rv = fs::pwrite(fd_,buf_,count_,offset_);
if(rv == -1)
return -errno;
if(rv == 0)
return 0;
return count;
}
return count_;
}
static
inline
int
_write_direct_io(const int fd,
const void *buf,
const size_t count,
const off_t offset)
{
int rv;
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;
rv = fs::pwrite(fd_,buf_,count_,offset_);
if(rv == -1)
return -errno;
return rv;
}
return rv;
}
namespace mergerfs
{
namespace fuse
static
int
write(WriteFunc func_,
const char *buf_,
const size_t count_,
const off_t offset_,
fuse_file_info *ffi_)
{ {
static
inline
int
write(WriteFunc func,
const char *buf,
const size_t count,
const off_t offset,
fuse_file_info *ffi)
{
int rv;
FileInfo* fi = reinterpret_cast<FileInfo*>(ffi->fh);
int rv;
FileInfo* fi;
rv = func(fi->fd,buf,count,offset);
if(_out_of_space(-rv))
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
fi = reinterpret_cast<FileInfo*>(ffi_->fh);
if(config.moveonenospc)
{
vector<string> paths;
const ugid::Set ugid(0,0);
const rwlock::ReadGuard readlock(&config.branches_lock);
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);
config.branches.to_paths(paths);
if(config.moveonenospc)
{
vector<string> paths;
const ugid::Set ugid(0,0);
const rwlock::ReadGuard readlock(&config.branches_lock);
rv = fs::movefile(paths,fi->fusepath,count,fi->fd);
if(rv == -1)
return -ENOSPC;
config.branches.to_paths(paths);
rv = func(fi->fd,buf,count,offset);
}
}
rv = fs::movefile(paths,fi->fusepath,count_,fi->fd);
if(rv == -1)
return -ENOSPC;
return rv;
}
rv = func_(fi->fd,buf_,count_,offset_);
}
}
return rv;
}
}
namespace mergerfs
{
namespace fuse
{
int int
write(const char *fusepath,
const char *buf,
size_t count,
off_t offset,
fuse_file_info *ffi)
write(const char *fusepath_,
const char *buf_,
size_t count_,
off_t offset_,
fuse_file_info *ffi_)
{ {
return write(_write,buf,count,offset,ffi);
}
WriteFunc wf;
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);
wf = ((ffi_->direct_io) ?
local::write_direct_io :
local::write_regular);
return local::write(wf,buf_,count_,offset_,ffi_);
} }
int int
write_null(const char *fusepath,
const char *buf,
size_t count,
off_t offset,
fuse_file_info *ffi)
write_null(const char *fusepath_,
const char *buf_,
size_t count_,
off_t offset_,
fuse_file_info *ffi_)
{ {
return count;
return count_;
} }
} }
} }
Loading…
Cancel
Save