From da355f79362f5724f75147dfd51d58d6ee3e552d Mon Sep 17 00:00:00 2001 From: Bernd Schubert Date: Mon, 24 Mar 2025 23:18:10 +0100 Subject: Add support for ring creation in fuse_lowlevel.c Signed-off-by: Bernd Schubert --- lib/fuse_i.h | 1 + lib/fuse_loop_mt.c | 5 +++++ lib/fuse_lowlevel.c | 31 +++++++++++++++++++++++++++++-- lib/fuse_uring_i.h | 27 +++++++++++++++++++++++++++ lib/util.h | 2 +- 5 files changed, 63 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/fuse_i.h b/lib/fuse_i.h index b643e90..23e58ef 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -61,6 +61,7 @@ struct fuse_notify_req { }; struct fuse_session_uring { + bool enable; unsigned int q_depth; struct fuse_ring_pool *pool; }; diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 46e2d6e..046256c 100644 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -15,6 +15,7 @@ #include "fuse_misc.h" #include "fuse_kernel.h" #include "fuse_i.h" +#include "fuse_uring_i.h" #include "util.h" #include @@ -407,12 +408,16 @@ int err; fuse_join_worker(&mt, mt.main.next); err = mt.error; + + if (se->uring.pool) + fuse_uring_stop(se); } pthread_mutex_destroy(&se->mt_lock); if(se->error != 0) err = se->error; + if (created_config) { fuse_loop_cfg_destroy(config); config = NULL; diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 4a4c71e..433594f 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -18,6 +18,7 @@ #include "fuse_misc.h" #include "mount_util.h" #include "util.h" +#include "fuse_uring_i.h" #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #ifdef USDT_ENABLED #include "usdt.h" @@ -46,7 +48,6 @@ #define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7) #endif - #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg))) #define OFFSET_MAX 0x7fffffffffffffffLL @@ -169,6 +170,10 @@ static void list_add_req(struct fuse_req *req, struct fuse_req *next) static void destroy_req(fuse_req_t req) { + if (req->is_uring) { + fuse_log(FUSE_LOG_ERR, "Refusing to destruct uring req\n"); + return; + } assert(req->ch == NULL); pthread_mutex_destroy(&req->lock); free(req); @@ -179,7 +184,11 @@ void fuse_free_req(fuse_req_t req) int ctr; struct fuse_session *se = req->se; - if (se->conn.no_interrupt) { + /* XXX: for now no support for interrupts with io-uring + * It actually might work alreasdy, though. But then would add + * a lock across ring queues. + */ + if (se->conn.no_interrupt || req->is_uring) { ctr = --req->ref_cnt; fuse_chan_put(req->ch); req->ch = NULL; @@ -209,6 +218,7 @@ static struct fuse_req *fuse_ll_alloc_req(struct fuse_session *se) req->ref_cnt = 1; list_init_req(req); pthread_mutex_init(&req->lock, NULL); + req->is_uring = false; } return req; @@ -2415,6 +2425,8 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, uint64_t outargflags = 0; bool buf_reallocable = se->buf_reallocable; (void) nodeid; + bool enable_io_uring = false; + if (se->debug) { fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor); if (arg->major == 7 && arg->minor >= 6) { @@ -2673,6 +2685,10 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, } if (se->conn.want_ext & FUSE_CAP_NO_EXPORT_SUPPORT) outargflags |= FUSE_NO_EXPORT_SUPPORT; + if (se->uring.enable && se->conn.want_ext & FUSE_CAP_OVER_IO_URING) { + outargflags |= FUSE_OVER_IO_URING; + enable_io_uring = true; + } if (inargflags & FUSE_INIT_EXT) { outargflags |= FUSE_INIT_EXT; @@ -2721,6 +2737,17 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in, outargsize = FUSE_COMPAT_22_INIT_OUT_SIZE; send_reply_ok(req, &outarg, outargsize); + + /* XXX: Split the start, and send SQEs only after send_reply_ok() */ + if (enable_io_uring) { + int ring_rc = fuse_uring_start(se); + + if (ring_rc != 0) { + fuse_log(FUSE_LOG_ERR, "fuse: failed to start io-uring: %s\n", + strerror(ring_rc)); + fuse_session_exit(se); + } + } } static __attribute__((no_sanitize("thread"))) void diff --git a/lib/fuse_uring_i.h b/lib/fuse_uring_i.h index fefb8a0..e9f2989 100644 --- a/lib/fuse_uring_i.h +++ b/lib/fuse_uring_i.h @@ -8,11 +8,38 @@ #ifndef FUSE_URING_I_H_ #define FUSE_URING_I_H_ +#include "fuse_config.h" #include "fuse_lowlevel.h" +#include "fuse_kernel.h" + +#ifndef HAVE_URING +#include "util.h" +#endif + +void fuse_session_process_uring_cqe(struct fuse_session *se, + struct fuse_req *req, + struct fuse_in_header *in, void *in_header, + void *in_payload, size_t payload_len); + +#ifdef HAVE_URING struct fuse_in_header; int fuse_uring_start(struct fuse_session *se); int fuse_uring_stop(struct fuse_session *se); +#else // HAVE_URING + +static inline int fuse_uring_start(struct fuse_session *se FUSE_VAR_UNUSED) +{ + return -ENOTSUP; +} + +static inline int fuse_uring_stop(struct fuse_session *se FUSE_VAR_UNUSED) +{ + return -ENOTSUP; +} + +#endif // HAVE_URING + #endif // FUSE_URING_I_H_ diff --git a/lib/util.h b/lib/util.h index d1939cf..96b59d3 100644 --- a/lib/util.h +++ b/lib/util.h @@ -28,7 +28,7 @@ static inline uint64_t fuse_higher_32_bits(uint64_t nr) } #ifndef FUSE_VAR_UNUSED -#define FUSE_VAR_UNUSED(var) (__attribute__((unused)) var) +#define FUSE_VAR_UNUSED __attribute__((__unused__)) #endif #define container_of(ptr, type, member) \ -- cgit v1.2.3