aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--example/passthrough_hp.cc36
-rw-r--r--include/fuse_lowlevel.h18
-rw-r--r--lib/fuse_lowlevel.c12
-rw-r--r--lib/fuse_uring.c24
-rw-r--r--lib/fuse_versionscript1
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;