Re: [PATCH v3 9/9] selftests/verification: add tlob selftests

From: Gabriele Monaco

Date: Mon Jun 22 2026 - 05:28:07 EST


On Mon, 2026-06-08 at 00:13 +0800, wen.yang@xxxxxxxxx wrote:
> From: Wen Yang <wen.yang@xxxxxxxxx>
>
> +grep -qE "^p ${UPROBE_TARGET}:0x[0-9a-f]+ 0x[0-9a-f]+ threshold=[0-
> 9]+$" "$TLOB_MONITOR"
> +grep -q "threshold=5000000000" "$TLOB_MONITOR"
> +
> +! echo "p ${UPROBE_TARGET}:${busy_offset} ${stop_offset}
> threshold=9999000" > "$TLOB_MONITOR" 2>/dev/null
> +
> +echo "-${UPROBE_TARGET}:${busy_offset}" > "$TLOB_MONITOR"
> +! grep -q "^p .*:0x${busy_offset#0x} " "$TLOB_MONITOR"
...
> +! grep -q "error_env_tlob" /sys/kernel/tracing/trace

There is a widespread misconception under selftests that ! cmd with set -e
fails if the command succeeds, so you can use it to expect a program failure.

That isn't the case though [1], errexit (what set -e does), skips commands starting
with ! where the result isn't checked.
Essentially if you want to say exit if the command succeeds, you can do:

cmd && exit 1 # explicit
! cmd || exit 1 # explicit

or still exploiting errexit

cmd && false
! cmd || false

I'm going to fix it in existing selftests using the last variant, but keep
this in mind in your selftests as well. (Variants with ! are preferred because
they also return 0 if cmd fails, as you'd expect, I personally prefer to use
false instead of explicit exit, but that's up to you).

Thanks,
Gabriele

[1] - https://www.shellcheck.net/wiki/SC2251

> +echo 0 > monitors/tlob/enable
> +echo 0 > /sys/kernel/tracing/events/rv/error_env_tlob/enable
> +echo > /sys/kernel/tracing/trace
> diff --git
> a/tools/testing/selftests/verification/test.d/tlob/uprobe_violation.t
> c
> b/tools/testing/selftests/verification/test.d/tlob/uprobe_violation.t
> c
> new file mode 100644
> index 000000000000..d210d9c3a92d
> --- /dev/null
> +++
> b/tools/testing/selftests/verification/test.d/tlob/uprobe_violation.t
> c
> @@ -0,0 +1,67 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# description: Test tlob monitor budget violation (error_env_tlob
> and detail_env_tlob fire with correct fields)
> +# requires: tlob:monitor
> +
> +RV_BINDIR="${RV_BINDIR:-$(realpath "$(dirname "${1:-$0}")")}"
> +UPROBE_TARGET="${RV_BINDIR}/tlob_target"
> +TLOB_SYM="${RV_BINDIR}/tlob_sym"
> +[ -x "$UPROBE_TARGET" ] || exit_unsupported
> +[ -x "$TLOB_SYM" ]      || exit_unsupported
> +TLOB_MONITOR=monitors/tlob/monitor
> +
> +busy_offset=$("$TLOB_SYM" sym_offset "$UPROBE_TARGET" tlob_busy_work
> 2>/dev/null)
> +stop_offset=$("$TLOB_SYM" sym_offset "$UPROBE_TARGET"
> tlob_busy_work_done 2>/dev/null)
> +[ -n "$busy_offset" ] || exit_unsupported
> +[ -n "$stop_offset" ] || exit_unsupported
> +
> +"$UPROBE_TARGET" 30000 &
> +busy_pid=$!
> +sleep 0.05
> +
> +echo 1 > /sys/kernel/tracing/events/rv/error_env_tlob/enable
> +echo 1 > /sys/kernel/tracing/events/rv/detail_env_tlob/enable
> +echo 1 > /sys/kernel/tracing/tracing_on
> +echo 1 > monitors/tlob/enable
> +echo > /sys/kernel/tracing/trace
> +
> +# 10 µs budget - fires almost immediately; task is busy-spinning on-
> CPU.
> +echo "p ${UPROBE_TARGET}:${busy_offset} ${stop_offset}
> threshold=10000" > "$TLOB_MONITOR"
> +
> +# wait up to 2 s for detail_env_tlob
> +found=0; i=0
> +while [ "$i" -lt 20 ]; do
> + sleep 0.1
> + grep -q "detail_env_tlob" /sys/kernel/tracing/trace && {
> found=1; break; }
> + i=$((i+1))
> +done
> +
> +echo "-${UPROBE_TARGET}:${busy_offset}" > "$TLOB_MONITOR"
> 2>/dev/null
> +kill "$busy_pid" 2>/dev/null || true; wait "$busy_pid" 2>/dev/null
> || true
> +echo 0 > /sys/kernel/tracing/events/rv/error_env_tlob/enable
> +echo 0 > /sys/kernel/tracing/events/rv/detail_env_tlob/enable
> +echo 0 > monitors/tlob/enable
> +
> +[ "$found" = "1" ]
> +
> +# error_env_tlob must carry the clk_elapsed environment field.
> +# The event label is "budget_exceeded" when detected by the hrtimer
> callback,
> +# or the triggering sched event name when detected by the constraint
> path on a
> +# preemption that races with the timer (common on PREEMPT_RT / VM). 
> Both are
> +# valid detections; check the env field instead of the label.
> +grep "error_env_tlob" /sys/kernel/tracing/trace | head -n 1 | grep -
> q "clk_elapsed="
> +
> +# detail_env_tlob must have all five fields with the correct
> threshold
> +line=$(grep "detail_env_tlob" /sys/kernel/tracing/trace | head -n 1)
> +echo "$line" | grep -q "pid="
> +echo "$line" | grep -q "threshold_ns=10000"
> +echo "$line" | grep -q "running_ns="
> +echo "$line" | grep -q "waiting_ns="
> +echo "$line" | grep -q "sleeping_ns="
> +
> +# Busy-spin keeps the task on-CPU: running_ns must exceed
> sleeping_ns.
> +running=$(echo "$line" | sed 's/.*running_ns=\([0-9]*\).*/\1/')
> +sleeping=$(echo "$line" | sed 's/.*sleeping_ns=\([0-9]*\).*/\1/')
> +[ "$running" -gt "$sleeping" ]
> +
> +echo > /sys/kernel/tracing/trace