libfuse: Add "async_dio" and "writeback_cache" options
authorMiklos Szeredi <mszeredi@suse.cz>
Wed, 29 Jan 2014 13:13:36 +0000 (14:13 +0100)
committerMiklos Szeredi <mszeredi@suse.cz>
Wed, 29 Jan 2014 13:13:36 +0000 (14:13 +0100)
Asynchronous direct I/O is supported by linux kernels 3.13 and
later, writeback caching is supported by 3.14 and later.

ChangeLog
include/fuse_common.h
include/fuse_kernel.h
lib/fuse_i.h
lib/fuse_lowlevel.c

index 753aaabde5d472fd93d30a515f6caaa9f3355cdb..f3270842d9f2b30f0fb3f80b99809953abf2d5c8 100644 (file)
--- 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
index 765e0a35ca7077c97a157b3a625036d7bd769dc0..22d9591bc9e2cb8668b2907bf84fecd20c000874 100644 (file)
@@ -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
index 706d035fa7488df73b142b1812c2c3feaa8708d3..797472139a650aef4cbc7ce1cc3c9c6d4fc3714d 100644 (file)
  * 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
 #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
index 582374371905ec518ffd4112feb4fd3d0f523fe5..30fe415780d3059bc2bebd84e193253616394668 100644 (file)
@@ -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;
index 1e9b92c7fc3657269b7d98d474900b36054b1e71..19feb14cdfd7faa72ef83b172ced2805fa635794 100755 (executable)
@@ -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"
 );
 }