Received: by 2002:ab2:7903:0:b0:1fb:b500:807b with SMTP id a3csp1186780lqj; Mon, 3 Jun 2024 12:55:26 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCXi1f8eWSKpx/k8t6XE4TLq9r/3hhwI1aXsV1gpEaoVIIAQuFYyoqET1tGbx/QRpIQevFpBkRnZ2iuT+pyToPJq0nrGTexJKmTIyzd+FQ== X-Google-Smtp-Source: AGHT+IFPEvWvtGNf9WsD2S5JJXyu/N7xoQnW3fHcD/JKuFdJBCbn6+603ARmru/6W506cMiXY/4d X-Received: by 2002:a17:90a:9e9:b0:2c2:10b5:237c with SMTP id 98e67ed59e1d1-2c210b5281cmr4590791a91.49.1717444525746; Mon, 03 Jun 2024 12:55:25 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1717444525; cv=pass; d=google.com; s=arc-20160816; b=1KXTTU7JYnANV77HN90acAmSxliPXPdSVNLlDAKmcjaCsrWFA9T99aI/YQPUJki4vF tWU5fjY36/0YrbBG+oNS1JvRCR+SoAeldLxiHJxk+F03jy/FMtWxuHG44EAyCWqa/ptY GjU9fjfsUCoqbwvKZEPylNmRFBe9VasfSCcR51wKZpBmt44XBZISJ1Esl1778f7ukH7w wBkOtDsFgXKw57iUFDpr3osEfkg8G3Mu/HC9FbRZFdLhLfEmmGfEgIoInfiW1vCglkRl ib5VMuomy250pKStS9Wi2ZbYJHAU3pJXDAJpfqFMiyc8FNTzf4+0Rev9IMXiyrywxgdi n2jQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:list-unsubscribe:list-subscribe:list-id:precedence :references:subject:cc:to:from:date:user-agent:message-id; bh=++I1NyAkNz2uPudrH/y1pjRep8mLSBsMVaVWdvapkDI=; fh=YfcaVrAzBpSwi8dOlqHV4K1os6qdULs4cyXFG/DyLfE=; b=pF9VpatjKYQOmjRWJ0/R3oxBPy1U5rp5g/7LJRcRm9KYzMKhbSmKZWf53RCyh/IE4q CdfoXH6wotajSaes6Mg9dmJ7sujGxIZcf+oGu+Eo35mXM8ZYeFmeucFsrBOHk+h0wOi1 5UAUdFKuVEM3SXeSRmsKp7k0h+xGBEX/IJL7fE/o63gc3G0eukOuQixalrZLPdVpkzl2 ucoPWbTVHIWf4+RqSukhvcC81e0Ye/N/aqvbfIguZsCWxVImOIDzRKqYnzBfVdPiP9vs kh4/mCmgr4+qearCOI4JJE1hSN+2Jwx4H5W/8EyEfEIpE2BEzjVIVzHJa4+7WxyS2SWe eKmg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of linux-kernel+bounces-199599-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-199599-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [2604:1380:40f1:3f00::1]) by mx.google.com with ESMTPS id 98e67ed59e1d1-2c1c282b756si6989203a91.119.2024.06.03.12.55.25 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jun 2024 12:55:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-199599-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) client-ip=2604:1380:40f1:3f00::1; Authentication-Results: mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of linux-kernel+bounces-199599-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:40f1:3f00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-199599-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id B529DB23F6B for ; Mon, 3 Jun 2024 19:08:01 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BB88713BC03; Mon, 3 Jun 2024 19:07:11 +0000 (UTC) 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 D688813A876; Mon, 3 Jun 2024 19:07:10 +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=1717441630; cv=none; b=WNRYxhxpDL1S5cFp0cqFBHbK2sy8UWvWc9qTIqe0oO+JK0UsypGw4EI4Znxvbej17yoDbABJUUFr6YS+moD1dXGNehXxTtsv0nLh+GYVpH4JNeEK23mFkdnfnwa4vjS61xImsg5gYPyZzdOcEtmAQdPRQuxvj+x+JYm90OqwaWA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717441630; c=relaxed/simple; bh=cxxSM/VMsMhJL+nDS/iAO5zz7lQPJbtvfAZavgYyWdM=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=YDnImufCGLHdpJdH9WfJrW4WtKgssp74dg/oW4Rg0MD4BtINm3/6z4Qtk1kh/kTwNtxEQGH/n0SMkV3p5ZhPt9O+Yh+yNtzHGlsEqV7Wrl7vuvl6XY7d3P7Ik9Vf9wPl8ahdyx+cCF4jTc1bHJEeuaXtpVAg3QthMfwaTHCqyTk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7DF6DC4AF15; Mon, 3 Jun 2024 19:07:10 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.97) (envelope-from ) id 1sED2b-00000009TnV-2F9W; Mon, 03 Jun 2024 15:08:21 -0400 Message-ID: <20240603190821.392113213@goodmis.org> User-Agent: quilt/0.68 Date: Mon, 03 Jun 2024 15:07:07 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Alexei Starovoitov , Florent Revest , Martin KaFai Lau , bpf , Sven Schnelle , Alexei Starovoitov , Jiri Olsa , Arnaldo Carvalho de Melo , Daniel Borkmann , Alan Maguire , Peter Zijlstra , Thomas Gleixner , Guo Ren Subject: [PATCH v3 03/27] function_graph: Add an array structure that will allow multiple callbacks References: <20240603190704.663840775@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 From: "Steven Rostedt (VMware)" Add an array structure that will eventually allow the function graph tracer to have up to 16 simultaneous callbacks attached. It's an array of 16 fgraph_ops pointers, that is assigned when one is registered. On entry of a function the entry of the first item in the array is called, and if it returns zero, then the callback returns non zero if it wants the return callback to be called on exit of the function. The array will simplify the process of having more than one callback attached to the same function, as its index into the array can be stored on the shadow stack. We need to only save the index, because this will allow the fgraph_ops to be freed before the function returns (which may happen if the function call schedule for a long time). Co-developed with Masami Hiramatsu: Link: https://lore.kernel.org/linux-trace-kernel/171509095075.162236.8272148192748284581.stgit@devnote2 Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/fgraph.c | 114 ++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 33 deletions(-) diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c index fdb206aeffe3..d2ce5d651cf0 100644 --- a/kernel/trace/fgraph.c +++ b/kernel/trace/fgraph.c @@ -52,6 +52,11 @@ DEFINE_STATIC_KEY_FALSE(kill_ftrace_graph); int ftrace_graph_active; +static int fgraph_array_cnt; +#define FGRAPH_ARRAY_SIZE 16 + +static struct fgraph_ops *fgraph_array[FGRAPH_ARRAY_SIZE]; + /* Both enabled by default (can be cleared by function_graph tracer flags */ static bool fgraph_sleep_time = true; @@ -75,6 +80,20 @@ int __weak ftrace_disable_ftrace_graph_caller(void) } #endif +int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) +{ + return 0; +} + +static void ftrace_graph_ret_stub(struct ftrace_graph_ret *trace) +{ +} + +static struct fgraph_ops fgraph_stub = { + .entryfunc = ftrace_graph_entry_stub, + .retfunc = ftrace_graph_ret_stub, +}; + /** * ftrace_graph_stop - set to permanently disable function graph tracing * @@ -161,7 +180,7 @@ int function_graph_enter(unsigned long ret, unsigned long func, goto out; /* Only trace if the calling function expects to */ - if (!ftrace_graph_entry(&trace)) + if (!fgraph_array[0]->entryfunc(&trace)) goto out_ret; return 0; @@ -276,7 +295,7 @@ static unsigned long __ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs trace.retval = fgraph_ret_regs_return_value(ret_regs); #endif trace.rettime = trace_clock_local(); - ftrace_graph_return(&trace); + fgraph_array[0]->retfunc(&trace); /* * The ftrace_graph_return() may still access the current * ret_stack structure, we need to make sure the update of @@ -412,11 +431,6 @@ void ftrace_graph_sleep_time_control(bool enable) fgraph_sleep_time = enable; } -int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) -{ - return 0; -} - /* * Simply points to ftrace_stub, but with the proper protocol. * Defined by the linker script in linux/vmlinux.lds.h @@ -654,37 +668,54 @@ static int start_graph_tracing(void) int register_ftrace_graph(struct fgraph_ops *gops) { int ret = 0; + int i; mutex_lock(&ftrace_lock); - /* we currently allow only one tracer registered at a time */ - if (ftrace_graph_active) { + if (!fgraph_array[0]) { + /* The array must always have real data on it */ + for (i = 0; i < FGRAPH_ARRAY_SIZE; i++) + fgraph_array[i] = &fgraph_stub; + } + + /* Look for an available spot */ + for (i = 0; i < FGRAPH_ARRAY_SIZE; i++) { + if (fgraph_array[i] == &fgraph_stub) + break; + } + if (i >= FGRAPH_ARRAY_SIZE) { ret = -EBUSY; goto out; } - register_pm_notifier(&ftrace_suspend_notifier); + fgraph_array[i] = gops; + if (i + 1 > fgraph_array_cnt) + fgraph_array_cnt = i + 1; ftrace_graph_active++; - ret = start_graph_tracing(); - if (ret) { - ftrace_graph_active--; - goto out; - } - ftrace_graph_return = gops->retfunc; + if (ftrace_graph_active == 1) { + register_pm_notifier(&ftrace_suspend_notifier); + ret = start_graph_tracing(); + if (ret) { + ftrace_graph_active--; + goto out; + } + + ftrace_graph_return = gops->retfunc; - /* - * Update the indirect function to the entryfunc, and the - * function that gets called to the entry_test first. Then - * call the update fgraph entry function to determine if - * the entryfunc should be called directly or not. - */ - __ftrace_graph_entry = gops->entryfunc; - ftrace_graph_entry = ftrace_graph_entry_test; - update_function_graph_func(); + /* + * Update the indirect function to the entryfunc, and the + * function that gets called to the entry_test first. Then + * call the update fgraph entry function to determine if + * the entryfunc should be called directly or not. + */ + __ftrace_graph_entry = gops->entryfunc; + ftrace_graph_entry = ftrace_graph_entry_test; + update_function_graph_func(); - ret = ftrace_startup(&graph_ops, FTRACE_START_FUNC_RET); + ret = ftrace_startup(&graph_ops, FTRACE_START_FUNC_RET); + } out: mutex_unlock(&ftrace_lock); return ret; @@ -692,19 +723,36 @@ int register_ftrace_graph(struct fgraph_ops *gops) void unregister_ftrace_graph(struct fgraph_ops *gops) { + int i; + mutex_lock(&ftrace_lock); if (unlikely(!ftrace_graph_active)) goto out; - ftrace_graph_active--; - ftrace_graph_return = ftrace_stub_graph; - ftrace_graph_entry = ftrace_graph_entry_stub; - __ftrace_graph_entry = ftrace_graph_entry_stub; - ftrace_shutdown(&graph_ops, FTRACE_STOP_FUNC_RET); - unregister_pm_notifier(&ftrace_suspend_notifier); - unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); + for (i = 0; i < fgraph_array_cnt; i++) + if (gops == fgraph_array[i]) + break; + if (i >= fgraph_array_cnt) + goto out; + fgraph_array[i] = &fgraph_stub; + if (i + 1 == fgraph_array_cnt) { + for (; i >= 0; i--) + if (fgraph_array[i] != &fgraph_stub) + break; + fgraph_array_cnt = i + 1; + } + + ftrace_graph_active--; + if (!ftrace_graph_active) { + ftrace_graph_return = ftrace_stub_graph; + ftrace_graph_entry = ftrace_graph_entry_stub; + __ftrace_graph_entry = ftrace_graph_entry_stub; + ftrace_shutdown(&graph_ops, FTRACE_STOP_FUNC_RET); + unregister_pm_notifier(&ftrace_suspend_notifier); + unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); + } out: mutex_unlock(&ftrace_lock); } -- 2.43.0