lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 20 Jun 2024 14:43:45 +0800
From: Haifeng Xu <haifeng.xu@...pee.com>
To: Christian Brauner <brauner@...nel.org>, Miklos Szeredi <miklos@...redi.hu>
Cc: linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [RFC] fuse: do not generate interrupt requests for fatal signals



On 2024/6/17 15:25, Christian Brauner wrote:
> On Fri, Jun 14, 2024 at 12:01:39PM GMT, Miklos Szeredi wrote:
>> On Thu, 13 Jun 2024 at 12:44, Haifeng Xu <haifeng.xu@...pee.com> wrote:
>>
>>> So why the client doesn't get woken up?
>>
>> Need to find out what the server (lxcfs) is doing.  Can you do a
>> strace of lxcfs to see the communication on the fuse device?
> 
> Fwiw, I'm one of the orignal authors and maintainers of LXCFS so if you
> have specific questions, I may be able to help.

Thanks. All server threads of lcxfs wokrs fine now.

So can we add another interface to abort those dead request?
If the client thread got killed and wait for relpy, but the fuse sever didn't 
send reply for some unknown reason,we can use this interface to wakeup the client thread.


diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index 97ac994ff78f..b171d03171e7 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -44,6 +44,17 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
 	return count;
 }

+static ssize_t fuse_abort_dead_requests_write(struct file *file, const char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
+	if (fc) {
+		fuse_abort_dead_requests(fc);
+		fuse_conn_put(fc);
+	}
+	return count;
+}
+
 static ssize_t fuse_conn_waiting_read(struct file *file, char __user *buf,
 				      size_t len, loff_t *ppos)
 {
@@ -186,6 +197,12 @@ static const struct file_operations fuse_ctl_abort_ops = {
 	.llseek = no_llseek,
 };

+static const struct file_operations fuse_ctl_abort_dead_requests_ops = {
+	.open = nonseekable_open,
+	.write = fuse_abort_dead_requests_write,
+	.llseek = no_llseek,
+};
+
 static const struct file_operations fuse_ctl_waiting_ops = {
 	.open = nonseekable_open,
 	.read = fuse_conn_waiting_read,
@@ -274,7 +291,10 @@ int fuse_ctl_add_conn(struct fuse_conn *fc)
 				 1, NULL, &fuse_conn_max_background_ops) ||
 	    !fuse_ctl_add_dentry(parent, fc, "congestion_threshold",
 				 S_IFREG | 0600, 1, NULL,
-				 &fuse_conn_congestion_threshold_ops))
+				 &fuse_conn_congestion_threshold_ops) ||
+	    !fuse_ctl_add_dentry(parent, fc, "abort_dead_requests",
+				 S_IFREG | 0200, 1, NULL,
+				 &fuse_ctl_abort_dead_requests_ops))
 		goto err;

 	return 0;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5fb830ad860d..77b54c5ea9bd 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2249,6 +2249,49 @@ void fuse_abort_conn(struct fuse_conn *fc)
 }
 EXPORT_SYMBOL_GPL(fuse_abort_conn);

+void fuse_abort_dead_requests(struct fuse_conn *fc)
+{
+	spin_lock(&fc->lock);
+	if (fc->connected) {
+		struct fuse_dev *fud;
+		struct fuse_req *req, *next;
+		LIST_HEAD(to_end);
+		unsigned int i;
+
+		list_for_each_entry(fud, &fc->devices, entry) {
+			struct fuse_pqueue *fpq = &fud->pq;
+
+			spin_lock(&fpq->lock);
+
+			for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) {
+				list_for_each_entry_safe(req, next, &fpq->processing[i], list) {
+					if (test_bit(FR_INTERRUPTED, &req->flags)) {
+						struct list_head *head = &req->waitq.head;
+						struct wait_queue_entry *wq;
+
+						list_for_each_entry(wq, head, entry) {
+							if (__fatal_signal_pending(wq->private)) {
+								list_move_tail(&req->list, &to_end);
+								break;
+							}
+						}
+
+					}
+
+				}
+			}
+
+			spin_unlock(&fpq->lock);
+		}
+
+		spin_unlock(&fc->lock);
+		end_requests(&to_end);
+	} else {
+		spin_unlock(&fc->lock);
+	}
+
+}
+
 void fuse_wait_aborted(struct fuse_conn *fc)
 {
 	/* matches implicit memory barrier in fuse_drop_waiting() */
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index f23919610313..fc8b5a7d1d0a 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -45,7 +45,7 @@
 #define FUSE_NAME_MAX 1024

 /** Number of dentries for each connection in the control filesystem */
-#define FUSE_CTL_NUM_DENTRIES 5
+#define FUSE_CTL_NUM_DENTRIES 6

 /** List of active connections */
 extern struct list_head fuse_conn_list;
@@ -1167,6 +1167,9 @@ void fuse_request_end(struct fuse_req *req);
 void fuse_abort_conn(struct fuse_conn *fc);
 void fuse_wait_aborted(struct fuse_conn *fc);

+/* Abort dead requests */
+void fuse_abort_dead_requests(struct fuse_conn *fc);
+
 /**
  * Invalidate inode attributes
  */

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