diff options
author | yangyun50 <149988609+yangyun50@users.noreply.github.com> | 2024-06-04 19:50:48 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-04 13:50:48 +0200 |
commit | cef8c8b249023fb8129ae791e0998cbca771f96a (patch) | |
tree | f7e335bb6fe30feadaef0cac05c23fcb957f79ab /lib | |
parent | 949944ff3bde50d62f98b0cab15cef2959d40a2d (diff) | |
download | libfuse-cef8c8b249023fb8129ae791e0998cbca771f96a.tar.gz |
Add support for no_interrupt (#956)
The function fuse_session_process_buf_int() would do much things
for FUSE_INTERRUPT requests, even there are no FUSE_INTERRUPT requests:
1. check every non-FUSE_INTERRUPT request and add these requests to the
linked list(se->list) under a big lock(se->lock).
2. the function fuse_free_req() frees every request and remove them from
the linked list(se->list) under a bing lock(se->lock).
These operations are not meaningful when there are no FUSE_INTERRUPT requests,
and have a great impact on the performance of fuse filesystem because the big
lock for each request.
In some cases, FUSE_INTERRUPT requests are infrequent, even none at all.
Besides, the user-defined filesystem may do nothing for FUSE_INTERRUPT requests.
And the kernel side has the option "no_interrupt" in struct fuse_conn. This kernel option
can be enabled by return ENOSYS in libfuse for the reply of FUSE_INTERRUPT request.
But I don't find the code to enable the "no_interrupt" kernel option in libfuse.
So add the no_interrupt support, and when this operaion is enabled:
1. remove the useless locking operaions and list operations.
2. return ENOSYS for the reply of FUSE_INTERRUPT request to inform the kernel to disable
FUSE_INTERRUPT request.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fuse.c | 4 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 30 |
2 files changed, 25 insertions, 9 deletions
@@ -2612,6 +2612,10 @@ static void fuse_lib_init(void *data, struct fuse_conn_info *conn) if(conn->capable & FUSE_CAP_EXPORT_SUPPORT) conn->want |= FUSE_CAP_EXPORT_SUPPORT; fuse_fs_init(f->fs, conn, &f->conf); + + /* Disable the receiving and processing of FUSE_INTERRUPT requests */ + if (!f->conf.intr) + conn->no_interrupt = 1; } void fuse_fs_destroy(struct fuse_fs *fs) diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index dc1b7a6..92f7a99 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -134,14 +134,20 @@ void fuse_free_req(fuse_req_t req) int ctr; struct fuse_session *se = req->se; - pthread_mutex_lock(&se->lock); - req->u.ni.func = NULL; - req->u.ni.data = NULL; - list_del_req(req); - ctr = --req->ctr; - fuse_chan_put(req->ch); - req->ch = NULL; - pthread_mutex_unlock(&se->lock); + if (se->conn.no_interrupt) { + ctr = --req->ctr; + fuse_chan_put(req->ch); + req->ch = NULL; + } else { + pthread_mutex_lock(&se->lock); + req->u.ni.func = NULL; + req->u.ni.data = NULL; + list_del_req(req); + ctr = --req->ctr; + fuse_chan_put(req->ch); + req->ch = NULL; + pthread_mutex_unlock(&se->lock); + } if (!ctr) destroy_req(req); } @@ -2786,7 +2792,13 @@ void fuse_session_process_buf_int(struct fuse_session *se, err = ENOSYS; if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func) goto reply_err; - if (in->opcode != FUSE_INTERRUPT) { + /* Do not process interrupt request */ + if (se->conn.no_interrupt && in->opcode == FUSE_INTERRUPT) { + if (se->debug) + fuse_log(FUSE_LOG_DEBUG, "FUSE_INTERRUPT: reply to kernel to disable interrupt\n"); + goto reply_err; + } + if (!se->conn.no_interrupt && in->opcode != FUSE_INTERRUPT) { struct fuse_req *intr; pthread_mutex_lock(&se->lock); intr = check_interrupt(se, req); |