From: Darrick J. Wong <djwong@xxxxxxxxxx> Make it so that fuse servers can ask the kernel fuse driver to use iomap to support buffered IO. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- include/fuse_common.h | 7 +++++++ include/fuse_kernel.h | 5 +++++ lib/fuse_lowlevel.c | 9 +++++++++ 3 files changed, 21 insertions(+) diff --git a/include/fuse_common.h b/include/fuse_common.h index 657256b6309284..8bc21677b6e5c7 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -530,6 +530,11 @@ struct fuse_loop_config_v1 { */ #define FUSE_CAP_IOMAP_DIRECTIO (1ULL << 33) +/* + * Client supports using iomap for buffered I/O file operations + */ +#define FUSE_CAP_IOMAP_FILEIO (1ULL << 34) + /** * Ioctl flags * @@ -1219,6 +1224,8 @@ struct fuse_iomap { #define FUSE_IFLAG_DAX (1U << 0) /* use iomap for directio */ #define FUSE_IFLAG_IOMAP_DIRECTIO (1U << 1) +/* use iomap for buffered io */ +#define FUSE_IFLAG_IOMAP_FILEIO (1U << 2) #endif /* FUSE_USE_VERSION >= 318 */ diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index 7205de018634b9..17ab74255cbf33 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -241,6 +241,7 @@ * SEEK_{DATA,HOLE} support * - add FUSE_DEV_IOC_IOMAP_DEV_ADD to configure block devices for iomap * - add FUSE_IOMAP_DIRECTIO/FUSE_ATTR_IOMAP_DIRECTIO for direct I/O support + * - add FUSE_IOMAP_FILEIO/FUSE_ATTR_IOMAP_FILEIO for buffered I/O support */ #ifndef _LINUX_FUSE_H @@ -452,6 +453,7 @@ struct fuse_file_lock { * FUSE_IOMAP: Client supports iomap for FIEMAP and SEEK_{DATA,HOLE} file * operations. * FUSE_IOMAP_DIRECTIO: Client supports iomap for direct I/O operations. + * FUSE_IOMAP_FILEIO: Client supports iomap for buffered I/O operations. */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -501,6 +503,7 @@ struct fuse_file_lock { #define FUSE_REQUEST_TIMEOUT (1ULL << 42) #define FUSE_IOMAP (1ULL << 43) #define FUSE_IOMAP_DIRECTIO (1ULL << 44) +#define FUSE_IOMAP_FILEIO (1ULL << 45) /** * CUSE INIT request/reply flags @@ -585,10 +588,12 @@ struct fuse_file_lock { * FUSE_ATTR_SUBMOUNT: Object is a submount root * FUSE_ATTR_DAX: Enable DAX for this file in per inode DAX mode * FUSE_ATTR_IOMAP_DIRECTIO: Use iomap for directio + * FUSE_ATTR_IOMAP_FILEIO: Use iomap for buffered io */ #define FUSE_ATTR_SUBMOUNT (1 << 0) #define FUSE_ATTR_DAX (1 << 1) #define FUSE_ATTR_IOMAP_DIRECTIO (1 << 2) +#define FUSE_ATTR_IOMAP_FILEIO (1 << 3) /** * Open flags diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index f98900c51d4a9b..d354b947a4fb6b 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -126,6 +126,8 @@ static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr, attr->flags |= FUSE_ATTR_DAX; if (iflags & FUSE_IFLAG_IOMAP_DIRECTIO) attr->flags |= FUSE_ATTR_IOMAP_DIRECTIO; + if (iflags & FUSE_IFLAG_IOMAP_FILEIO) + attr->flags |= FUSE_ATTR_IOMAP_FILEIO; } static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf) @@ -2781,6 +2783,8 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, se->conn.capable_ext |= FUSE_CAP_IOMAP; if (inargflags & FUSE_IOMAP_DIRECTIO) se->conn.capable_ext |= FUSE_CAP_IOMAP_DIRECTIO; + if (inargflags & FUSE_IOMAP_FILEIO) + se->conn.capable_ext |= FUSE_CAP_IOMAP_FILEIO; } else { se->conn.max_readahead = 0; } @@ -2829,6 +2833,7 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, /* servers need to opt-in to iomap explicitly */ LL_SET_DEFAULT(0, FUSE_CAP_IOMAP); LL_SET_DEFAULT(0, FUSE_CAP_IOMAP_DIRECTIO); + LL_SET_DEFAULT(0, FUSE_CAP_IOMAP_FILEIO); /* This could safely become default, but libfuse needs an API extension * to support it @@ -2952,6 +2957,8 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, outargflags |= FUSE_IOMAP; if (se->conn.want_ext & FUSE_CAP_IOMAP_DIRECTIO) outargflags |= FUSE_IOMAP_DIRECTIO; + if (se->conn.want_ext & FUSE_CAP_IOMAP_FILEIO) + outargflags |= FUSE_IOMAP_FILEIO; if (inargflags & FUSE_INIT_EXT) { outargflags |= FUSE_INIT_EXT; @@ -2997,6 +3004,8 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, fuse_log(FUSE_LOG_DEBUG, " iomap=1\n"); if (se->conn.want_ext & FUSE_CAP_IOMAP_DIRECTIO) fuse_log(FUSE_LOG_DEBUG, " iomap_directio=1\n"); + if (se->conn.want_ext & FUSE_CAP_IOMAP_FILEIO) + fuse_log(FUSE_LOG_DEBUG, " iomap_fileio=1\n"); } if (arg->minor < 5) outargsize = FUSE_COMPAT_INIT_OUT_SIZE;