On Mon, 2026-06-08 at 00:13 +0800, [email protected] wrote: > From: Wen Yang <[email protected]> > > +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
