diff options
-rw-r--r-- | include/fuse.h | 14 | ||||
-rw-r--r-- | include/fuse_common.h | 8 | ||||
-rw-r--r-- | include/fuse_kernel.h | 3 | ||||
-rw-r--r-- | lib/fuse.c | 9 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 2 |
5 files changed, 32 insertions, 4 deletions
diff --git a/include/fuse.h b/include/fuse.h index 6f162dd..3cf0423 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -274,6 +274,20 @@ struct fuse_config { * fuse_file_info argument is NULL. */ int nullpath_ok; + /** + * Allow parallel direct-io writes to operate on the same file. + * + * FUSE implementations which do not handle parallel writes on + * same file/region should NOT enable this option at all as it + * might lead to data inconsistencies. + * + * For the FUSE implementations which have their own mechanism + * of cache/data integrity are beneficiaries of this setting as + * it now open doors to parallel writes on the same file (without + * enabling this setting, all direct writes on the same file are + * serialized, resulting in huge data bandwidth loss). + */ + int parallel_direct_writes; /** * The remaining options are used by libfuse internally and diff --git a/include/fuse_common.h b/include/fuse_common.h index 06ee365..d2e7fbe 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -59,7 +59,7 @@ struct fuse_file_info { requests if write caching had been disabled. */ unsigned int writepage : 1; - /** Can be filled in by open, to use direct I/O on this file. */ + /** Can be filled in by open/create, to use direct I/O on this file. */ unsigned int direct_io : 1; /** Can be filled in by open and opendir. It signals the kernel that any @@ -68,6 +68,10 @@ struct fuse_file_info { the file/directory is closed. */ unsigned int keep_cache : 1; + /** Can be filled by open/create, to allow parallel direct writes on this + * file */ + unsigned int parallel_direct_writes : 1; + /** Indicates a flush operation. Set in flush operation, also maybe set in highlevel lock operation and lowlevel release operation. */ @@ -93,7 +97,7 @@ struct fuse_file_info { unsigned int noflush : 1; /** Padding. Reserved for future use*/ - unsigned int padding : 24; + unsigned int padding : 23; unsigned int padding2 : 32; /** File handle id. May be filled in by filesystem in create, diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index 39cfb34..814a86f 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -307,6 +307,7 @@ struct fuse_file_lock { * FOPEN_CACHE_DIR: allow caching this directory * FOPEN_STREAM: the file is stream-like (no file position at all) * FOPEN_NOFLUSH: don't flush data cache on close (unless FUSE_WRITEBACK_CACHE) + * FOPEN_PARALLEL_DIRECT_WRITES: allow parallel direct writes on the same file */ #define FOPEN_DIRECT_IO (1 << 0) #define FOPEN_KEEP_CACHE (1 << 1) @@ -314,7 +315,7 @@ struct fuse_file_lock { #define FOPEN_CACHE_DIR (1 << 3) #define FOPEN_STREAM (1 << 4) #define FOPEN_NOFLUSH (1 << 5) - +#define FOPEN_PARALLEL_DIRECT_WRITES (1 << 6) /** * INIT request/reply flags * @@ -3145,7 +3145,9 @@ static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent, fi->direct_io = 1; if (f->conf.kernel_cache) fi->keep_cache = 1; - + if (fi->direct_io && + f->conf.parallel_direct_writes) + fi->parallel_direct_writes = 1; } } fuse_finish_interrupt(f, req, &d); @@ -3229,6 +3231,10 @@ static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino, if (f->conf.no_rofd_flush && (fi->flags & O_ACCMODE) == O_RDONLY) fi->noflush = 1; + + if (fi->direct_io && f->conf.parallel_direct_writes) + fi->parallel_direct_writes = 1; + } fuse_finish_interrupt(f, req, &d); } @@ -4653,6 +4659,7 @@ static const struct fuse_opt fuse_lib_opts[] = { FUSE_LIB_OPT("noforget", remember, -1), FUSE_LIB_OPT("remember=%u", remember, 0), FUSE_LIB_OPT("modules=%s", modules, 0), + FUSE_LIB_OPT("parallel_direct_write=%d", parallel_direct_writes, 0), FUSE_OPT_END }; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index a0f8f00..baed664 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -405,6 +405,8 @@ static void fill_open(struct fuse_open_out *arg, arg->open_flags |= FOPEN_NONSEEKABLE; if (f->noflush) arg->open_flags |= FOPEN_NOFLUSH; + if (f->parallel_direct_writes) + arg->open_flags |= FOPEN_PARALLEL_DIRECT_WRITES; } int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e) |