diff options
-rw-r--r-- | example/passthrough_hp.cc | 36 | ||||
-rw-r--r-- | include/fuse_lowlevel.h | 18 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 12 | ||||
-rw-r--r-- | lib/fuse_uring.c | 24 | ||||
-rw-r--r-- | lib/fuse_versionscript | 1 |
5 files changed, 87 insertions, 4 deletions
diff --git a/example/passthrough_hp.cc b/example/passthrough_hp.cc index a0bf0d5..2bdfc0a 100644 --- a/example/passthrough_hp.cc +++ b/example/passthrough_hp.cc @@ -1158,10 +1158,38 @@ static void sfs_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, static void do_read(fuse_req_t req, size_t size, off_t off, fuse_file_info *fi) { fuse_bufvec buf = FUSE_BUFVEC_INIT(size); - buf.buf[0].flags = - static_cast<fuse_buf_flags>(FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK); - buf.buf[0].fd = fi->fh; - buf.buf[0].pos = off; + char *payload = NULL; + size_t payload_size = 0; + int res = fuse_req_get_payload(req, &payload, &payload_size, NULL); + + /* + * This is a demonstration how to use io-uring payload. For FUSE_BUF_IS_FD + * it shouldn't make much of a difference because fuse_reply_data() -> + * fuse_reply_data_uring() also has access to the payload and will + * read directly from the FD into the payload. + * It is more useful for file systems that need a buffer for decryption, + * decompression, etc. + */ + if (res == 0) { + /* This is an io-uring request - write directly to the payload */ + assert(payload_size >= size); + + buf.buf[0].mem = payload; + buf.buf[0].size = payload_size; + + res = pread(fi->fh, payload, size, off); + if (res < 0) { + fuse_reply_err(req, errno); + return; + } + + buf.buf[0].size = res; + } else { + buf.buf[0].flags = static_cast<fuse_buf_flags>( + FUSE_BUF_IS_FD | FUSE_BUF_FD_SEEK); + buf.buf[0].fd = fi->fh; + buf.buf[0].pos = off; + } fuse_reply_data(req, &buf, FUSE_BUF_COPY_FLAGS); } diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index 844ee71..dc4ec07 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -2367,6 +2367,24 @@ int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf); */ bool fuse_req_is_uring(fuse_req_t req); +/** + * Get the payload of a request + * (for requests submitted through fuse-io-uring only) + * + * This is useful for a file system that wants to write data directly + * to the request buffer. With io-uring the req is the buffer owner + * and the file system can write directly to the buffer and avoid + * extra copying. For example useful for network file systems. + * + * @param req the request + * @param payload pointer to the payload + * @param payload_sz size of the payload + * @param mr memory registration handle, currently unused + * @return 0 on success, -errno on failure + */ +int fuse_req_get_payload(fuse_req_t req, char **payload, size_t *payload_sz, + void **mr); + #ifdef __cplusplus } #endif diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 6afcecd..e4544df 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -3317,6 +3317,18 @@ bool fuse_req_is_uring(fuse_req_t req) return req->is_uring; } +#ifndef HAVE_URING +int fuse_req_get_payload(fuse_req_t req, char **payload, size_t *payload_sz, + void **mr) +{ + (void)req; + (void)payload; + (void)payload_sz; + (void)mr; + return -ENOTSUP; +} +#endif + static struct { void (*func)(fuse_req_t req, const fuse_ino_t node, const void *arg); const char *name; diff --git a/lib/fuse_uring.c b/lib/fuse_uring.c index 104be14..ee68fab 100644 --- a/lib/fuse_uring.c +++ b/lib/fuse_uring.c @@ -190,6 +190,30 @@ static int fuse_uring_commit_sqe(struct fuse_ring_pool *ring_pool, return 0; } +int fuse_req_get_payload(fuse_req_t req, char **payload, size_t *payload_sz, + void **mr) +{ + struct fuse_ring_ent *ring_ent; + + /* Not possible without io-uring interface */ + if (!req->is_uring) + return -EINVAL; + + ring_ent = container_of(req, struct fuse_ring_ent, req); + + *payload = ring_ent->op_payload; + *payload_sz = ring_ent->req_payload_sz; + + /* + * For now unused, but will be used later when the application can + * allocate the buffers itself and register them for rdma. + */ + if (mr) + *mr = NULL; + + return 0; +} + int send_reply_uring(fuse_req_t req, int error, const void *arg, size_t argsize) { int res; diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index 0e581f1..2feafcf 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -205,6 +205,7 @@ FUSE_3.17 { FUSE_3.18 { global: fuse_req_is_uring; + fuse_req_get_payload; fuse_set_feature_flag; fuse_unset_feature_flag; fuse_get_feature_flag; |