diff options
author | Björn Bidar | 2022-03-25 02:51:40 +0200 |
---|---|---|
committer | Björn Bidar | 2022-06-11 14:10:58 +0300 |
commit | 05a0260e8dc51ce338d4ba7d1a9ffcd6b73d04b2 (patch) | |
tree | 5685de18d1c76307f59556bfbe7d2aa2f461b601 /0008-ZEN-Input-evdev-use-call_rcu-when-detaching-client.patch | |
parent | 2c114d74749ddbf43bad8b112b3674bd81d01d27 (diff) | |
download | aur-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.patch | 110 |
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 + |