From: Darrick J. Wong <djwong@xxxxxxxxxx> Plumb in the pieces needed to attach block devices to a fuse+iomap mount for use with iomap operations. This enables us to have filesystems where the metadata could live somewhere else, but the actual file IO goes to locally attached storage. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- include/fuse_kernel.h | 3 +++ include/fuse_lowlevel.h | 16 ++++++++++++++++ lib/fuse_lowlevel.c | 17 +++++++++++++++++ lib/fuse_versionscript | 1 + 4 files changed, 37 insertions(+) diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index eb59ff687b2e7d..97ca55f0114b1d 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -239,6 +239,7 @@ * 7.99 * - add FUSE_IOMAP and iomap_{begin,end,ioend} handlers for FIEMAP and * SEEK_{DATA,HOLE} support + * - add FUSE_DEV_IOC_IOMAP_DEV_ADD to configure block devices for iomap */ #ifndef _LINUX_FUSE_H @@ -1136,6 +1137,8 @@ struct fuse_backing_map { #define FUSE_DEV_IOC_BACKING_OPEN _IOW(FUSE_DEV_IOC_MAGIC, 1, \ struct fuse_backing_map) #define FUSE_DEV_IOC_BACKING_CLOSE _IOW(FUSE_DEV_IOC_MAGIC, 2, uint32_t) +#define FUSE_DEV_IOC_IOMAP_DEV_ADD _IOW(FUSE_DEV_IOC_MAGIC, 3, \ + struct fuse_backing_map) struct fuse_lseek_in { uint64_t fh; diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index d3de87897c47b8..d3e505ed52815b 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -1962,6 +1962,22 @@ int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino, int fuse_lowlevel_notify_retrieve(struct fuse_session *se, fuse_ino_t ino, size_t size, off_t offset, void *cookie); +#if FUSE_USE_VERSION >= FUSE_MAKE_VERSION(3, 18) +/** + * Attach an open file descriptor to a fuse+iomap mount. Currently must be + * a block device. + * + * Added in FUSE protocol version 7.99. If the kernel does not support + * this (or a newer) version, the function will return -ENOSYS and do + * nothing. + * + * @param se the session object + * @param fd file descriptor of an open block device + * @param flags flags for the operation; none defined so far + * @return positive device id for success, zero for failure + */ +int fuse_iomap_add_device(struct fuse_session *se, int fd, unsigned int flags); +#endif /* ----------------------------------------------------------- * * Utility functions * diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 875d2345461251..5df0cdd4ac461a 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -580,6 +580,23 @@ int fuse_passthrough_close(fuse_req_t req, int backing_id) return ret; } +int fuse_iomap_add_device(struct fuse_session *se, int fd, unsigned int flags) +{ + struct fuse_backing_map map = { + .fd = fd, + .flags = flags, + }; + int ret; + + ret = ioctl(se->fd, FUSE_DEV_IOC_IOMAP_DEV_ADD, &map); + if (ret <= 0) { + fuse_log(FUSE_LOG_ERR, "fuse: iomap_dev_add: %s\n", strerror(errno)); + return 0; + } + + return ret; +} + int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f) { struct fuse_open_out arg; diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index 2b4c16abdaf519..4cdae6a6a42051 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -214,6 +214,7 @@ FUSE_3.18 { fuse_convert_to_conn_want_ext; fuse_reply_iomap_begin; + fuse_iomap_add_device; } FUSE_3.17; # Local Variables: