diff options
author | Martin KaFai Lau <kafai@fb.com> | 2017-01-17 01:17:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-01-17 15:39:39 -0500 |
commit | 3fbfadce6012e7bb384b2e9ad47869d5177f7209 (patch) | |
tree | c768617d6b7949b5b4bb75c6b2e58b08b4e1f6ea | |
parent | d5ff72d9af73bc3cbaa3edb541333a851f8c7295 (diff) |
bpf: Fix test_lru_sanity5() in test_lru_map.c
test_lru_sanity5() fails when the number of online cpus
is fewer than the number of possible cpus. It can be
reproduced with qemu by using cmd args "--smp cpus=2,maxcpus=8".
The problem is the loop in test_lru_sanity5() is testing
'i' which is incorrect.
This patch:
1. Make sched_next_online() always return -1 if it cannot
find a next cpu to schedule the process.
2. In test_lru_sanity5(), the parent process does
sched_setaffinity() first (through sched_next_online())
and the forked process will inherit it according to
the 'man sched_setaffinity'.
Fixes: 5db58faf989f ("bpf: Add tests for the LRU bpf_htab")
Reported-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | tools/testing/selftests/bpf/test_lru_map.c | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c index b13fed534d76..9f7bd1915c21 100644 --- a/tools/testing/selftests/bpf/test_lru_map.c +++ b/tools/testing/selftests/bpf/test_lru_map.c | |||
@@ -67,21 +67,23 @@ static int map_equal(int lru_map, int expected) | |||
67 | return map_subset(lru_map, expected) && map_subset(expected, lru_map); | 67 | return map_subset(lru_map, expected) && map_subset(expected, lru_map); |
68 | } | 68 | } |
69 | 69 | ||
70 | static int sched_next_online(int pid, int next_to_try) | 70 | static int sched_next_online(int pid, int *next_to_try) |
71 | { | 71 | { |
72 | cpu_set_t cpuset; | 72 | cpu_set_t cpuset; |
73 | int next = *next_to_try; | ||
74 | int ret = -1; | ||
73 | 75 | ||
74 | if (next_to_try == nr_cpus) | 76 | while (next < nr_cpus) { |
75 | return -1; | ||
76 | |||
77 | while (next_to_try < nr_cpus) { | ||
78 | CPU_ZERO(&cpuset); | 77 | CPU_ZERO(&cpuset); |
79 | CPU_SET(next_to_try++, &cpuset); | 78 | CPU_SET(next++, &cpuset); |
80 | if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) | 79 | if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) { |
80 | ret = 0; | ||
81 | break; | 81 | break; |
82 | } | ||
82 | } | 83 | } |
83 | 84 | ||
84 | return next_to_try; | 85 | *next_to_try = next; |
86 | return ret; | ||
85 | } | 87 | } |
86 | 88 | ||
87 | /* Size of the LRU amp is 2 | 89 | /* Size of the LRU amp is 2 |
@@ -96,11 +98,12 @@ static void test_lru_sanity0(int map_type, int map_flags) | |||
96 | { | 98 | { |
97 | unsigned long long key, value[nr_cpus]; | 99 | unsigned long long key, value[nr_cpus]; |
98 | int lru_map_fd, expected_map_fd; | 100 | int lru_map_fd, expected_map_fd; |
101 | int next_cpu = 0; | ||
99 | 102 | ||
100 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 103 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
101 | map_flags); | 104 | map_flags); |
102 | 105 | ||
103 | assert(sched_next_online(0, 0) != -1); | 106 | assert(sched_next_online(0, &next_cpu) != -1); |
104 | 107 | ||
105 | if (map_flags & BPF_F_NO_COMMON_LRU) | 108 | if (map_flags & BPF_F_NO_COMMON_LRU) |
106 | lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus); | 109 | lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus); |
@@ -183,6 +186,7 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free) | |||
183 | int lru_map_fd, expected_map_fd; | 186 | int lru_map_fd, expected_map_fd; |
184 | unsigned int batch_size; | 187 | unsigned int batch_size; |
185 | unsigned int map_size; | 188 | unsigned int map_size; |
189 | int next_cpu = 0; | ||
186 | 190 | ||
187 | if (map_flags & BPF_F_NO_COMMON_LRU) | 191 | if (map_flags & BPF_F_NO_COMMON_LRU) |
188 | /* Ther percpu lru list (i.e each cpu has its own LRU | 192 | /* Ther percpu lru list (i.e each cpu has its own LRU |
@@ -196,7 +200,7 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free) | |||
196 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 200 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
197 | map_flags); | 201 | map_flags); |
198 | 202 | ||
199 | assert(sched_next_online(0, 0) != -1); | 203 | assert(sched_next_online(0, &next_cpu) != -1); |
200 | 204 | ||
201 | batch_size = tgt_free / 2; | 205 | batch_size = tgt_free / 2; |
202 | assert(batch_size * 2 == tgt_free); | 206 | assert(batch_size * 2 == tgt_free); |
@@ -262,6 +266,7 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free) | |||
262 | int lru_map_fd, expected_map_fd; | 266 | int lru_map_fd, expected_map_fd; |
263 | unsigned int batch_size; | 267 | unsigned int batch_size; |
264 | unsigned int map_size; | 268 | unsigned int map_size; |
269 | int next_cpu = 0; | ||
265 | 270 | ||
266 | if (map_flags & BPF_F_NO_COMMON_LRU) | 271 | if (map_flags & BPF_F_NO_COMMON_LRU) |
267 | /* Ther percpu lru list (i.e each cpu has its own LRU | 272 | /* Ther percpu lru list (i.e each cpu has its own LRU |
@@ -275,7 +280,7 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free) | |||
275 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 280 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
276 | map_flags); | 281 | map_flags); |
277 | 282 | ||
278 | assert(sched_next_online(0, 0) != -1); | 283 | assert(sched_next_online(0, &next_cpu) != -1); |
279 | 284 | ||
280 | batch_size = tgt_free / 2; | 285 | batch_size = tgt_free / 2; |
281 | assert(batch_size * 2 == tgt_free); | 286 | assert(batch_size * 2 == tgt_free); |
@@ -370,11 +375,12 @@ static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free) | |||
370 | int lru_map_fd, expected_map_fd; | 375 | int lru_map_fd, expected_map_fd; |
371 | unsigned int batch_size; | 376 | unsigned int batch_size; |
372 | unsigned int map_size; | 377 | unsigned int map_size; |
378 | int next_cpu = 0; | ||
373 | 379 | ||
374 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 380 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
375 | map_flags); | 381 | map_flags); |
376 | 382 | ||
377 | assert(sched_next_online(0, 0) != -1); | 383 | assert(sched_next_online(0, &next_cpu) != -1); |
378 | 384 | ||
379 | batch_size = tgt_free / 2; | 385 | batch_size = tgt_free / 2; |
380 | assert(batch_size * 2 == tgt_free); | 386 | assert(batch_size * 2 == tgt_free); |
@@ -430,11 +436,12 @@ static void test_lru_sanity4(int map_type, int map_flags, unsigned int tgt_free) | |||
430 | int lru_map_fd, expected_map_fd; | 436 | int lru_map_fd, expected_map_fd; |
431 | unsigned long long key, value[nr_cpus]; | 437 | unsigned long long key, value[nr_cpus]; |
432 | unsigned long long end_key; | 438 | unsigned long long end_key; |
439 | int next_cpu = 0; | ||
433 | 440 | ||
434 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 441 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
435 | map_flags); | 442 | map_flags); |
436 | 443 | ||
437 | assert(sched_next_online(0, 0) != -1); | 444 | assert(sched_next_online(0, &next_cpu) != -1); |
438 | 445 | ||
439 | if (map_flags & BPF_F_NO_COMMON_LRU) | 446 | if (map_flags & BPF_F_NO_COMMON_LRU) |
440 | lru_map_fd = create_map(map_type, map_flags, | 447 | lru_map_fd = create_map(map_type, map_flags, |
@@ -502,9 +509,8 @@ static void do_test_lru_sanity5(unsigned long long last_key, int map_fd) | |||
502 | static void test_lru_sanity5(int map_type, int map_flags) | 509 | static void test_lru_sanity5(int map_type, int map_flags) |
503 | { | 510 | { |
504 | unsigned long long key, value[nr_cpus]; | 511 | unsigned long long key, value[nr_cpus]; |
505 | int next_sched_cpu = 0; | 512 | int next_cpu = 0; |
506 | int map_fd; | 513 | int map_fd; |
507 | int i; | ||
508 | 514 | ||
509 | if (map_flags & BPF_F_NO_COMMON_LRU) | 515 | if (map_flags & BPF_F_NO_COMMON_LRU) |
510 | return; | 516 | return; |
@@ -519,27 +525,20 @@ static void test_lru_sanity5(int map_type, int map_flags) | |||
519 | key = 0; | 525 | key = 0; |
520 | assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST)); | 526 | assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST)); |
521 | 527 | ||
522 | for (i = 0; i < nr_cpus; i++) { | 528 | while (sched_next_online(0, &next_cpu) != -1) { |
523 | pid_t pid; | 529 | pid_t pid; |
524 | 530 | ||
525 | pid = fork(); | 531 | pid = fork(); |
526 | if (pid == 0) { | 532 | if (pid == 0) { |
527 | next_sched_cpu = sched_next_online(0, next_sched_cpu); | 533 | do_test_lru_sanity5(key, map_fd); |
528 | if (next_sched_cpu != -1) | ||
529 | do_test_lru_sanity5(key, map_fd); | ||
530 | exit(0); | 534 | exit(0); |
531 | } else if (pid == -1) { | 535 | } else if (pid == -1) { |
532 | printf("couldn't spawn #%d process\n", i); | 536 | printf("couldn't spawn process to test key:%llu\n", |
537 | key); | ||
533 | exit(1); | 538 | exit(1); |
534 | } else { | 539 | } else { |
535 | int status; | 540 | int status; |
536 | 541 | ||
537 | /* It is mostly redundant and just allow the parent | ||
538 | * process to update next_shced_cpu for the next child | ||
539 | * process | ||
540 | */ | ||
541 | next_sched_cpu = sched_next_online(pid, next_sched_cpu); | ||
542 | |||
543 | assert(waitpid(pid, &status, 0) == pid); | 542 | assert(waitpid(pid, &status, 0) == pid); |
544 | assert(status == 0); | 543 | assert(status == 0); |
545 | key++; | 544 | key++; |
@@ -547,6 +546,8 @@ static void test_lru_sanity5(int map_type, int map_flags) | |||
547 | } | 546 | } |
548 | 547 | ||
549 | close(map_fd); | 548 | close(map_fd); |
549 | /* At least one key should be tested */ | ||
550 | assert(key > 0); | ||
550 | 551 | ||
551 | printf("Pass\n"); | 552 | printf("Pass\n"); |
552 | } | 553 | } |