All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ian Rogers" <irogers@google.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v6 06/11] perf bpf-filter: Extend lock_held() to other kernel lock types
Date: Thu, 22 Oct 2026 20:55:09 +0000	[thread overview]
Message-ID: <sashiko-outbox-182029@kernel.org> (raw)
In-Reply-To: <20261022203003.1779152-7-irogers@google.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] perf bpf-filter: prescan_one_lock_expr() misses percpu_rw_semaphore symbols
- [Medium] perf bpf-filter: '*_sem' rw_semaphore and percpu_rw_semaphore symbols misclassified as counting semaphores
--

commit 088eb8ec579be2bc3ffee09560153843b89f7a25
Author: Ian Rogers <irogers@google.com>

perf bpf-filter: Extend lock_held() to other kernel lock types

This commit extends the lock_held() BPF sample filter to support additional
kernel lock types, lock type flags, and hexadecimal lock addresses. It uses
direct owner inspection where possible and attaches fentry/fexit BPF hooks
to track lock acquisitions and releases in an LRU hash map otherwise.

> diff --git a/tools/perf/util/bpf-filter.c b/tools/perf/util/bpf-filter.c
> index 639db6c031379..8797f67698f7d 100644
> --- a/tools/perf/util/bpf-filter.c
> +++ b/tools/perf/util/bpf-filter.c
[ ... ]
> @@ -301,26 +517,225 @@ static int find_kernel_lock_sym(const char *name, u64 *addr)
[ ... ]
>  static void prescan_one_lock_expr(struct perf_bpf_filter_expr *expr,
> -				  bool *has_lock_filter)
> +				  bool *has_lock_filter,
> +				  unsigned int *prog_groups,
> +				  unsigned int *required_groups)
>  {
> +	char base[128];
> +	bool has_amp;
> +	unsigned int mode, groups = 0;
> +	u64 dummy;
> +
>  	if (expr->term != PBF_TERM_LOCK_HELD || !expr->lock_name)
>  		return;
>  
>  	*has_lock_filter = true;
> +	if (split_lock_name_mode(expr->lock_name, expr->part, base,
> +				 sizeof(base), &has_amp, &mode) < 0 || has_amp)
> +		return;
> +
> +	if (parse_lock_type_name(base, mode, NULL, NULL, &groups)) {
> +		*prog_groups |= groups;
> +		*required_groups |= groups;
> +		return;
> +	}
> +
> +	if (parse_lock_hex_addr(base, &dummy)) {
> +		*prog_groups |= LOCK_PROG_ALL;
> +		return;
> +	}
> +
> +	if (str_ends_with(base, "rt_mutex") || str_ends_with(base, "rtmutex") ||
> +	    str_ends_with(base, "mutex")) {
> +		/* Inspected directly via lock->owner; no tracing hooks needed. */
> +		return;
> +	} else if (str_ends_with(base, "percpu_rwsem") ||
> +		   str_ends_with(base, "pcpu_rwsem")) {
> +		*prog_groups |= LOCK_PROG_PERCPU_RWSEM;
> +		*required_groups |= LOCK_PROG_PERCPU_RWSEM;
> +	} else if (str_ends_with(base, "rwsem")) {
> +		if (mode & PBF_LOCK_MODE_READ) {
> +			*prog_groups |= LOCK_PROG_RWSEM_READ;
> +			*required_groups |= LOCK_PROG_RWSEM_READ;
> +		}
> +		if (mode & PBF_LOCK_MODE_WRITE) {
> +			*prog_groups |= LOCK_PROG_RWSEM_WRITE | LOCK_PROG_PERCPU_RWSEM;
> +			*required_groups |= LOCK_PROG_RWSEM_WRITE;
> +		}
> +	} else if (str_ends_with(base, "spinlock")) {
> +		*prog_groups |= LOCK_PROG_SPIN;
> +		*required_groups |= LOCK_PROG_SPIN;
> +	} else if (str_ends_with(base, "sem")) {
> +		*prog_groups |= LOCK_PROG_SEM;
> +		*required_groups |= LOCK_PROG_SEM;
> +	} else if (str_ends_with(base, "rwlock")) {
> +		if (mode & PBF_LOCK_MODE_READ)
> +			groups |= LOCK_PROG_RWLOCK_READ;
> +		if (mode & PBF_LOCK_MODE_WRITE)
> +			groups |= LOCK_PROG_RWLOCK_WRITE;
> +		*prog_groups |= groups;
> +		*required_groups |= groups;
> +	} else {
> +		*prog_groups |= LOCK_PROG_ALL;
> +	}
>  }

