aboutsummaryrefslogtreecommitdiffstats
path: root/lib/fuse_lowlevel.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fuse_lowlevel.c')
-rw-r--r--lib/fuse_lowlevel.c70
1 files changed, 43 insertions, 27 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index d6b254e..03aeca7 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -227,21 +227,22 @@ static struct fuse_req *fuse_ll_alloc_req(struct fuse_session *se)
/*
* Send data to fuse-kernel using an fd of the fuse device.
*/
-static int _fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch,
- struct iovec *iov, int count)
+static int fuse_write_msg_dev(struct fuse_session *se, struct fuse_chan *ch,
+ struct iovec *iov, int count)
{
ssize_t res;
int err;
- if (se->io != NULL) {
+ if (se->io != NULL)
+
/* se->io->writev is never NULL if se->io is not NULL as
* specified by fuse_session_custom_io()
*/
res = se->io->writev(ch ? ch->fd : se->fd, iov, count,
se->userdata);
- } else {
+ else
res = writev(ch ? ch->fd : se->fd, iov, count);
- }
+
if (res == -1) {
/* ENOENT means the operation was interrupted */
err = errno;
@@ -253,15 +254,17 @@ static int _fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch,
return 0;
}
-/* Send data. If *ch* is NULL, send via session master fd */
static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch,
- struct iovec *iov, int count)
+ struct iovec *iov, int count, fuse_req_t req)
{
struct fuse_out_header *out = iov[0].iov_base;
int err;
+ bool is_uring = req && req->is_uring ? true : false;
- assert(se != NULL);
+ if (!is_uring)
+ assert(se != NULL);
out->len = iov_length(iov, count);
+
if (se->debug) {
if (out->unique == 0) {
fuse_log(FUSE_LOG_DEBUG, "NOTIFY: code=%d length=%u\n",
@@ -278,12 +281,15 @@ static int fuse_send_msg(struct fuse_session *se, struct fuse_chan *ch,
}
}
- err = _fuse_send_msg(se, ch, iov, count);
+ if (is_uring)
+ err = fuse_send_msg_uring(req, iov, count);
+ else
+ err = fuse_write_msg_dev(se, ch, iov, count);
+
trace_request_reply(out->unique, out->len, out->error, err);
return err;
}
-
int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
int count)
{
@@ -305,7 +311,7 @@ int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
iov[0].iov_base = &out;
iov[0].iov_len = sizeof(struct fuse_out_header);
- return fuse_send_msg(req->se, req->ch, iov, count);
+ return fuse_send_msg(req->se, req->ch, iov, count, req);
}
static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
@@ -321,6 +327,9 @@ static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
static int send_reply(fuse_req_t req, int error, const void *arg,
size_t argsize)
{
+ if (req->is_uring)
+ return send_reply_uring(req, error, arg, argsize);
+
struct iovec iov[2];
int count = 1;
if (argsize) {
@@ -599,7 +608,7 @@ static int fuse_send_data_iov_fallback(struct fuse_session *se,
struct fuse_chan *ch,
struct iovec *iov, int iov_count,
struct fuse_bufvec *buf,
- size_t len)
+ size_t len, fuse_req_t req)
{
struct fuse_bufvec mem_buf = FUSE_BUFVEC_INIT(len);
void *mbuf;
@@ -614,7 +623,7 @@ static int fuse_send_data_iov_fallback(struct fuse_session *se,
iov[iov_count].iov_base = buf->buf[0].mem;
iov[iov_count].iov_len = len;
iov_count++;
- return fuse_send_msg(se, ch, iov, iov_count);
+ return fuse_send_msg(se, ch, iov, iov_count, req);
}
res = posix_memalign(&mbuf, pagesize, len);
@@ -632,7 +641,7 @@ static int fuse_send_data_iov_fallback(struct fuse_session *se,
iov[iov_count].iov_base = mbuf;
iov[iov_count].iov_len = len;
iov_count++;
- res = fuse_send_msg(se, ch, iov, iov_count);
+ res = fuse_send_msg(se, ch, iov, iov_count, req);
free(mbuf);
return res;
@@ -764,8 +773,9 @@ static int grow_pipe_to_max(int pipefd)
}
static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
- struct iovec *iov, int iov_count,
- struct fuse_bufvec *buf, unsigned int flags)
+ struct iovec *iov, int iov_count,
+ struct fuse_bufvec *buf, unsigned int flags,
+ fuse_req_t req)
{
int res;
size_t len = fuse_buf_size(buf);
@@ -917,7 +927,7 @@ static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
iov[iov_count].iov_base = mbuf;
iov[iov_count].iov_len = len;
iov_count++;
- res = fuse_send_msg(se, ch, iov, iov_count);
+ res = fuse_send_msg(se, ch, iov, iov_count, req);
free(mbuf);
return res;
}
@@ -964,17 +974,17 @@ clear_pipe:
return res;
fallback:
- return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len);
+ return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len, req);
}
#else
static int fuse_send_data_iov(struct fuse_session *se, struct fuse_chan *ch,
struct iovec *iov, int iov_count,
- struct fuse_bufvec *buf, unsigned int flags)
+ struct fuse_bufvec *req_data, unsigned int flags)
{
- size_t len = fuse_buf_size(buf);
+ size_t len = fuse_buf_size(req_data);
(void) flags;
- return fuse_send_data_iov_fallback(se, ch, iov, iov_count, buf, len);
+ return fuse_send_data_iov_fallback(se, ch, iov, iov_count, req_data, len);
}
#endif
@@ -985,13 +995,16 @@ int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv,
struct fuse_out_header out;
int res;
+ if (req->is_uring)
+ return fuse_reply_data_uring(req, bufv, flags);
+
iov[0].iov_base = &out;
iov[0].iov_len = sizeof(struct fuse_out_header);
out.unique = req->unique;
out.error = 0;
- res = fuse_send_data_iov(req->se, req->ch, iov, 1, bufv, flags);
+ res = fuse_send_data_iov(req->se, req->ch, iov, 1, bufv, flags, req);
if (res <= 0) {
fuse_free_req(req);
return res;
@@ -1743,8 +1756,8 @@ static void do_write_buf(fuse_req_t req, const fuse_ino_t nodeid,
sizeof(struct fuse_write_in);
}
if (bufv.buf[0].size < arg->size) {
- fuse_log(FUSE_LOG_ERR, "fuse: %s: buffer size too small\n",
- __func__);
+ fuse_log(FUSE_LOG_ERR,
+ "fuse: %s: buffer size too small\n", __func__);
fuse_reply_err(req, EIO);
goto out;
}
@@ -2576,6 +2589,7 @@ _do_init(fuse_req_t req, const fuse_ino_t nodeid, const void *op_in,
LL_SET_DEFAULT(se->op.readdirplus, FUSE_CAP_READDIRPLUS);
LL_SET_DEFAULT(se->op.readdirplus && se->op.readdir,
FUSE_CAP_READDIRPLUS_AUTO);
+ LL_SET_DEFAULT(1, FUSE_CAP_OVER_IO_URING);
/* This could safely become default, but libfuse needs an API extension
* to support it
@@ -2840,6 +2854,7 @@ static int send_notify_iov(struct fuse_session *se, int notify_code,
struct iovec *iov, int count)
{
struct fuse_out_header out;
+ struct fuse_req *req = NULL;
if (!se->got_init)
return -ENOTCONN;
@@ -2849,7 +2864,7 @@ static int send_notify_iov(struct fuse_session *se, int notify_code,
iov[0].iov_base = &out;
iov[0].iov_len = sizeof(struct fuse_out_header);
- return fuse_send_msg(se, NULL, iov, count);
+ return fuse_send_msg(se, NULL, iov, count, req);
}
int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
@@ -2991,6 +3006,7 @@ int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino,
struct iovec iov[3];
size_t size = fuse_buf_size(bufv);
int res;
+ struct fuse_req *req = NULL;
if (!se)
return -EINVAL;
@@ -3011,7 +3027,7 @@ int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino,
iov[1].iov_base = &outarg;
iov[1].iov_len = sizeof(outarg);
- res = fuse_send_data_iov(se, NULL, iov, 2, bufv, flags);
+ res = fuse_send_data_iov(se, NULL, iov, 2, bufv, flags, req);
if (res > 0)
res = -res;
@@ -3392,7 +3408,7 @@ void fuse_session_process_buf_internal(struct fuse_session *se,
.iov_len = sizeof(struct fuse_out_header),
};
- fuse_send_msg(se, ch, &iov, 1);
+ fuse_send_msg(se, ch, &iov, 1, NULL);
goto clear_pipe;
}