diff --git a/src/fuse_create.cpp b/src/fuse_create.cpp index 80026775..8bef3316 100644 --- a/src/fuse_create.cpp +++ b/src/fuse_create.cpp @@ -45,18 +45,48 @@ namespace l true of any caching. */ static - int - tweak_flags_writeback_cache(const int flags_) + void + tweak_flags_writeback_cache(int *flags_) { - int flags; - - flags = flags_; - if((flags & O_ACCMODE) == O_WRONLY) - flags = ((flags & ~O_ACCMODE) | O_RDWR); - if(flags & O_APPEND) - flags &= ~O_APPEND; + if((*flags_ & O_ACCMODE) == O_WRONLY) + *flags_ = ((*flags_ & ~O_ACCMODE) | O_RDWR); + if(*flags_ & O_APPEND) + *flags_ &= ~O_APPEND; + } - return flags; + static + void + config_to_ffi_flags(const Config &config_, + fuse_file_info *ffi_) + { + switch(config_.cache_files) + { + case CacheFiles::LIBFUSE: + ffi_->direct_io = config_.direct_io; + ffi_->keep_cache = config_.kernel_cache; + ffi_->auto_cache = config_.auto_cache; + break; + case CacheFiles::OFF: + ffi_->direct_io = 1; + ffi_->keep_cache = 0; + ffi_->auto_cache = 0; + break; + case CacheFiles::PARTIAL: + ffi_->direct_io = 0; + ffi_->keep_cache = 0; + ffi_->auto_cache = 0; + break; + case CacheFiles::FULL: + ffi_->direct_io = 0; + ffi_->keep_cache = 1; + ffi_->auto_cache = 0; + break; + case CacheFiles::AUTO_FULL: + ffi_->direct_io = 0; + ffi_->keep_cache = 0; + ffi_->auto_cache = 1; + break; + } } static @@ -148,37 +178,10 @@ namespace FUSE const ugid::Set ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.branches_lock); - switch(config.cache_files) - { - case CacheFiles::LIBFUSE: - ffi_->direct_io = config.direct_io; - ffi_->keep_cache = config.kernel_cache; - ffi_->auto_cache = config.auto_cache; - break; - case CacheFiles::OFF: - ffi_->direct_io = 1; - ffi_->keep_cache = 0; - ffi_->auto_cache = 0; - break; - case CacheFiles::PARTIAL: - ffi_->direct_io = 0; - ffi_->keep_cache = 0; - ffi_->auto_cache = 0; - break; - case CacheFiles::FULL: - ffi_->direct_io = 0; - ffi_->keep_cache = 1; - ffi_->auto_cache = 0; - break; - case CacheFiles::AUTO_FULL: - ffi_->direct_io = 0; - ffi_->keep_cache = 0; - ffi_->auto_cache = 1; - break; - } + l::config_to_ffi_flags(config,ffi_); if(config.writeback_cache) - ffi_->flags = l::tweak_flags_writeback_cache(ffi_->flags); + l::tweak_flags_writeback_cache(&ffi_->flags); return l::create(config.getattr, config.create, diff --git a/src/fuse_getxattr.cpp b/src/fuse_getxattr.cpp index 9bfff730..503fe8d3 100644 --- a/src/fuse_getxattr.cpp +++ b/src/fuse_getxattr.cpp @@ -395,6 +395,8 @@ namespace l l::getxattr_controlfile_bool(config.cache_readdir,attrvalue); else if((attr[2] == "cache") && (attr[3] == "files")) l::getxattr_controlfile(config.cache_files,attrvalue); + else if((attr[2] == "cache") && (attr[3] == "writeback")) + l::getxattr_controlfile_bool(config.writeback_cache,attrvalue); break; } diff --git a/src/fuse_listxattr.cpp b/src/fuse_listxattr.cpp index 32a0fcbb..242bdc5c 100644 --- a/src/fuse_listxattr.cpp +++ b/src/fuse_listxattr.cpp @@ -54,6 +54,7 @@ namespace l ("user.mergerfs.cache.readdir") ("user.mergerfs.cache.statfs") ("user.mergerfs.cache.symlinks") + ("user.mergerfs.cache.writeback") ("user.mergerfs.direct_io") ("user.mergerfs.dropcacheonclose") ("user.mergerfs.fuse_msg_size") diff --git a/src/fuse_open.cpp b/src/fuse_open.cpp index 4ff7b027..a4142fd2 100644 --- a/src/fuse_open.cpp +++ b/src/fuse_open.cpp @@ -35,19 +35,58 @@ typedef Config::CacheFiles CacheFiles; namespace l { + /* + The kernel expects being able to issue read requests when running + with writeback caching enabled so we must change O_WRONLY to + O_RDWR. + + With writeback caching enabled the kernel handles O_APPEND. Could + be an issue if the underlying file changes out of band but that is + true of any caching. + */ static - int - tweak_flags_writeback_cache(const int flags_) + void + tweak_flags_writeback_cache(int *flags_) { - int flags; - - flags = flags_; - if((flags & O_ACCMODE) == O_WRONLY) - flags = ((flags & ~O_ACCMODE) | O_RDWR); - if(flags & O_APPEND) - flags &= ~O_APPEND; + if((*flags_ & O_ACCMODE) == O_WRONLY) + *flags_ = ((*flags_ & ~O_ACCMODE) | O_RDWR); + if(*flags_ & O_APPEND) + *flags_ &= ~O_APPEND; + } - return flags; + static + void + config_to_ffi_flags(const Config &config_, + fuse_file_info *ffi_) + { + switch(config_.cache_files) + { + case CacheFiles::LIBFUSE: + ffi_->direct_io = config_.direct_io; + ffi_->keep_cache = config_.kernel_cache; + ffi_->auto_cache = config_.auto_cache; + break; + case CacheFiles::OFF: + ffi_->direct_io = 1; + ffi_->keep_cache = 0; + ffi_->auto_cache = 0; + break; + case CacheFiles::PARTIAL: + ffi_->direct_io = 0; + ffi_->keep_cache = 0; + ffi_->auto_cache = 0; + break; + case CacheFiles::FULL: + ffi_->direct_io = 0; + ffi_->keep_cache = 1; + ffi_->auto_cache = 0; + break; + case CacheFiles::AUTO_FULL: + ffi_->direct_io = 0; + ffi_->keep_cache = 0; + ffi_->auto_cache = 1; + break; + } } static @@ -108,37 +147,10 @@ namespace FUSE const ugid::Set ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.branches_lock); - switch(config.cache_files) - { - case CacheFiles::LIBFUSE: - ffi_->direct_io = config.direct_io; - ffi_->keep_cache = config.kernel_cache; - ffi_->auto_cache = config.auto_cache; - break; - case CacheFiles::OFF: - ffi_->direct_io = 1; - ffi_->keep_cache = 0; - ffi_->auto_cache = 0; - break; - case CacheFiles::PARTIAL: - ffi_->direct_io = 0; - ffi_->keep_cache = 0; - ffi_->auto_cache = 0; - break; - case CacheFiles::FULL: - ffi_->direct_io = 0; - ffi_->keep_cache = 1; - ffi_->auto_cache = 0; - break; - case CacheFiles::AUTO_FULL: - ffi_->direct_io = 0; - ffi_->keep_cache = 0; - ffi_->auto_cache = 1; - break; - } + l::config_to_ffi_flags(config,ffi_); if(config.writeback_cache) - ffi_->flags = l::tweak_flags_writeback_cache(ffi_->flags); + l::tweak_flags_writeback_cache(&ffi_->flags); return l::open(config.open, config.open_cache,