[Severity: Medium]
In perf_bpf_filter__prepare(), prescan_lock_filters() calls
prescan_one_lock_expr() before btf__load_vmlinux_btf() is called:

perf_bpf_filter__prepare()
  prescan_lock_filters()
    prescan_one_lock_expr()
  ...
  btf = btf__load_vmlinux_btf();
  configure_lock_progs(skel, btf, prog_groups, required_groups, ...);
  sample_filter_bpf__load(skel);
  get_filter_entries(evsel, skel, btf, entry)
    resolve_lock_expr(skel, btf, ...)
      is_percpu_rwsem_sym(btf, base)

Because prescan_one_lock_expr() only checks whether base ends with
"percpu_rwsem" or "pcpu_rwsem" without calling is_percpu_rwsem_sym(),
won't percpu_rw_semaphore symbols with other suffixes be misclassified
during prescan?

For example, when filtering on dup_mmap_sem or bp_cpuinfo_sem,
prescan_one_lock_expr() matches str_ends_with(base, "sem") and only sets
LOCK_PROG_SEM. Then configure_lock_progs() disables autoload for
fexit_percpu_down_write and fentry_percpu_up_write before the skeleton is
loaded. When resolve_lock_expr() later runs and identifies the symbol via
is_percpu_rwsem_sym(btf, base), the LOCK_PROG_PERCPU_RWSEM programs were
never loaded or attached.

Similarly, for percpu_rw_semaphore symbols ending in "_rwsem" (such as
cgroup_threadgroup_rwsem) or "_lock" (such as cpu_hotplug_lock and
mem_hotplug_lock), wouldn't prescan_one_lock_expr() enable unnecessary
LOCK_PROG_RWSEM or LOCK_PROG_ALL hooks across other lock families?

