Re: [RFC] fuse: do not generate interrupt requests for fatal signals

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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@xxxxxxxxxx> 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
  */




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux