From 8bb62a632caa4269bb6436cae67307404882b936 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi <mszeredi@suse.cz> Date: Wed, 29 Jan 2014 14:13:36 +0100 Subject: [PATCH] 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. --- ChangeLog | 6 ++++++ include/fuse_common.h | 7 +++++++ include/fuse_kernel.h | 12 +++++++++++- lib/fuse_i.h | 4 ++++ lib/fuse_lowlevel.c | 33 ++++++++++++++++++++++++++++----- 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" ); } -- 2.30.2