> @@ -390,14 +805,42 @@ static int normalize_lock_expr_op(const struct perf_bpf_filter_expr *expr,
>  	return -EINVAL;
>  }
>  
> -static int resolve_lock_expr(struct perf_bpf_filter_expr *expr,
> +static bool is_percpu_rwsem_sym(struct btf *btf, const char *name)
> +{
> +	char rc_name[160];
> +
> +	if (str_ends_with(name, "percpu_rwsem") ||
> +	    str_ends_with(name, "pcpu_rwsem"))
> +		return true;
> +
> +	if (!btf)
> +		return false;
> +
> +	snprintf(rc_name, sizeof(rc_name), "__percpu_rwsem_rc_%s", name);
> +	return btf__find_by_name_kind(btf, rc_name, BTF_KIND_VAR) > 0;
> +}
[ ... ]
> @@ -410,29 +853,79 @@ static int resolve_lock_expr(struct perf_bpf_filter_expr *expr,
[ ... ]
> +	ret = find_kernel_lock_sym(base, &addr);
> +	if (ret == 0) {
> +		unsigned int direct_flag = 0;
> +		bool is_pcpu_rwsem = is_percpu_rwsem_sym(btf, base);
> +
> +		if (str_ends_with(base, "rt_mutex") || str_ends_with(base, "rtmutex"))
> +			direct_flag = PBF_LOCK_DIRECT_RTMUTEX;
> +		else if (str_ends_with(base, "mutex"))
> +			direct_flag = PBF_LOCK_DIRECT_MUTEX;
> +		else if (str_ends_with(base, "rwsem") && !is_pcpu_rwsem)
> +			direct_flag = PBF_LOCK_DIRECT_RWSEM;
> +
> +		if ((direct_flag == PBF_LOCK_DIRECT_MUTEX ||
> +		     direct_flag == PBF_LOCK_DIRECT_RTMUTEX ||
> +		     is_pcpu_rwsem ||
> +		     str_ends_with(base, "spinlock") ||
> +		     (str_ends_with(base, "sem") &&
> +		      !str_ends_with(base, "rwsem"))) &&
> +		    !(mode & PBF_LOCK_MODE_WRITE)) {
> +			pr_err("Error: Lock '%s' is exclusive and does not support read/shared mode\n",
> +			       name);
> +			return -EINVAL;
> +		}

[Severity: Medium]
How are global or static rw_semaphore locks whose names end in "_sem"
(such as namespace_sem, uts_sem, pci_bus_sem, or dev_addr_sem, defined
with DECLARE_RWSEM) handled here and in prescan_one_lock_expr()?

Because both functions classify any symbol ending in "sem" (and not
"rwsem") as a counting semaphore:

1. In resolve_lock_expr(), read-mode filters such as
   lock_held_read(namespace_sem) or lock_held(uts_sem:R) hit the
   str_ends_with(base, "sem") && !str_ends_with(base, "rwsem") check
   when !(mode & PBF_LOCK_MODE_WRITE) and are rejected with -EINVAL.

2. For write-mode or any-mode filters such as lock_held(namespace_sem)
   or lock_held_write(uts_sem), prescan_one_lock_expr() only enables
   LOCK_PROG_SEM (down/up) and resolve_lock_expr() leaves direct_flag as 0,
   so neither PBF_LOCK_DIRECT_RWSEM nor the down_read/down_write hooks are
   used.

Could BTF type inspection on the symbol (or checking whether the BTF var
type is struct rw_semaphore vs struct semaphore) be used to distinguish
rw_semaphore symbols ending in "_sem" from counting semaphores?

> +
> +		entry->part = PBF_LOCK_ADDR | mode | direct_flag;
> +		entry->value = addr;
[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261022203003.1779152-1-irogers@google.com?part=6

  reply	other threads:[~2026-10-22 20:55 UTC|newest]

Thread overview: 106+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-17  5:45 [PATCH v1 0/5] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Ian Rogers
2026-10-17  5:45 ` [PATCH v1 1/5] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-17  5:52   ` sashiko-bot
2026-10-17  5:45 ` [PATCH v1 2/5] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-17  6:09   ` sashiko-bot
2026-10-17  5:45 ` [PATCH v1 3/5] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-17  5:49   ` sashiko-bot
2026-10-17  5:45 ` [PATCH v1 4/5] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-17  5:56   ` sashiko-bot
2026-10-17  5:45 ` [PATCH v1 5/5] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-17  6:08   ` sashiko-bot
2026-10-17 17:14 ` [PATCH v2 0/6] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Ian Rogers
2026-10-17 17:14   ` [PATCH v2 1/6] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-17 17:31     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 2/6] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-17 17:35     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 3/6] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-17 17:17     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 4/6] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-17 17:25     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 5/6] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-17 17:30     ` sashiko-bot
2026-10-17 17:14   ` [PATCH v2 6/6] perf lock contention: Filter events before creating lock_stat Ian Rogers
2026-10-17 17:17     ` sashiko-bot
2026-10-18  5:37   ` [PATCH v3 0/6] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Ian Rogers
2026-10-18  5:37     ` [PATCH v3 1/6] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-18  5:50       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 2/6] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-18  6:12       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 3/6] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-18  5:41       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 4/6] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-18  5:51       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 5/6] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-18  5:48       ` sashiko-bot
2026-10-18  5:37     ` [PATCH v3 6/6] perf lock contention: Filter events before creating lock_stat Ian Rogers
2026-10-18  5:40       ` sashiko-bot
2026-10-19  7:00     ` [PATCH v3 0/6] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Namhyung Kim
2026-10-19 19:08       ` Ian Rogers
2026-10-19 22:09     ` [PATCH v4 0/7] " Ian Rogers
2026-10-19 22:09       ` [PATCH v4 1/7] perf lock contention: Filter events before creating lock_stat Ian Rogers
2026-10-19 22:14         ` sashiko-bot
2026-10-20  4:34         ` Namhyung Kim
2026-10-21 21:39           ` Arnaldo Carvalho de Melo
2026-10-19 22:09       ` [PATCH v4 2/7] perf bpf-filter: Support BPF sample filters on tracepoint events Ian Rogers
2026-10-19 22:26         ` sashiko-bot
2026-10-20  5:41         ` Namhyung Kim
2026-10-20 15:30           ` Ian Rogers
2026-10-20 22:29             ` Namhyung Kim
2026-10-19 22:09       ` [PATCH v4 3/7] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-19 22:17         ` sashiko-bot
2026-10-19 22:09       ` [PATCH v4 4/7] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-19 22:28         ` sashiko-bot
2026-10-19 22:09       ` [PATCH v4 5/7] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-19 22:12         ` sashiko-bot
2026-10-19 22:09       ` [PATCH v4 6/7] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-19 22:19         ` sashiko-bot
2026-10-19 22:09       ` [PATCH v4 7/7] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-19 22:19         ` sashiko-bot
2026-10-20 20:58       ` [PATCH v5 0/8] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Ian Rogers
2026-10-20 20:58         ` [PATCH v5 1/8] perf lock contention: Filter events before creating lock_stat Ian Rogers
2026-10-20 22:38           ` sashiko-bot
2026-10-20 20:58         ` [PATCH v5 2/8] perf bpf-filter: Fix bpf_link leak by using PERF_EVENT_IOC_SET_BPF Ian Rogers
2026-10-20 22:41           ` sashiko-bot
2026-10-20 20:58         ` [PATCH v5 3/8] perf bpf-filter: Support BPF sample filters on tracepoint events Ian Rogers
2026-10-20 22:57           ` sashiko-bot
2026-10-20 20:58         ` [PATCH v5 4/8] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-20 22:42           ` Namhyung Kim
2026-10-20 23:02           ` sashiko-bot
2026-10-20 20:58         ` [PATCH v5 5/8] perf bpf-filter: Add lock_held() sample filter Ian Rogers
2026-10-20 22:49           ` Namhyung Kim
2026-10-20 23:17           ` sashiko-bot
2026-10-20 20:58         ` [PATCH v5 6/8] perf test: Add tests for lock_held() BPF " Ian Rogers
2026-10-20 23:20           ` sashiko-bot
2026-10-20 20:58         ` [PATCH v5 7/8] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-20 23:29           ` sashiko-bot
2026-10-20 20:58         ` [PATCH v5 8/8] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-20 23:37           ` sashiko-bot
2026-10-22 20:29         ` [PATCH v6 00/11] perf bpf-filter / lock contention: Add lock_held() sample filter and RCU/SRCU support Ian Rogers
2026-10-22 20:29           ` [PATCH v6 01/11] perf bpf-filter: Fix bpf_link leak by using PERF_EVENT_IOC_SET_BPF Ian Rogers
2026-10-22 20:35             ` sashiko-bot
2026-10-22 22:06             ` Namhyung Kim
2026-10-22 20:29           ` [PATCH v6 02/11] perf bpf-filter: Support BPF sample filters on tracepoint events Ian Rogers
2026-10-22 20:55             ` sashiko-bot
2026-10-22 20:29           ` [PATCH v6 03/11] perf lock contention: Share common BPF and lock type definitions in lock_data.h Ian Rogers
2026-10-22 20:36             ` sashiko-bot
2026-10-22 20:29           ` [PATCH v6 04/11] perf lock contention: Extend get_lock_owner() for rt_mutex and mutex handoff Ian Rogers
2026-10-22 20:41             ` sashiko-bot
2026-10-22 20:29           ` [PATCH v6 05/11] perf bpf-filter: Add lock_held() sample filter for global mutexes Ian Rogers
2026-10-22 20:46             ` sashiko-bot
2026-10-22 22:55             ` Namhyung Kim
2026-10-23  5:16               ` Ian Rogers
2026-10-22 20:29           ` [PATCH v6 06/11] perf bpf-filter: Extend lock_held() to other kernel lock types Ian Rogers
2026-10-22 20:55             ` sashiko-bot [this message]
2026-10-22 22:56             ` Namhyung Kim
2026-10-23  5:19               ` Ian Rogers
2026-10-22 20:29           ` [PATCH v6 07/11] perf bpf-filter: Support per-process and semi-global locks in lock_held() Ian Rogers
2026-10-22 20:49             ` sashiko-bot
2026-10-22 20:30           ` [PATCH v6 08/11] perf bpf-filter: Support slab cache locks (&<name>) " Ian Rogers
2026-10-22 20:37             ` sashiko-bot
2026-10-22 20:30           ` [PATCH v6 09/11] perf test: Add tests for lock_held() BPF sample filter Ian Rogers
2026-10-22 20:37             ` sashiko-bot
2026-10-22 20:30           ` [PATCH v6 10/11] perf bpf-filter: Extend lock_held() to support RCU, Tasks Trace RCU, and SRCU Ian Rogers
2026-10-22 20:44             ` sashiko-bot
2026-10-22 20:30           ` [PATCH v6 11/11] perf lock contention: Extend BPF lock contention to RCU " Ian Rogers
2026-10-22 20:43             ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-182029@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=irogers@google.com \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.