From nobody Mon Dec 1 22:00:26 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA36A23817E for ; Fri, 28 Nov 2025 01:23:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764293002; cv=none; b=f+np1S40tyJWJ6f9L4iRtnP7exJLdPD1TT4PlUKYP46eDRwZngtjEqdCVT+V3EIXUo3Bu218aMQicgxgs9UJ11Kl4457uGRX6qvKARSlUELt83CGFOp6gaJvWbphq/I3vH58zM4r5T+QEVdPIBLyq/nxBNZNKv/9Gk4XKKxUhCQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764293002; c=relaxed/simple; bh=38p3e3WjY5GaqZjp+K1iy1pJnX35CZ1f+nBXLEr1z0o=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=oOhPiuCcYGaS15PEQHF6r94qpcmaaB2Y15Ca245ocTJ6XknMqw5P09YlLiVEHIrdQD0qLUAow00E+almqAp524GDOl8Iso8zHNV8WHX0GOAQhuhaOLl49k28quoobgSl6dQZsxlAbasoWdyfKWA9+rZhlE0HuoNE/H0NtjCbjkk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fjyVRdAJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fjyVRdAJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9DCAEC113D0; Fri, 28 Nov 2025 01:23:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1764293002; bh=38p3e3WjY5GaqZjp+K1iy1pJnX35CZ1f+nBXLEr1z0o=; h=Date:From:To:Cc:Subject:References:From; b=fjyVRdAJ/Pj/vAwhkQkLPe54G2jcnwM4OGg5AMQuVWAYw25QBbemMc5Acl+jq1H8Q /hQyi5tng79WCqDMDQ7f3i29gyK7CkBzMYiIB4yvS74Qjem3IeGPRClvLMUNAXYJMc +YwyQrVOJ3yxGxJnyBDE3o1XO3smYqkKUbRoRKjPAyT7O0YFEohPmFk23uOa805C7K 9kfe/O1dVs/x1O2EdTTTz7P/rEbejhjxCKqNVWsO55yxD/xqAd2wqLGlam+ZqYyjJd 0mmC73Ta9JySavPZLyCP5A5siUE6i7F9j0BGyZeRPDEhhtXrTgi8Dq6uAIoafEUyj+ 8yVf7gvNyroeQ== Received: from rostedt by gandalf with local (Exim 4.98.2) (envelope-from ) id 1vOnDY-00000006ghF-1Gru; Thu, 27 Nov 2025 20:24:12 -0500 Message-ID: <20251128012412.155385563@kernel.org> User-Agent: quilt/0.68 Date: Thu, 27 Nov 2025 20:23:39 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Tom Zanussi Subject: [for-next][PATCH 08/13] tracing: Add bulk garbage collection of freeing event_trigger_data References: <20251128012331.307010654@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Steven Rostedt The event trigger data requires a full tracepoint_synchronize_unregister() call before freeing. That call can take 100s of milliseconds to complete. In order to allow for bulk freeing of the trigger data, it can not call the tracepoint_synchronize_unregister() for every individual trigger data being free. Create a kthread that gets created the first time a trigger data is freed, and have it use the lockless llist to get the list of data to free, run the tracepoint_synchronize_unregister() then free everything in the list. By freeing hundreds of event_trigger_data elements together, it only requires two runs of the synchronization function, and not hundreds of runs. This speeds up the operation by orders of magnitude (milliseconds instead of several seconds). Cc: Mark Rutland Cc: Mathieu Desnoyers Cc: Andrew Morton Cc: Tom Zanussi Link: https://patch.msgid.link/20251125214032.151674992@kernel.org Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace.h | 2 ++ kernel/trace/trace_events_trigger.c | 55 +++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 901aad30099b..a3aa225ed50a 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -22,6 +22,7 @@ #include #include #include +#include =20 #include "pid_list.h" =20 @@ -1808,6 +1809,7 @@ struct event_trigger_data { char *name; struct list_head named_list; struct event_trigger_data *named_data; + struct llist_node llist; }; =20 /* Avoid typos */ diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_event= s_trigger.c index e5dcfcbb2cd5..3b97c242b795 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -6,6 +6,7 @@ */ =20 #include +#include #include #include #include @@ -17,15 +18,63 @@ static LIST_HEAD(trigger_commands); static DEFINE_MUTEX(trigger_cmd_mutex); =20 +static struct task_struct *trigger_kthread; +static struct llist_head trigger_data_free_list; +static DEFINE_MUTEX(trigger_data_kthread_mutex); + +/* Bulk garbage collection of event_trigger_data elements */ +static int trigger_kthread_fn(void *ignore) +{ + struct event_trigger_data *data, *tmp; + struct llist_node *llnodes; + + /* Once this task starts, it lives forever */ + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (llist_empty(&trigger_data_free_list)) + schedule(); + + __set_current_state(TASK_RUNNING); + + llnodes =3D llist_del_all(&trigger_data_free_list); + + /* make sure current triggers exit before free */ + tracepoint_synchronize_unregister(); + + llist_for_each_entry_safe(data, tmp, llnodes, llist) + kfree(data); + } + + return 0; +} + void trigger_data_free(struct event_trigger_data *data) { if (data->cmd_ops->set_filter) data->cmd_ops->set_filter(NULL, data, NULL); =20 - /* make sure current triggers exit before free */ - tracepoint_synchronize_unregister(); + if (unlikely(!trigger_kthread)) { + guard(mutex)(&trigger_data_kthread_mutex); + /* Check again after taking mutex */ + if (!trigger_kthread) { + struct task_struct *kthread; + + kthread =3D kthread_create(trigger_kthread_fn, NULL, + "trigger_data_free"); + if (!IS_ERR(kthread)) + WRITE_ONCE(trigger_kthread, kthread); + } + } + + if (!trigger_kthread) { + /* Do it the slow way */ + tracepoint_synchronize_unregister(); + kfree(data); + return; + } =20 - kfree(data); + llist_add(&data->llist, &trigger_data_free_list); + wake_up_process(trigger_kthread); } =20 static inline void data_ops_trigger(struct event_trigger_data *data, --=20 2.51.0