From nobody Fri Dec 19 10:43:38 2025 Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6440126F2A1 for ; Mon, 13 Oct 2025 01:52:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760320342; cv=none; b=DZcPazp6QKiXVDq+SVsUv05WsYrkiDy4uKIDX2olhLdUtvt9JzfRS8snwtZuaQvUPfjPKw6u26rBUgQWFwkKl5qz3GeYG37CkE7j1Fak3vhW2kXRJFWHvvS9YUkVMC6BkIA5Hl0DNoaacnfSNBJIsEJyF0z2aWgDH3i4Ihy4nys= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760320342; c=relaxed/simple; bh=0ik3H27UNRE+ExKUAWRj/tEyb714XStPlG+VbKW6R0w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FSOxLucvAaI4VJVm89hItdaGrlt/Vwf++NmkJ3ShhxlqMe6fQBhoFLwJ0SPRkMXcH6Z1yKXM0qEe0saNJIEUFOkEPNvfNdfh/U+WPKTyv5Szknb/WFYNIQWRB9PIQZ/h47oeOA0dA2EPr+m/akeQxUFNxFbNAg46DO8bZwbVw0k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=cxhn/wxQ; arc=none smtp.client-ip=209.85.214.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cxhn/wxQ" Received: by mail-pl1-f196.google.com with SMTP id d9443c01a7336-27d3540a43fso34352845ad.3 for ; Sun, 12 Oct 2025 18:52:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760320338; x=1760925138; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Zj6tK1V/4VHMz9n6jIia523IIMIYEY9cFEmoYWPFnfU=; b=cxhn/wxQ47Cb3BNng1ohtkEsslInS16FmRoYw3d/WYXxpMJXV2u+TDVE//yFMaZlWq WrqfkIS5v/RWO2pF3NMU3nzZ9xkUuCko+fq1SSM+E65JyEcKv1TfjXZd5TvWNqZI1xNW 2dLF15Fmcj8tZUfTMXrRu4a9DmdICp8qnKZvr1DYExwy2RHGQVKEs2Vc3a0VMnKqN900 xUjnwx6E3NMNSCX2gcStELgZ77MWCjh+4MjSPK3TwTqzamVCjpGiuKtx0M2tIZwHdQXJ hAdQnU4wbpsv6gUI7AUVxu+/CKPdjzQsre+UDc5YXPW4oU0y9Y+t03p7nUVdAe5AjsIS r7PQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760320338; x=1760925138; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Zj6tK1V/4VHMz9n6jIia523IIMIYEY9cFEmoYWPFnfU=; b=WbObIU+42PVEfLeRFFYWlRfv2+NNQ9GECB1wAhkhPbpiOU2ewVS5AYc5KzowQc5Hcj 6T+HCTRlQ72H50H5MSuDXzD8kGatazZL6V1XGFQR51aVUVbYCPROzo+pKmUF4WZXhKxZ hO803VAHgLI9YG8o1CfR7p4rk63SOVCULpzB3FbXQXIECybE+drIIfTiNVVnqa5MoH1F 2p/cIVmVmoqdNr4ovOTB83vwSbXtiXCmbR9H3ozY8yYjkj6S1c5HcPHn/SBB+wfChqXw F9HIJNSX0sfRVz8uCdh5IjIle5bEWBIVnRns8Xri7KtMC1Co7Dq3EM1wVMfsNTxOPQPO Peug== X-Forwarded-Encrypted: i=1; AJvYcCVgGZox2fDDW67KaqT1tOS4oNI+P4s6A4RSlEL/WWdr4DBRxmee0TgUVZsm5UabMdelPnpR6iCsP9zENF4=@vger.kernel.org X-Gm-Message-State: AOJu0Yxkor6I+BvKjxi+J1jOIVjuje8SAj+OT/AEDFfY7OA3iFBKQOIi iImLSeTcaMptljlrLeXO941r+2+XLckLUjQtxQv21uJN4tcUlX2Wf8io X-Gm-Gg: ASbGncvnTwk4JLzu+w1epUr6k2ZWc23+XUacCqcyRpbo7JKahF531aWHaJwamM2XYW6 XF1So4hFWD39venNl0UYouA4zTYzSYEsWPJUhjnIf+WMEhmaNHvWix+wljyAAWxnRJ++z/fZwDW 99Hd287kpChY0YAQRF9r9xc3HuMdQl22CtXSxOiUuUia22DZTUY1LDkDwUube10TrjCRPa5obGx g5tIrFLiUiwWDWOGQj/dKgzwTKjxRV52MPeHD5uJJYNBLb0NsJwYnSWdunszZ3mMGK+6GBqZ4k6 QBaMJMoTJ6gV8VY/bKek7QrMVwaNzYofx2zTz3Fhcc1WUyp3BCYKUpq8GMB4E2xUPhbQZ/u70lc nYMnYJR2uDpJxwOIW7+HuCRB0RTxzoiVwpbmgtGF995r7GV1IdZSA X-Google-Smtp-Source: AGHT+IEkHuwtHGCVb3KQH7p/KEDNupgikQ1g8RqG2TQVMHAYFAyUOGsvqlTsC9cN+QSF4E2v5Or1yw== X-Received: by 2002:a17:903:1a03:b0:267:a1f1:9b23 with SMTP id d9443c01a7336-2902723ff44mr247637635ad.18.1760320338430; Sun, 12 Oct 2025 18:52:18 -0700 (PDT) Received: from 7950hx ([43.129.244.20]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29034deaa54sm117224925ad.5.2025.10.12.18.52.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 12 Oct 2025 18:52:18 -0700 (PDT) From: Menglong Dong X-Google-Original-From: Menglong Dong To: mhiramat@kernel.org Cc: rostedt@goodmis.org, mathieu.desnoyers@efficios.com, jiang.biao@linux.dev, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Subject: [PATCH v3 1/2] tracing: fprobe: optimization for entry only case Date: Mon, 13 Oct 2025 09:52:08 +0800 Message-ID: <20251013015209.30949-2-dongml2@chinatelecom.cn> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251013015209.30949-1-dongml2@chinatelecom.cn> References: <20251013015209.30949-1-dongml2@chinatelecom.cn> 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" Content-Transfer-Encoding: quoted-printable For now, fgraph is used for the fprobe, even if we need trace the entry only. However, the performance of ftrace is better than fgraph, and we can use ftrace_ops for this case. Then performance of kprobe-multi increases from 54M to 69M. Before this commit: $ ./benchs/run_bench_trigger.sh kprobe-multi kprobe-multi : 54.663 =C2=B1 0.493M/s After this commit: $ ./benchs/run_bench_trigger.sh kprobe-multi kprobe-multi : 69.447 =C2=B1 0.143M/s Mitigation is disable during the bench testing above. Signed-off-by: Menglong Dong --- v3: - add some comment to the rcu_read_lock() in fprobe_ftrace_entry() v2: - add some document for fprobe_fgraph_entry as Masami suggested - merge the rename of fprobe_entry into current patch - use ftrace_test_recursion_trylock() in fprobe_ftrace_entry() --- kernel/trace/fprobe.c | 109 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 98 insertions(+), 11 deletions(-) diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index 99d83c08b9e2..18319c22cec4 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -254,8 +254,9 @@ static inline int __fprobe_kprobe_handler(unsigned long= ip, unsigned long parent return ret; } =20 -static int fprobe_entry(struct ftrace_graph_ent *trace, struct fgraph_ops = *gops, - struct ftrace_regs *fregs) +/* fgraph_ops callback, this processes fprobes which have exit_handler. */ +static int fprobe_fgraph_entry(struct ftrace_graph_ent *trace, struct fgra= ph_ops *gops, + struct ftrace_regs *fregs) { unsigned long *fgraph_data =3D NULL; unsigned long func =3D trace->func; @@ -292,7 +293,7 @@ static int fprobe_entry(struct ftrace_graph_ent *trace,= struct fgraph_ops *gops, if (node->addr !=3D func) continue; fp =3D READ_ONCE(node->fp); - if (fp && !fprobe_disabled(fp)) + if (fp && !fprobe_disabled(fp) && fp->exit_handler) fp->nmissed++; } return 0; @@ -312,11 +313,11 @@ static int fprobe_entry(struct ftrace_graph_ent *trac= e, struct fgraph_ops *gops, if (node->addr !=3D func) continue; fp =3D READ_ONCE(node->fp); - if (!fp || fprobe_disabled(fp)) + if (unlikely(!fp || fprobe_disabled(fp) || !fp->exit_handler)) continue; =20 data_size =3D fp->entry_data_size; - if (data_size && fp->exit_handler) + if (data_size) data =3D fgraph_data + used + FPROBE_HEADER_SIZE_IN_LONG; else data =3D NULL; @@ -327,7 +328,7 @@ static int fprobe_entry(struct ftrace_graph_ent *trace,= struct fgraph_ops *gops, ret =3D __fprobe_handler(func, ret_ip, fp, fregs, data); =20 /* If entry_handler returns !0, nmissed is not counted but skips exit_ha= ndler. */ - if (!ret && fp->exit_handler) { + if (!ret) { int size_words =3D SIZE_IN_LONG(data_size); =20 if (write_fprobe_header(&fgraph_data[used], fp, size_words)) @@ -340,7 +341,7 @@ static int fprobe_entry(struct ftrace_graph_ent *trace,= struct fgraph_ops *gops, /* If any exit_handler is set, data must be used. */ return used !=3D 0; } -NOKPROBE_SYMBOL(fprobe_entry); +NOKPROBE_SYMBOL(fprobe_fgraph_entry); =20 static void fprobe_return(struct ftrace_graph_ret *trace, struct fgraph_ops *gops, @@ -379,11 +380,87 @@ static void fprobe_return(struct ftrace_graph_ret *tr= ace, NOKPROBE_SYMBOL(fprobe_return); =20 static struct fgraph_ops fprobe_graph_ops =3D { - .entryfunc =3D fprobe_entry, + .entryfunc =3D fprobe_fgraph_entry, .retfunc =3D fprobe_return, }; static int fprobe_graph_active; =20 +/* ftrace_ops callback, this processes fprobes which have only entry_handl= er. */ +static void fprobe_ftrace_entry(unsigned long ip, unsigned long parent_ip, + struct ftrace_ops *ops, struct ftrace_regs *fregs) +{ + struct fprobe_hlist_node *node; + struct rhlist_head *head, *pos; + struct fprobe *fp; + int bit; + + bit =3D ftrace_test_recursion_trylock(ip, parent_ip); + if (bit < 0) + return; + + /* + * ftrace_test_recursion_trylock() disables preemption, but + * rhltable_lookup() checks whether rcu_read_lcok is held. + * So we take rcu_read_lock() here. + */ + rcu_read_lock(); + head =3D rhltable_lookup(&fprobe_ip_table, &ip, fprobe_rht_params); + + rhl_for_each_entry_rcu(node, pos, head, hlist) { + if (node->addr !=3D ip) + break; + fp =3D READ_ONCE(node->fp); + if (unlikely(!fp || fprobe_disabled(fp) || fp->exit_handler)) + continue; + + if (fprobe_shared_with_kprobes(fp)) + __fprobe_kprobe_handler(ip, parent_ip, fp, fregs, NULL); + else + __fprobe_handler(ip, parent_ip, fp, fregs, NULL); + } + rcu_read_unlock(); + ftrace_test_recursion_unlock(bit); +} +NOKPROBE_SYMBOL(fprobe_ftrace_entry); + +static struct ftrace_ops fprobe_ftrace_ops =3D { + .func =3D fprobe_ftrace_entry, + .flags =3D FTRACE_OPS_FL_SAVE_REGS, +}; +static int fprobe_ftrace_active; + +static int fprobe_ftrace_add_ips(unsigned long *addrs, int num) +{ + int ret; + + lockdep_assert_held(&fprobe_mutex); + + ret =3D ftrace_set_filter_ips(&fprobe_ftrace_ops, addrs, num, 0, 0); + if (ret) + return ret; + + if (!fprobe_ftrace_active) { + ret =3D register_ftrace_function(&fprobe_ftrace_ops); + if (ret) { + ftrace_free_filter(&fprobe_ftrace_ops); + return ret; + } + } + fprobe_ftrace_active++; + return 0; +} + +static void fprobe_ftrace_remove_ips(unsigned long *addrs, int num) +{ + lockdep_assert_held(&fprobe_mutex); + + fprobe_ftrace_active--; + if (!fprobe_ftrace_active) + unregister_ftrace_function(&fprobe_ftrace_ops); + if (num) + ftrace_set_filter_ips(&fprobe_ftrace_ops, addrs, num, 1, 0); +} + /* Add @addrs to the ftrace filter and register fgraph if needed. */ static int fprobe_graph_add_ips(unsigned long *addrs, int num) { @@ -498,9 +575,12 @@ static int fprobe_module_callback(struct notifier_bloc= k *nb, } while (node =3D=3D ERR_PTR(-EAGAIN)); rhashtable_walk_exit(&iter); =20 - if (alist.index > 0) + if (alist.index > 0) { ftrace_set_filter_ips(&fprobe_graph_ops.ops, alist.addrs, alist.index, 1, 0); + ftrace_set_filter_ips(&fprobe_ftrace_ops, + alist.addrs, alist.index, 1, 0); + } mutex_unlock(&fprobe_mutex); =20 kfree(alist.addrs); @@ -733,7 +813,11 @@ int register_fprobe_ips(struct fprobe *fp, unsigned lo= ng *addrs, int num) mutex_lock(&fprobe_mutex); =20 hlist_array =3D fp->hlist_array; - ret =3D fprobe_graph_add_ips(addrs, num); + if (fp->exit_handler) + ret =3D fprobe_graph_add_ips(addrs, num); + else + ret =3D fprobe_ftrace_add_ips(addrs, num); + if (!ret) { add_fprobe_hash(fp); for (i =3D 0; i < hlist_array->size; i++) { @@ -829,7 +913,10 @@ int unregister_fprobe(struct fprobe *fp) } del_fprobe_hash(fp); =20 - fprobe_graph_remove_ips(addrs, count); + if (fp->exit_handler) + fprobe_graph_remove_ips(addrs, count); + else + fprobe_ftrace_remove_ips(addrs, count); =20 kfree_rcu(hlist_array, rcu); fp->hlist_array =3D NULL; --=20 2.51.0 From nobody Fri Dec 19 10:43:38 2025 Received: from mail-pl1-f195.google.com (mail-pl1-f195.google.com [209.85.214.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BFF1F274643 for ; Mon, 13 Oct 2025 01:52:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760320344; cv=none; b=TOAjgCfOAPQ6yZouvEGWMCSjUqZlZi4J0Nwq7w4Snxj5Sfjv2fNd7xZzvyUbXZORzRRgm5bq0KI6N6BBS33OiWyadDjuta3bbHtsbsYytgFu7Kl36A+FnT4XsDDz0Ky137aNbSjIK9Uq/8ZgcO+EbWs4+8CUl7H1RL9pP7xfcac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760320344; c=relaxed/simple; bh=KXynVc/l4z0I/0afxLQ1qgxkhnxUen6TcUANd7bwj6s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dkio4NXfT6CntixHrPMvhBAok8k7/MH37I57nDnl9ssQj4zK4WGC+cDjfJqFAqYS4LBWvDiUIgJUw8vpnvRN4Hwrgkhvpb3YIGVIOiirn9eQJx/8iY2ozcXCV2m4FaxEb5IWk9eT/frzhw7q1MmbdH0qSeke26/qN0md9LR1+UQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WNfIEyxo; arc=none smtp.client-ip=209.85.214.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WNfIEyxo" Received: by mail-pl1-f195.google.com with SMTP id d9443c01a7336-27ee41e0798so60179985ad.1 for ; Sun, 12 Oct 2025 18:52:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1760320341; x=1760925141; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aBZqKJ/asg/RWAeGZDfmIrxp30oaYR/dgJdIlWzmC0w=; b=WNfIEyxoTVjddxmDF1nJhO6yQBze65YXAKa1DvD+wUVKLocTNvYRyURkb5OOOW0rW/ MkfF1OqN1KAdgrRZH5VlbwKjxdR8mNugH/UMZ2Z3BesKMzqYAlE7Yau2Mub8VMnJklKH M15C31YoEmKFDlzn2WaioAcJI240RY0oLRrI+/eJ3s+GkcdAgXzUX1W1dKtEBsyQjmjg jXInxY1rxNzOZbpbm1B9adg/m89kh2Gk0lU9VRWVvStNosRPqKF6VCjv3cKOCToThnaV TQNxOmwggW/Hm67nrvhIDXjy9tahEhCyB/XVpV9uUQofvF1b35qkXiwiuHKX/op7ktdj 3N+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760320341; x=1760925141; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aBZqKJ/asg/RWAeGZDfmIrxp30oaYR/dgJdIlWzmC0w=; b=ANLlrW1HpAjGAvtZZh4Yj9b/Lb0ZRMkkdwgPbQEyiZxtb5TeIOBxgRNEM+gGt9HHlj nIJcrbwkHMA8pjVmpiUUytD94tu60fDQnmlpuno0qRNAOgPLZvUcNgYuH7LfyR0iCLkW 44KoZgQpFkkUT9YloCcMdl/D49FzBp6lhD9t0wTiNLuY/XO5iqgE4/MGkN0yvrNkuzCH 1Ghdo//IM0sUwwwMK52f0TbrdkW/GOuSUuQZrhe7rFyM1zTQIhemHY6cQ17Qq3d1HiVc eIsUvPkS6Nl34N5gpYm7XW/od7RK65Yco1soxV6DnlzoW0+wrH8Xm4V+E3Fxw92pgH6x i5BQ== X-Forwarded-Encrypted: i=1; AJvYcCUwlwadUIg1v98Oa28HooQVYqxlw6JrMCJOGejciTbM6xW2SnV1HNv5wqMrMnSfyhzS7jLAGqG7CihHtsw=@vger.kernel.org X-Gm-Message-State: AOJu0YzL5vGRryvOFZ3Rj/TOPsxzSohXdAbEXW0GPgyTHqEHrF+XrvNn m65Wryk9lrPQhAoT9VcRx58QVu1aFTWOnDhBiIKPOP0Ffg26+OGUK/LT X-Gm-Gg: ASbGncuxllvbVyhPJAxib7C05BBRjTXlHQ05zzgTs8DHcoymXOFCUUjfE5N6uwkyw0t D+CTr7uueNALHnmj5UtYkJpVdQRxncKUJ4K9S+lUDHnKIfL6JSJK3WetaOCawlqr4uddtlnrsNI LmmzzFUjk9RUzmRLmjuisrcAO8qEf6PVSP0tw1yuZLPUsQCgfueh+nwFKm8tOvMyHozweXU9sgM Mta8YnZQj5lsnmUxbFOskKXM7b2C8ttBrn3t9cNQnrsXzbNsKI3INyXaH2YsmpM6PK2XeiP4/C3 Y4aiHeQDJeCKiAR3N/YTPwfZ005gQgjzmBRjeFK2azyHbB6+tyT6WS+w0pYy3AOARDQxXWqi9Ws xJIMDpyIUzUnbit5aynTtpkOEWZ6gmIVL3QHt/GXDHA== X-Google-Smtp-Source: AGHT+IG0OBHQAlbS9opbTzuG1IHDgaFt3docgqywj3nlM2f/kPmiwXzx6GvTMtpNFzMpjE2za6EI/g== X-Received: by 2002:a17:903:1b2e:b0:27b:472e:3a22 with SMTP id d9443c01a7336-2902741cd22mr257155465ad.56.1760320340728; Sun, 12 Oct 2025 18:52:20 -0700 (PDT) Received: from 7950hx ([43.129.244.20]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29034deaa54sm117224925ad.5.2025.10.12.18.52.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 12 Oct 2025 18:52:20 -0700 (PDT) From: Menglong Dong X-Google-Original-From: Menglong Dong To: mhiramat@kernel.org Cc: rostedt@goodmis.org, mathieu.desnoyers@efficios.com, jiang.biao@linux.dev, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org Subject: [PATCH v3 2/2] lib/test_fprobe: add testcase for mixed fprobe Date: Mon, 13 Oct 2025 09:52:09 +0800 Message-ID: <20251013015209.30949-3-dongml2@chinatelecom.cn> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20251013015209.30949-1-dongml2@chinatelecom.cn> References: <20251013015209.30949-1-dongml2@chinatelecom.cn> 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" Add the testcase for the fprobe, which will hook the same target with two fprobe: entry, entry+exit. And the two fprobes will be registered with different order. fgraph and ftrace are both used for the fprobe, and this testcase is for the mixed situation. Signed-off-by: Menglong Dong --- lib/tests/test_fprobe.c | 99 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/lib/tests/test_fprobe.c b/lib/tests/test_fprobe.c index cf92111b5c79..108c7aa33cb4 100644 --- a/lib/tests/test_fprobe.c +++ b/lib/tests/test_fprobe.c @@ -12,7 +12,8 @@ =20 static struct kunit *current_test; =20 -static u32 rand1, entry_val, exit_val; +static u32 rand1, entry_only_val, entry_val, exit_val; +static u32 entry_only_count, entry_count, exit_count; =20 /* Use indirect calls to avoid inlining the target functions */ static u32 (*target)(u32 value); @@ -190,6 +191,101 @@ static void test_fprobe_skip(struct kunit *test) KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp)); } =20 +/* Handler for fprobe entry only case */ +static notrace int entry_only_handler(struct fprobe *fp, unsigned long ip, + unsigned long ret_ip, + struct ftrace_regs *fregs, void *data) +{ + KUNIT_EXPECT_FALSE(current_test, preemptible()); + KUNIT_EXPECT_EQ(current_test, ip, target_ip); + + entry_only_count++; + entry_only_val =3D (rand1 / div_factor); + + return 0; +} + +static notrace int fprobe_entry_multi_handler(struct fprobe *fp, unsigned = long ip, + unsigned long ret_ip, + struct ftrace_regs *fregs, + void *data) +{ + KUNIT_EXPECT_FALSE(current_test, preemptible()); + KUNIT_EXPECT_EQ(current_test, ip, target_ip); + + entry_count++; + entry_val =3D (rand1 / div_factor); + + return 0; +} + +static notrace void fprobe_exit_multi_handler(struct fprobe *fp, unsigned = long ip, + unsigned long ret_ip, + struct ftrace_regs *fregs, + void *data) +{ + unsigned long ret =3D ftrace_regs_get_return_value(fregs); + + KUNIT_EXPECT_FALSE(current_test, preemptible()); + KUNIT_EXPECT_EQ(current_test, ip, target_ip); + KUNIT_EXPECT_EQ(current_test, ret, (rand1 / div_factor)); + + exit_count++; + exit_val =3D ret; +} + +static void check_fprobe_multi(struct kunit *test) +{ + entry_only_count =3D entry_count =3D exit_count =3D 0; + entry_only_val =3D entry_val =3D exit_val =3D 0; + + target(rand1); + + /* Verify all handlers were called */ + KUNIT_EXPECT_EQ(test, 1, entry_only_count); + KUNIT_EXPECT_EQ(test, 1, entry_count); + KUNIT_EXPECT_EQ(test, 1, exit_count); + + /* Verify values are correct */ + KUNIT_EXPECT_EQ(test, (rand1 / div_factor), entry_only_val); + KUNIT_EXPECT_EQ(test, (rand1 / div_factor), entry_val); + KUNIT_EXPECT_EQ(test, (rand1 / div_factor), exit_val); +} + +/* Test multiple fprobes hooking the same target function */ +static void test_fprobe_multi(struct kunit *test) +{ + struct fprobe fp1 =3D { + .entry_handler =3D fprobe_entry_multi_handler, + .exit_handler =3D fprobe_exit_multi_handler, + }; + struct fprobe fp2 =3D { + .entry_handler =3D entry_only_handler, + }; + + current_test =3D test; + + /* Test Case 1: Register in order 1 -> 2 */ + KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp1, "fprobe_selftest_target", = NULL)); + KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp2, "fprobe_selftest_target", = NULL)); + + check_fprobe_multi(test); + + /* Unregister all */ + KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp1)); + KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp2)); + + /* Test Case 2: Register in order 2 -> 1 */ + KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp2, "fprobe_selftest_target", = NULL)); + KUNIT_EXPECT_EQ(test, 0, register_fprobe(&fp1, "fprobe_selftest_target", = NULL)); + + check_fprobe_multi(test); + + /* Unregister all */ + KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp1)); + KUNIT_EXPECT_EQ(test, 0, unregister_fprobe(&fp2)); +} + static unsigned long get_ftrace_location(void *func) { unsigned long size, addr =3D (unsigned long)func; @@ -217,6 +313,7 @@ static struct kunit_case fprobe_testcases[] =3D { KUNIT_CASE(test_fprobe_syms), KUNIT_CASE(test_fprobe_data), KUNIT_CASE(test_fprobe_skip), + KUNIT_CASE(test_fprobe_multi), {} }; =20 --=20 2.51.0