summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-01-29 14:13:36 +0100
committerMiklos Szeredi <mszeredi@suse.cz>2014-01-29 14:13:36 +0100
commit8bb62a632caa4269bb6436cae67307404882b936 (patch)
tree424b027334a65d134c44fb2dfc02dcd3c0577a61
parentdd432032db34c2ca22570af5ac6794822ef4c877 (diff)
downloadfuse-8bb62a632caa4269bb6436cae67307404882b936.tar.gz
libfuse: Add "async_dio" and "writeback_cache" options
Asynchronous direct I/O is supported by linux kernels 3.13 and later, writeback caching is supported by 3.14 and later.
-rw-r--r--ChangeLog6
-rw-r--r--include/fuse_common.h7
-rw-r--r--include/fuse_kernel.h12
-rw-r--r--lib/fuse_i.h4
-rwxr-xr-xlib/fuse_lowlevel.c33
5 files changed, 56 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 753aaab..f327084 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-01-29 Miklos Szeredi <miklos@szeredi.hu>
+
+ * libfuse: Add "async_dio" and "writeback_cache" options.
+ Asynchronous direct I/O is supported by linux kernels 3.13 and
+ later, writeback caching is supported by 3.14 and later.
+
2013-08-26 Miklos Szeredi <miklos@szeredi.hu>
* libfuse: Add missing includes. This allows compiling fuse with
diff --git a/include/fuse_common.h b/include/fuse_common.h
index 765e0a3..22d9591 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -96,6 +96,11 @@ struct fuse_file_info {
* FUSE_CAP_SPLICE_MOVE: ability to move data to the fuse device with splice()
* FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device
* FUSE_CAP_IOCTL_DIR: ioctl support on directories
+ * FUSE_CAP_AUTO_INVAL_DATA: automatically invalidate cached pages
+ * FUSE_CAP_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one)
+ * FUSE_CAP_READDIRPLUS_AUTO: adaptive readdirplus
+ * FUSE_CAP_ASYNC_DIO: asynchronous direct I/O submission
+ * FUSE_CAP_WRITEBACK_CACHE: use writeback cache for buffered writes
*/
#define FUSE_CAP_ASYNC_READ (1 << 0)
#define FUSE_CAP_POSIX_LOCKS (1 << 1)
@@ -111,6 +116,8 @@ struct fuse_file_info {
#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
#define FUSE_CAP_READDIRPLUS (1 << 13)
#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
+#define FUSE_CAP_ASYNC_DIO (1 << 15)
+#define FUSE_CAP_WRITEBACK_CACHE (1 << 16)
/**
* Ioctl flags
diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
index 706d035..7974721 100644
--- a/include/fuse_kernel.h
+++ b/include/fuse_kernel.h
@@ -90,6 +90,12 @@
* 7.21
* - add FUSE_READDIRPLUS
* - send the requested events in POLL request
+ *
+ * 7.22
+ * - add FUSE_ASYNC_DIO
+ *
+ * 7.23
+ * - add FUSE_WRITEBACK_CACHE
*/
#ifndef _LINUX_FUSE_H
@@ -125,7 +131,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 21
+#define FUSE_KERNEL_MINOR_VERSION 22
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -215,6 +221,8 @@ struct fuse_file_lock {
* FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages
* FUSE_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one)
* FUSE_READDIRPLUS_AUTO: adaptive readdirplus
+ * FUSE_ASYNC_DIO: asynchronous direct I/O submission
+ * FUSE_WRITEBACK_CACHE: use writeback cache for buffered writes
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -231,6 +239,8 @@ struct fuse_file_lock {
#define FUSE_AUTO_INVAL_DATA (1 << 12)
#define FUSE_DO_READDIRPLUS (1 << 13)
#define FUSE_READDIRPLUS_AUTO (1 << 14)
+#define FUSE_ASYNC_DIO (1 << 15)
+#define FUSE_WRITEBACK_CACHE (1 << 16)
/**
* CUSE INIT request/reply flags
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 5823743..30fe415 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -74,6 +74,10 @@ struct fuse_ll {
int no_auto_inval_data;
int no_readdirplus;
int no_readdirplus_auto;
+ int async_dio;
+ int no_async_dio;
+ int writeback_cache;
+ int no_writeback_cache;
struct fuse_lowlevel_ops op;
int got_init;
struct cuse_data *cuse_data;
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 1e9b92c..19feb14 100755
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -1901,6 +1901,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
f->conn.capable |= FUSE_CAP_READDIRPLUS;
if (arg->flags & FUSE_READDIRPLUS_AUTO)
f->conn.capable |= FUSE_CAP_READDIRPLUS_AUTO;
+ if (arg->flags & FUSE_ASYNC_DIO)
+ f->conn.capable |= FUSE_CAP_ASYNC_DIO;
+ if (arg->flags & FUSE_WRITEBACK_CACHE)
+ f->conn.capable |= FUSE_CAP_WRITEBACK_CACHE;
} else {
f->conn.async_read = 0;
f->conn.max_readahead = 0;
@@ -1938,6 +1942,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
if (!f->no_readdirplus_auto)
f->conn.want |= FUSE_CAP_READDIRPLUS_AUTO;
}
+ if (f->async_dio)
+ f->conn.want |= FUSE_CAP_ASYNC_DIO;
+ if (f->writeback_cache)
+ f->conn.want |= FUSE_CAP_WRITEBACK_CACHE;
if (bufsize < FUSE_MIN_READ_BUFFER) {
fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
@@ -1965,6 +1973,11 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
f->conn.want &= ~FUSE_CAP_READDIRPLUS;
if (f->no_readdirplus_auto)
f->conn.want &= ~FUSE_CAP_READDIRPLUS_AUTO;
+ if (f->no_async_dio)
+ f->conn.want &= ~FUSE_CAP_ASYNC_DIO;
+ if (f->no_writeback_cache)
+ f->conn.want &= ~FUSE_CAP_WRITEBACK_CACHE;
+
if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ))
outarg.flags |= FUSE_ASYNC_READ;
if (f->conn.want & FUSE_CAP_POSIX_LOCKS)
@@ -1985,6 +1998,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
outarg.flags |= FUSE_DO_READDIRPLUS;
if (f->conn.want & FUSE_CAP_READDIRPLUS_AUTO)
outarg.flags |= FUSE_READDIRPLUS_AUTO;
+ if (f->conn.want & FUSE_CAP_ASYNC_DIO)
+ outarg.flags |= FUSE_ASYNC_DIO;
+ if (f->conn.want & FUSE_CAP_WRITEBACK_CACHE)
+ outarg.flags |= FUSE_WRITEBACK_CACHE;
outarg.max_readahead = f->conn.max_readahead;
outarg.max_write = f->conn.max_write;
if (f->conn.proto_minor >= 13) {
@@ -2604,6 +2621,10 @@ static const struct fuse_opt fuse_ll_opts[] = {
{ "readdirplus=yes", offsetof(struct fuse_ll, no_readdirplus_auto), 1},
{ "readdirplus=auto", offsetof(struct fuse_ll, no_readdirplus), 0},
{ "readdirplus=auto", offsetof(struct fuse_ll, no_readdirplus_auto), 0},
+ { "async_dio", offsetof(struct fuse_ll, async_dio), 1},
+ { "no_async_dio", offsetof(struct fuse_ll, no_async_dio), 1},
+ { "writeback_cache", offsetof(struct fuse_ll, writeback_cache), 1},
+ { "no_writeback_cache", offsetof(struct fuse_ll, no_writeback_cache), 1},
FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
FUSE_OPT_KEY("-h", KEY_HELP),
FUSE_OPT_KEY("--help", KEY_HELP),
@@ -2631,12 +2652,14 @@ static void fuse_ll_help(void)
" -o big_writes enable larger than 4kB writes\n"
" -o no_remote_lock disable remote file locking\n"
" -o no_remote_flock disable remote file locking (BSD)\n"
-" -o no_remote_posix_lock disable remove file locking (POSIX)\n"
-" -o [no_]splice_write use splice to write to the fuse device\n"
-" -o [no_]splice_move move data while splicing to the fuse device\n"
-" -o [no_]splice_read use splice to read from the fuse device\n"
+" -o no_remote_posix_lock disable remove file locking (POSIX)\n"
+" -o [no_]splice_write use splice to write to the fuse device\n"
+" -o [no_]splice_move move data while splicing to the fuse device\n"
+" -o [no_]splice_read use splice to read from the fuse device\n"
" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n"
-" -o readdirplus=S control readdirplus use (yes|no|auto)\n"
+" -o readdirplus=S control readdirplus use (yes|no|auto)\n"
+" -o [no_]async_dio asynchronous direct I/O\n"
+" -o [no_]writeback_cache asynchronous, buffered writes\n"
);
}