Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp8446469pxu; Sun, 27 Dec 2020 06:46:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJxk9HBaZQl21ZzO9+xkrR1emIvXZx//h3f4Yn9w6V85EuJ0nIbeBR7bYoIwxIt1ujSqX8w/ X-Received: by 2002:a17:906:2da:: with SMTP id 26mr32764482ejk.15.1609080387731; Sun, 27 Dec 2020 06:46:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1609080387; cv=none; d=google.com; s=arc-20160816; b=uAUHDbOdBFMJsiSIbAx0SLKspST/HtwIj6tzdh/+QMv6NV+70HcSc/nSLlDBXfC/YE mgUg4UDbLPsrbLAQrkOlRuNEWVj07t/tjgxw3OYsIA3PnsrsW4NpebzLrts/jxXUiydQ VOGKTQ8XBoaaGb6fDZ4YxrqUO/D1pfGAwKJBncM14mqoznZ0G5/yzwmnn4RYLHtiYhl0 aDeguvY+5Rr7svZ2Ncv7uUtmrsGKGjbtIZhcgoceIdlMIlyl3jBI+vKe428jt1S5VxNZ pHUsz4LEkxjDW7hf3u5hITbZbVWkULRBVHTaA0qULlM8KtcFL8f1i7+RGxON+2bb/O48 O6mA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:date:content-transfer-encoding:mime-version :message-id:subject:cc:to:from:dkim-signature; bh=LlgK43BtTlQ6++cCaXNMqGTvJaDHPrjIe9skQ875zsU=; b=WtVa9SWtrPOQJo7GOEQB7LRLNZFd6wryvBvVrfdB6Ku11MbxaQy0WyN4dzPYVC/BYr VhVIWrfP6OmNAsQOOAPWVJoGw5jFa/W4xCqJyHr7R4bWhsUMnGlXm3RrRt3QqzPjeQzH QYtjGZgsxRtfj7lwRM7zF0pUbCcMQPEGSf6J0q4VYZk2nHXwv4JnZG5My/f0eg1RzNYw kzscdwYJtqzH4QwOcrRZwuaVLfXIA3S5o7Px1JMLrOEsZQ58hLNkaRgV71n+5WkOdhf0 6G8ebITZH+JwESAe+kWQ6tD8E2u0ym10QF6VDJQRcKq69L9n1PkYlRGCBC2BaaCzPE0f Mt9g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kl.wtf header.s=default header.b=aZDq9BZC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=kl.wtf Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id se25si17566591ejb.82.2020.12.27.06.46.04; Sun, 27 Dec 2020 06:46:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kl.wtf header.s=default header.b=aZDq9BZC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=kl.wtf Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726268AbgL0OoF (ORCPT + 99 others); Sun, 27 Dec 2020 09:44:05 -0500 Received: from out0.migadu.com ([94.23.1.103]:2966 "EHLO out0.migadu.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726209AbgL0OoA (ORCPT ); Sun, 27 Dec 2020 09:44:00 -0500 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kl.wtf; s=default; t=1609080193; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=LlgK43BtTlQ6++cCaXNMqGTvJaDHPrjIe9skQ875zsU=; b=aZDq9BZCFD7bl/5IBCqHSaWdcz0o/oKE/iW/wE7KvAwYEZ1RULC3uDsR3RkGpFtthTnTyN EfGrnhL6/cSKXY0J0iGwGsSEpo6jD+uuelqYx1a5JHd9poTzu5e6B++qVXhoQ3pUgly9+h F+rMEbCuUZsa8f0epZNI+MXp/Acdjww= From: Kenny Levinsen To: linux-input@vger.kernel.org Cc: dmitry.torokhov@gmail.com, linux-kernel@vger.kernel.org, Kenny Levinsen Subject: [PATCH] Input: evdev - use call_rcu when detaching client Message-Id: <20201227144302.9419-1-kl@kl.wtf> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT X-Migadu-Auth-User: kl@kl.wtf Date: Sun, 27 Dec 2020 14:43:13 GMT Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 #include 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 --- 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.29.2