From: Darrick J. Wong <djwong@xxxxxxxxxx> Add some flags to query and request kernel support for filesystem iomap for regular files. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- include/fuse_common.h | 5 +++++ include/fuse_kernel.h | 5 +++++ lib/fuse_lowlevel.c | 10 +++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/fuse_common.h b/include/fuse_common.h index b82f2c41deb30c..8f87263d78f999 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -520,6 +520,11 @@ struct fuse_loop_config_v1 { */ #define FUSE_CAP_OVER_IO_URING (1UL << 31) +/** + * Client supports using iomap for FIEMAP and SEEK_{DATA,HOLE} + */ +#define FUSE_CAP_IOMAP (1ULL << 32) + /** * Ioctl flags * diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index 4d68c4e8a71d5f..6779b9c69bb9e2 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -237,6 +237,8 @@ * - add FUSE_NOTIFY_INC_EPOCH * * 7.99 + * - add FUSE_IOMAP and iomap_{begin,end,ioend} handlers for FIEMAP and + * SEEK_{DATA,HOLE} */ #ifndef _LINUX_FUSE_H @@ -445,6 +447,8 @@ struct fuse_file_lock { * FUSE_OVER_IO_URING: Indicate that client supports io-uring * FUSE_REQUEST_TIMEOUT: kernel supports timing out requests. * init_out.request_timeout contains the timeout (in secs) + * FUSE_IOMAP: Client supports iomap for FIEMAP and SEEK_{DATA,HOLE} file + * operations. */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -492,6 +496,7 @@ struct fuse_file_lock { #define FUSE_ALLOW_IDMAP (1ULL << 40) #define FUSE_OVER_IO_URING (1ULL << 41) #define FUSE_REQUEST_TIMEOUT (1ULL << 42) +#define FUSE_IOMAP (1ULL << 43) /** * CUSE INIT request/reply flags diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 6afcecd3bdda96..33c71ba216679c 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -2686,7 +2686,8 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, se->conn.capable_ext |= FUSE_CAP_NO_EXPORT_SUPPORT; if (inargflags & FUSE_OVER_IO_URING) se->conn.capable_ext |= FUSE_CAP_OVER_IO_URING; - + if (inargflags & FUSE_IOMAP) + se->conn.capable_ext |= FUSE_CAP_IOMAP; } else { se->conn.max_readahead = 0; } @@ -2732,6 +2733,9 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, FUSE_CAP_READDIRPLUS_AUTO); LL_SET_DEFAULT(1, FUSE_CAP_OVER_IO_URING); + /* servers need to opt-in to iomap explicitly */ + LL_SET_DEFAULT(0, FUSE_CAP_IOMAP); + /* This could safely become default, but libfuse needs an API extension * to support it * LL_SET_DEFAULT(1, FUSE_CAP_SETXATTR_EXT); @@ -2850,6 +2854,8 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, outargflags |= FUSE_REQUEST_TIMEOUT; outarg.request_timeout = se->conn.request_timeout; } + if (se->conn.want_ext & FUSE_CAP_IOMAP) + outargflags |= FUSE_IOMAP; if (inargflags & FUSE_INIT_EXT) { outargflags |= FUSE_INIT_EXT; @@ -2891,6 +2897,8 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, if (se->conn.want_ext & FUSE_CAP_PASSTHROUGH) fuse_log(FUSE_LOG_DEBUG, " max_stack_depth=%u\n", outarg.max_stack_depth); + if (se->conn.want_ext & FUSE_CAP_IOMAP) + fuse_log(FUSE_LOG_DEBUG, " iomap=1\n"); } if (arg->minor < 5) outargsize = FUSE_COMPAT_INIT_OUT_SIZE;