Skip to content

Commit 1f24362

Browse files
anakryikoborkmann
authored andcommitted
selftests/bpf: Fix ringbuf selftest sample counting undeterminism
Fix test race, in which background poll can get either 5 or 6 samples, depending on timing of notification. Prevent this by open-coding sample triggering and forcing notification for the very last sample only. Also switch to using atomic increments and exchanges for more obviously reliable counting and checking. Additionally, check expected processed sample counters for single-threaded use cases as well. Fixes: 9a5f25a ("selftests/bpf: Fix sample_cnt shared between two threads") Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent e7ed83d commit 1f24362

File tree

1 file changed

+35
-7
lines changed
  • tools/testing/selftests/bpf/prog_tests

1 file changed

+35
-7
lines changed

tools/testing/selftests/bpf/prog_tests/ringbuf.c

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,23 @@ struct sample {
2525
char comm[16];
2626
};
2727

28-
static volatile int sample_cnt;
28+
static int sample_cnt;
29+
30+
static void atomic_inc(int *cnt)
31+
{
32+
__atomic_add_fetch(cnt, 1, __ATOMIC_SEQ_CST);
33+
}
34+
35+
static int atomic_xchg(int *cnt, int val)
36+
{
37+
return __atomic_exchange_n(cnt, val, __ATOMIC_SEQ_CST);
38+
}
2939

3040
static int process_sample(void *ctx, void *data, size_t len)
3141
{
3242
struct sample *s = data;
3343

34-
sample_cnt++;
44+
atomic_inc(&sample_cnt);
3545

3646
switch (s->seq) {
3747
case 0:
@@ -76,7 +86,7 @@ void test_ringbuf(void)
7686
const size_t rec_sz = BPF_RINGBUF_HDR_SZ + sizeof(struct sample);
7787
pthread_t thread;
7888
long bg_ret = -1;
79-
int err;
89+
int err, cnt;
8090

8191
skel = test_ringbuf__open_and_load();
8292
if (CHECK(!skel, "skel_open_load", "skeleton open&load failed\n"))
@@ -116,11 +126,15 @@ void test_ringbuf(void)
116126
/* -EDONE is used as an indicator that we are done */
117127
if (CHECK(err != -EDONE, "err_done", "done err: %d\n", err))
118128
goto cleanup;
129+
cnt = atomic_xchg(&sample_cnt, 0);
130+
CHECK(cnt != 2, "cnt", "exp %d samples, got %d\n", 2, cnt);
119131

120132
/* we expect extra polling to return nothing */
121133
err = ring_buffer__poll(ringbuf, 0);
122134
if (CHECK(err != 0, "extra_samples", "poll result: %d\n", err))
123135
goto cleanup;
136+
cnt = atomic_xchg(&sample_cnt, 0);
137+
CHECK(cnt != 0, "cnt", "exp %d samples, got %d\n", 0, cnt);
124138

125139
CHECK(skel->bss->dropped != 0, "err_dropped", "exp %ld, got %ld\n",
126140
0L, skel->bss->dropped);
@@ -136,6 +150,8 @@ void test_ringbuf(void)
136150
3L * rec_sz, skel->bss->cons_pos);
137151
err = ring_buffer__poll(ringbuf, -1);
138152
CHECK(err <= 0, "poll_err", "err %d\n", err);
153+
cnt = atomic_xchg(&sample_cnt, 0);
154+
CHECK(cnt != 2, "cnt", "exp %d samples, got %d\n", 2, cnt);
139155

140156
/* start poll in background w/ long timeout */
141157
err = pthread_create(&thread, NULL, poll_thread, (void *)(long)10000);
@@ -164,6 +180,8 @@ void test_ringbuf(void)
164180
2L, skel->bss->total);
165181
CHECK(skel->bss->discarded != 1, "err_discarded", "exp %ld, got %ld\n",
166182
1L, skel->bss->discarded);
183+
cnt = atomic_xchg(&sample_cnt, 0);
184+
CHECK(cnt != 0, "cnt", "exp %d samples, got %d\n", 0, cnt);
167185

168186
/* clear flags to return to "adaptive" notification mode */
169187
skel->bss->flags = 0;
@@ -178,10 +196,20 @@ void test_ringbuf(void)
178196
if (CHECK(err != EBUSY, "try_join", "err %d\n", err))
179197
goto cleanup;
180198

199+
/* still no samples, because consumer is behind */
200+
cnt = atomic_xchg(&sample_cnt, 0);
201+
CHECK(cnt != 0, "cnt", "exp %d samples, got %d\n", 0, cnt);
202+
203+
skel->bss->dropped = 0;
204+
skel->bss->total = 0;
205+
skel->bss->discarded = 0;
206+
207+
skel->bss->value = 333;
208+
syscall(__NR_getpgid);
181209
/* now force notifications */
182210
skel->bss->flags = BPF_RB_FORCE_WAKEUP;
183-
sample_cnt = 0;
184-
trigger_samples();
211+
skel->bss->value = 777;
212+
syscall(__NR_getpgid);
185213

186214
/* now we should get a pending notification */
187215
usleep(50000);
@@ -193,8 +221,8 @@ void test_ringbuf(void)
193221
goto cleanup;
194222

195223
/* 3 rounds, 2 samples each */
196-
CHECK(sample_cnt != 6, "wrong_sample_cnt",
197-
"expected to see %d samples, got %d\n", 6, sample_cnt);
224+
cnt = atomic_xchg(&sample_cnt, 0);
225+
CHECK(cnt != 6, "cnt", "exp %d samples, got %d\n", 6, cnt);
198226

199227
/* BPF side did everything right */
200228
CHECK(skel->bss->dropped != 0, "err_dropped", "exp %ld, got %ld\n",

0 commit comments

Comments
 (0)