aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryangyun50 <149988609+yangyun50@users.noreply.github.com>2024-06-04 19:50:48 +0800
committerGitHub <noreply@github.com>2024-06-04 13:50:48 +0200
commitcef8c8b249023fb8129ae791e0998cbca771f96a (patch)
treef7e335bb6fe30feadaef0cac05c23fcb957f79ab
parent949944ff3bde50d62f98b0cab15cef2959d40a2d (diff)
downloadlibfuse-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.
-rw-r--r--example/cuse.c9
-rw-r--r--example/hello_ll.c9
-rw-r--r--example/hello_ll_uds.c9
-rw-r--r--example/notify_inval_entry.c8
-rw-r--r--example/notify_inval_inode.c8
-rw-r--r--example/notify_store_retrieve.c8
-rw-r--r--example/passthrough_hp.cc3
-rw-r--r--example/passthrough_ll.c3
-rw-r--r--include/fuse_common.h12
-rw-r--r--lib/fuse.c4
-rw-r--r--lib/fuse_lowlevel.c30
11 files changed, 93 insertions, 10 deletions
diff --git a/example/cuse.c b/example/cuse.c
index 0c0e7bc..6b33302 100644
--- a/example/cuse.c
+++ b/example/cuse.c
@@ -87,6 +87,14 @@ static int cusexmp_expand(size_t new_size)
return 0;
}
+static void cusexmp_init(void *userdata, struct fuse_conn_info *conn)
+{
+ (void)userdata;
+
+ /* Disable the receiving and processing of FUSE_INTERRUPT requests */
+ conn->no_interrupt = 1;
+}
+
static void cusexmp_open(fuse_req_t req, struct fuse_file_info *fi)
{
fuse_reply_open(req, fi);
@@ -281,6 +289,7 @@ static int cusexmp_process_arg(void *data, const char *arg, int key,
}
static const struct cuse_lowlevel_ops cusexmp_clop = {
+ .init = cusexmp_init,
.open = cusexmp_open,
.read = cusexmp_read,
.write = cusexmp_write,
diff --git a/example/hello_ll.c b/example/hello_ll.c
index 10f4b4a..28bd1c4 100644
--- a/example/hello_ll.c
+++ b/example/hello_ll.c
@@ -53,6 +53,14 @@ static int hello_stat(fuse_ino_t ino, struct stat *stbuf)
return 0;
}
+static void hello_ll_init(void *userdata, struct fuse_conn_info *conn)
+{
+ (void)userdata;
+
+ /* Disable the receiving and processing of FUSE_INTERRUPT requests */
+ conn->no_interrupt = 1;
+}
+
static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi)
{
@@ -202,6 +210,7 @@ static void hello_ll_removexattr(fuse_req_t req, fuse_ino_t ino, const char *nam
}
static const struct fuse_lowlevel_ops hello_ll_oper = {
+ .init = hello_ll_init,
.lookup = hello_ll_lookup,
.getattr = hello_ll_getattr,
.readdir = hello_ll_readdir,
diff --git a/example/hello_ll_uds.c b/example/hello_ll_uds.c
index f291fed..a566155 100644
--- a/example/hello_ll_uds.c
+++ b/example/hello_ll_uds.c
@@ -77,6 +77,14 @@ static void hello_ll_getattr(fuse_req_t req, fuse_ino_t ino,
fuse_reply_attr(req, &stbuf, 1.0);
}
+static void hello_ll_init(void *userdata, struct fuse_conn_info *conn)
+{
+ (void)userdata;
+
+ /* Disable the receiving and processing of FUSE_INTERRUPT requests */
+ conn->no_interrupt = 1;
+}
+
static void hello_ll_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
struct fuse_entry_param e;
@@ -164,6 +172,7 @@ static void hello_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
}
static const struct fuse_lowlevel_ops hello_ll_oper = {
+ .init = hello_ll_init,
.lookup = hello_ll_lookup,
.getattr = hello_ll_getattr,
.readdir = hello_ll_readdir,
diff --git a/example/notify_inval_entry.c b/example/notify_inval_entry.c
index 83b24d2..c307899 100644
--- a/example/notify_inval_entry.c
+++ b/example/notify_inval_entry.c
@@ -140,6 +140,13 @@ static int tfs_stat(fuse_ino_t ino, struct stat *stbuf) {
return 0;
}
+static void tfs_init(void *userdata, struct fuse_conn_info *conn) {
+ (void)userdata;
+
+ /* Disable the receiving and processing of FUSE_INTERRUPT requests */
+ conn->no_interrupt = 1;
+}
+
static void tfs_lookup(fuse_req_t req, fuse_ino_t parent,
const char *name) {
struct fuse_entry_param e;
@@ -232,6 +239,7 @@ static void tfs_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
}
static const struct fuse_lowlevel_ops tfs_oper = {
+ .init = tfs_init,
.lookup = tfs_lookup,
.getattr = tfs_getattr,
.readdir = tfs_readdir,
diff --git a/example/notify_inval_inode.c b/example/notify_inval_inode.c
index c0b1112..de88c87 100644
--- a/example/notify_inval_inode.c
+++ b/example/notify_inval_inode.c
@@ -123,6 +123,13 @@ static int tfs_stat(fuse_ino_t ino, struct stat *stbuf) {
return 0;
}
+static void tfs_init(void *userdata, struct fuse_conn_info *conn) {
+ (void)userdata;
+
+ /* Disable the receiving and processing of FUSE_INTERRUPT requests */
+ conn->no_interrupt = 1;
+}
+
static void tfs_destroy(void *userarg)
{
(void)userarg;
@@ -250,6 +257,7 @@ static void tfs_read(fuse_req_t req, fuse_ino_t ino, size_t size,
}
static const struct fuse_lowlevel_ops tfs_oper = {
+ .init = tfs_init,
.destroy = tfs_destroy,
.lookup = tfs_lookup,
.getattr = tfs_getattr,
diff --git a/example/notify_store_retrieve.c b/example/notify_store_retrieve.c
index 1298591..7145bf4 100644
--- a/example/notify_store_retrieve.c
+++ b/example/notify_store_retrieve.c
@@ -132,6 +132,13 @@ static int tfs_stat(fuse_ino_t ino, struct stat *stbuf) {
return 0;
}
+static void tfs_init(void *userdata, struct fuse_conn_info *conn) {
+ (void)userdata;
+
+ /* Disable the receiving and processing of FUSE_INTERRUPT requests */
+ conn->no_interrupt = 1;
+}
+
static void tfs_lookup(fuse_req_t req, fuse_ino_t parent,
const char *name) {
struct fuse_entry_param e;
@@ -304,6 +311,7 @@ static void tfs_destroy(void *userdata)
static const struct fuse_lowlevel_ops tfs_oper = {
+ .init = tfs_init,
.lookup = tfs_lookup,
.getattr = tfs_getattr,
.readdir = tfs_readdir,
diff --git a/example/passthrough_hp.cc b/example/passthrough_hp.cc
index 7b8febe..e780f23 100644
--- a/example/passthrough_hp.cc
+++ b/example/passthrough_hp.cc
@@ -223,6 +223,9 @@ static void sfs_init(void *userdata, fuse_conn_info *conn) {
/* This is a local file system - no network coherency needed */
if (conn->capable & FUSE_CAP_DIRECT_IO_ALLOW_MMAP)
conn->want |= FUSE_CAP_DIRECT_IO_ALLOW_MMAP;
+
+ /* Disable the receiving and processing of FUSE_INTERRUPT requests */
+ conn->no_interrupt = 1;
}
diff --git a/example/passthrough_ll.c b/example/passthrough_ll.c
index da9de53..87c18a2 100644
--- a/example/passthrough_ll.c
+++ b/example/passthrough_ll.c
@@ -181,6 +181,9 @@ static void lo_init(void *userdata,
fuse_log(FUSE_LOG_DEBUG, "lo_init: activating flock locks\n");
conn->want |= FUSE_CAP_FLOCK_LOCKS;
}
+
+ /* Disable the receiving and processing of FUSE_INTERRUPT requests */
+ conn->no_interrupt = 1;
}
static void lo_destroy(void *userdata)
diff --git a/include/fuse_common.h b/include/fuse_common.h
index ba4b127..c583af3 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -635,9 +635,19 @@ struct fuse_conn_info {
unsigned max_backing_stack_depth;
/**
+ * Disable FUSE_INTERRUPT requests.
+ *
+ * Enable `no_interrupt` option to:
+ * 1) Avoid unnecessary locking operations and list operations,
+ * 2) Return ENOSYS for the reply of FUSE_INTERRUPT request to
+ * inform the kernel not to send the FUSE_INTERRUPT request.
+ */
+ unsigned no_interrupt;
+
+ /**
* For future use.
*/
- unsigned reserved[21];
+ unsigned reserved[20];
};
struct fuse_session;
diff --git a/lib/fuse.c b/lib/fuse.c
index 8617168..4f06da7 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -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);