diff --git a/src/config.cpp b/src/config.cpp index 829ff2a0..e0c3de3e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -39,6 +39,7 @@ namespace mergerfs srcmountslock(), minfreespace(MINFREESPACE_DEFAULT), moveonenospc(false), + direct_io(false), POLICYINIT(access), POLICYINIT(chmod), POLICYINIT(chown), diff --git a/src/config.hpp b/src/config.hpp index b3ad4771..0ec36d04 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -47,6 +47,7 @@ namespace mergerfs mutable pthread_rwlock_t srcmountslock; uint64_t minfreespace; bool moveonenospc; + bool direct_io; public: const Policy *policies[FuseFunc::Enum::END]; diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index fabbac92..d4c40d85 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -78,7 +78,8 @@ namespace local static void - get_fuse_operations(struct fuse_operations &ops) + get_fuse_operations(struct fuse_operations &ops, + const bool direct_io) { #if FLAG_NOPATH ops.flag_nopath = false; @@ -115,7 +116,9 @@ namespace local ops.open = mergerfs::fuse::open; ops.opendir = mergerfs::fuse::opendir; ops.poll = NULL; - ops.read = mergerfs::fuse::read; + ops.read = direct_io ? + mergerfs::fuse::read_direct_io : + mergerfs::fuse::read; #if READ_BUF ops.read_buf = mergerfs::fuse::read_buf; #endif @@ -133,7 +136,9 @@ namespace local ops.unlink = mergerfs::fuse::unlink; ops.utime = NULL; /* deprecated; use utimens() */ ops.utimens = mergerfs::fuse::utimens; - ops.write = mergerfs::fuse::write; + ops.write = direct_io ? + mergerfs::fuse::write_direct_io : + mergerfs::fuse::write; #if WRITE_BUF ops.write_buf = mergerfs::fuse::write_buf; #endif @@ -172,7 +177,7 @@ namespace mergerfs mergerfs::options::parse(args,config); local::setup_resources(); - local::get_fuse_operations(ops); + local::get_fuse_operations(ops,config.direct_io); return fuse_main(args.argc, args.argv, diff --git a/src/option_parser.cpp b/src/option_parser.cpp index 0711b94f..485cb6fa 100644 --- a/src/option_parser.cpp +++ b/src/option_parser.cpp @@ -140,10 +140,9 @@ parse_and_process_arg(Config &config, fuse_args *outargs) { if(arg == "defaults") - { - set_default_options(*outargs); - return 0; - } + return (set_default_options(*outargs),0); + else if(arg == "direct_io") + return (config.direct_io=true,1); return 1; } diff --git a/src/read.cpp b/src/read.cpp index e741e777..80d08c09 100644 --- a/src/read.cpp +++ b/src/read.cpp @@ -25,6 +25,7 @@ #include "fs_base_read.hpp" static +inline int _read(const int fd, void *buf, @@ -34,8 +35,29 @@ _read(const int fd, int rv; rv = fs::pread(fd,buf,count,offset); + if(rv == -1) + return -errno; + if(rv == 0) + return 0; - return ((rv == -1) ? -errno : rv); + return count; +} + +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; + + return rv; } namespace mergerfs @@ -51,10 +73,19 @@ namespace mergerfs { FileInfo *fi = reinterpret_cast(ffi->fh); - return _read(fi->fd, - buf, - count, - offset); + 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(ffi->fh); + + return _read_direct_io(fi->fd,buf,count,offset); } } } diff --git a/src/read.hpp b/src/read.hpp index fe3e3a8e..1ce57ae2 100644 --- a/src/read.hpp +++ b/src/read.hpp @@ -24,5 +24,12 @@ namespace mergerfs size_t count, off_t offset, fuse_file_info *fi); + + int + read_direct_io(const char *fusepath, + char *buf, + size_t count, + off_t offset, + fuse_file_info *fi); } } diff --git a/src/write.cpp b/src/write.cpp index 15f2efca..6d722b06 100644 --- a/src/write.cpp +++ b/src/write.cpp @@ -24,6 +24,10 @@ #include "rwlock.hpp" #include "ugid.hpp" +using namespace mergerfs; + +typedef int (*WriteFunc)(const int,const void*,const size_t,const off_t); + static bool _out_of_space(const int error) @@ -33,6 +37,7 @@ _out_of_space(const int error) } static +inline int _write(const int fd, const void *buf, @@ -42,25 +47,52 @@ _write(const int fd, int rv; rv = fs::pwrite(fd,buf,count,offset); + if(rv == -1) + return -errno; + if(rv == 0) + return 0; - return ((rv == -1) ? -errno : rv); + 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 fuse { + static + inline int - write(const char *fusepath, + write(WriteFunc func, + const char *fusepath, const char *buf, - size_t count, - off_t offset, + const size_t count, + const off_t offset, fuse_file_info *ffi) { int rv; FileInfo* fi = reinterpret_cast(ffi->fh); - rv = _write(fi->fd,buf,count,offset); + rv = func(fi->fd,buf,count,offset); if(_out_of_space(-rv)) { const fuse_context *fc = fuse_get_context(); @@ -75,11 +107,31 @@ namespace mergerfs if(rv == -1) return -ENOSPC; - rv = _write(fi->fd,buf,count,offset); + rv = func(fi->fd,buf,count,offset); } } return rv; } + + int + write(const char *fusepath, + const char *buf, + size_t count, + off_t offset, + fuse_file_info *ffi) + { + return write(_write,fusepath,buf,count,offset,ffi); + } + + 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,fusepath,buf,count,offset,ffi); + } } } diff --git a/src/write.hpp b/src/write.hpp index e20cd654..1736f9a0 100644 --- a/src/write.hpp +++ b/src/write.hpp @@ -24,5 +24,12 @@ namespace mergerfs size_t count, off_t offset, fuse_file_info *fi); + + int + write_direct_io(const char *fusepath, + const char *buf, + size_t count, + off_t offset, + fuse_file_info *fi); } }