summarylogtreecommitdiffstats
path: root/0008-ZEN-Input-evdev-use-call_rcu-when-detaching-client.patch
diff options
context:
space:
mode:
authorBjörn Bidar2022-03-25 02:51:40 +0200
committerBjörn Bidar2022-06-11 14:10:58 +0300
commit05a0260e8dc51ce338d4ba7d1a9ffcd6b73d04b2 (patch)
tree5685de18d1c76307f59556bfbe7d2aa2f461b601 /0008-ZEN-Input-evdev-use-call_rcu-when-detaching-client.patch
parent2c114d74749ddbf43bad8b112b3674bd81d01d27 (diff)
downloadaur-05a0260e8dc51ce338d4ba7d1a9ffcd6b73d04b2.tar.gz
Update to 5.17.0.pf1
- New upstream release based on 5.17.0 - Update kernel configs from arch and arch32 - Disable projectc patch-set for now in favor of ZEN interactive patches
Diffstat (limited to '0008-ZEN-Input-evdev-use-call_rcu-when-detaching-client.patch')
-rw-r--r--0008-ZEN-Input-evdev-use-call_rcu-when-detaching-client.patch110
1 files changed, 110 insertions, 0 deletions
diff --git a/0008-ZEN-Input-evdev-use-call_rcu-when-detaching-client.patch b/0008-ZEN-Input-evdev-use-call_rcu-when-detaching-client.patch
new file mode 100644
index 000000000000..dbc1360bab79
--- /dev/null
+++ b/0008-ZEN-Input-evdev-use-call_rcu-when-detaching-client.patch
@@ -0,0 +1,110 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Kenny Levinsen <kl@kl.wtf>
+Date: Sun, 27 Dec 2020 14:43:13 +0000
+Subject: [PATCH] ZEN: Input: evdev - use call_rcu when detaching client
+
+Significant time was spent on synchronize_rcu in evdev_detach_client
+when applications closed evdev devices. Switching VT away from a
+graphical environment commonly leads to mass input device closures,
+which could lead to noticable delays on systems with many input devices.
+
+Replace synchronize_rcu with call_rcu, deferring reclaim of the evdev
+client struct till after the RCU grace period instead of blocking the
+calling application.
+
+While this does not solve all slow evdev fd closures, it takes care of a
+good portion of them, including this simple test:
+
+ #include <fcntl.h>
+ #include <unistd.h>
+
+ int main(int argc, char *argv[])
+ {
+ int idx, fd;
+ const char *path = "/dev/input/event0";
+ for (idx = 0; idx < 1000; idx++) {
+ if ((fd = open(path, O_RDWR)) == -1) {
+ return -1;
+ }
+ close(fd);
+ }
+ return 0;
+ }
+
+Time to completion of above test when run locally:
+
+ Before: 0m27.111s
+ After: 0m0.018s
+
+Signed-off-by: Kenny Levinsen <kl@kl.wtf>
+---
+ drivers/input/evdev.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
+index 95f90699d2b1..2b10fe29d2c8 100644
+--- a/drivers/input/evdev.c
++++ b/drivers/input/evdev.c
+@@ -46,6 +46,7 @@ struct evdev_client {
+ struct fasync_struct *fasync;
+ struct evdev *evdev;
+ struct list_head node;
++ struct rcu_head rcu;
+ enum input_clock_type clk_type;
+ bool revoked;
+ unsigned long *evmasks[EV_CNT];
+@@ -377,13 +378,22 @@ static void evdev_attach_client(struct evdev *evdev,
+ spin_unlock(&evdev->client_lock);
+ }
+
++static void evdev_reclaim_client(struct rcu_head *rp)
++{
++ struct evdev_client *client = container_of(rp, struct evdev_client, rcu);
++ unsigned int i;
++ for (i = 0; i < EV_CNT; ++i)
++ bitmap_free(client->evmasks[i]);
++ kvfree(client);
++}
++
+ static void evdev_detach_client(struct evdev *evdev,
+ struct evdev_client *client)
+ {
+ spin_lock(&evdev->client_lock);
+ list_del_rcu(&client->node);
+ spin_unlock(&evdev->client_lock);
+- synchronize_rcu();
++ call_rcu(&client->rcu, evdev_reclaim_client);
+ }
+
+ static int evdev_open_device(struct evdev *evdev)
+@@ -436,7 +446,6 @@ static int evdev_release(struct inode *inode, struct file *file)
+ {
+ struct evdev_client *client = file->private_data;
+ struct evdev *evdev = client->evdev;
+- unsigned int i;
+
+ mutex_lock(&evdev->mutex);
+
+@@ -448,11 +457,6 @@ static int evdev_release(struct inode *inode, struct file *file)
+
+ evdev_detach_client(evdev, client);
+
+- for (i = 0; i < EV_CNT; ++i)
+- bitmap_free(client->evmasks[i]);
+-
+- kvfree(client);
+-
+ evdev_close_device(evdev);
+
+ return 0;
+@@ -495,7 +499,6 @@ static int evdev_open(struct inode *inode, struct file *file)
+
+ err_free_client:
+ evdev_detach_client(evdev, client);
+- kvfree(client);
+ return error;
+ }
+
+--
+2.35.1
+