summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fuse.h14
-rw-r--r--include/fuse_common.h8
-rw-r--r--include/fuse_kernel.h3
-rw-r--r--lib/fuse.c9
-rw-r--r--lib/fuse_lowlevel.c2
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
*
diff --git a/lib/fuse.c b/lib/fuse.c
index a247d3c..6b42a69 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -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)