Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Kumar Kartikeya Dwivedi | 1810 | 87.19% | 1 | 14.29% |
Kui-Feng Lee | 153 | 7.37% | 1 | 14.29% |
Dave Marchevsky | 77 | 3.71% | 2 | 28.57% |
Alexei Starovoitov | 33 | 1.59% | 2 | 28.57% |
Andrii Nakryiko | 3 | 0.14% | 1 | 14.29% |
Total | 2076 | 7 |
// SPDX-License-Identifier: GPL-2.0 #include <vmlinux.h> #include <bpf/bpf_tracing.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_core_read.h> #include "bpf_experimental.h" #include "bpf_misc.h" #include "linked_list.h" struct head_nested_inner { struct bpf_spin_lock lock; struct bpf_list_head head __contains(foo, node2); }; struct head_nested { int dummy; struct head_nested_inner inner; }; private(C) struct bpf_spin_lock glock_c; private(C) struct bpf_list_head ghead_array[2] __contains(foo, node2); private(C) struct bpf_list_head ghead_array_one[1] __contains(foo, node2); private(D) struct head_nested ghead_nested; static __always_inline int list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) { struct bpf_list_node *n; struct foo *f; f = bpf_obj_new(typeof(*f)); if (!f) return 2; bpf_spin_lock(lock); n = bpf_list_pop_front(head); bpf_spin_unlock(lock); if (n) { bpf_obj_drop(container_of(n, struct foo, node2)); bpf_obj_drop(f); return 3; } bpf_spin_lock(lock); n = bpf_list_pop_back(head); bpf_spin_unlock(lock); if (n) { bpf_obj_drop(container_of(n, struct foo, node2)); bpf_obj_drop(f); return 4; } bpf_spin_lock(lock); f->data = 42; bpf_list_push_front(head, &f->node2); bpf_spin_unlock(lock); if (leave_in_map) return 0; bpf_spin_lock(lock); n = bpf_list_pop_back(head); bpf_spin_unlock(lock); if (!n) return 5; f = container_of(n, struct foo, node2); if (f->data != 42) { bpf_obj_drop(f); return 6; } bpf_spin_lock(lock); f->data = 13; bpf_list_push_front(head, &f->node2); bpf_spin_unlock(lock); bpf_spin_lock(lock); n = bpf_list_pop_front(head); bpf_spin_unlock(lock); if (!n) return 7; f = container_of(n, struct foo, node2); if (f->data != 13) { bpf_obj_drop(f); return 8; } bpf_obj_drop(f); bpf_spin_lock(lock); n = bpf_list_pop_front(head); bpf_spin_unlock(lock); if (n) { bpf_obj_drop(container_of(n, struct foo, node2)); return 9; } bpf_spin_lock(lock); n = bpf_list_pop_back(head); bpf_spin_unlock(lock); if (n) { bpf_obj_drop(container_of(n, struct foo, node2)); return 10; } return 0; } static __always_inline int list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) { struct bpf_list_node *n; struct foo *f[200], *pf; int i; /* Loop following this check adds nodes 2-at-a-time in order to * validate multiple release_on_unlock release logic */ if (ARRAY_SIZE(f) % 2) return 10; for (i = 0; i < ARRAY_SIZE(f); i += 2) { f[i] = bpf_obj_new(typeof(**f)); if (!f[i]) return 2; f[i]->data = i; f[i + 1] = bpf_obj_new(typeof(**f)); if (!f[i + 1]) { bpf_obj_drop(f[i]); return 9; } f[i + 1]->data = i + 1; bpf_spin_lock(lock); bpf_list_push_front(head, &f[i]->node2); bpf_list_push_front(head, &f[i + 1]->node2); bpf_spin_unlock(lock); } for (i = 0; i < ARRAY_SIZE(f); i++) { bpf_spin_lock(lock); n = bpf_list_pop_front(head); bpf_spin_unlock(lock); if (!n) return 3; pf = container_of(n, struct foo, node2); if (pf->data != (ARRAY_SIZE(f) - i - 1)) { bpf_obj_drop(pf); return 4; } bpf_spin_lock(lock); bpf_list_push_back(head, &pf->node2); bpf_spin_unlock(lock); } if (leave_in_map) return 0; for (i = 0; i < ARRAY_SIZE(f); i++) { bpf_spin_lock(lock); n = bpf_list_pop_back(head); bpf_spin_unlock(lock); if (!n) return 5; pf = container_of(n, struct foo, node2); if (pf->data != i) { bpf_obj_drop(pf); return 6; } bpf_obj_drop(pf); } bpf_spin_lock(lock); n = bpf_list_pop_back(head); bpf_spin_unlock(lock); if (n) { bpf_obj_drop(container_of(n, struct foo, node2)); return 7; } bpf_spin_lock(lock); n = bpf_list_pop_front(head); bpf_spin_unlock(lock); if (n) { bpf_obj_drop(container_of(n, struct foo, node2)); return 8; } return 0; } static __always_inline int list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) { struct bpf_list_node *n; struct bar *ba[8], *b; struct foo *f; int i; f = bpf_obj_new(typeof(*f)); if (!f) return 2; for (i = 0; i < ARRAY_SIZE(ba); i++) { b = bpf_obj_new(typeof(*b)); if (!b) { bpf_obj_drop(f); return 3; } b->data = i; bpf_spin_lock(&f->lock); bpf_list_push_back(&f->head, &b->node); bpf_spin_unlock(&f->lock); } bpf_spin_lock(lock); f->data = 42; bpf_list_push_front(head, &f->node2); bpf_spin_unlock(lock); if (leave_in_map) return 0; bpf_spin_lock(lock); n = bpf_list_pop_front(head); bpf_spin_unlock(lock); if (!n) return 4; f = container_of(n, struct foo, node2); if (f->data != 42) { bpf_obj_drop(f); return 5; } for (i = 0; i < ARRAY_SIZE(ba); i++) { bpf_spin_lock(&f->lock); n = bpf_list_pop_front(&f->head); bpf_spin_unlock(&f->lock); if (!n) { bpf_obj_drop(f); return 6; } b = container_of(n, struct bar, node); if (b->data != i) { bpf_obj_drop(f); bpf_obj_drop(b); return 7; } bpf_obj_drop(b); } bpf_spin_lock(&f->lock); n = bpf_list_pop_front(&f->head); bpf_spin_unlock(&f->lock); if (n) { bpf_obj_drop(f); bpf_obj_drop(container_of(n, struct bar, node)); return 8; } bpf_obj_drop(f); return 0; } static __always_inline int test_list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head) { int ret; ret = list_push_pop(lock, head, false); if (ret) return ret; return list_push_pop(lock, head, true); } static __always_inline int test_list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head) { int ret; ret = list_push_pop_multiple(lock, head, false); if (ret) return ret; return list_push_pop_multiple(lock, head, true); } static __always_inline int test_list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head) { int ret; ret = list_in_list(lock, head, false); if (ret) return ret; return list_in_list(lock, head, true); } SEC("tc") int map_list_push_pop(void *ctx) { struct map_value *v; v = bpf_map_lookup_elem(&array_map, &(int){0}); if (!v) return 1; return test_list_push_pop(&v->lock, &v->head); } SEC("tc") int inner_map_list_push_pop(void *ctx) { struct map_value *v; void *map; map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); if (!map) return 1; v = bpf_map_lookup_elem(map, &(int){0}); if (!v) return 1; return test_list_push_pop(&v->lock, &v->head); } SEC("tc") int global_list_push_pop(void *ctx) { return test_list_push_pop(&glock, &ghead); } SEC("tc") int global_list_push_pop_nested(void *ctx) { return test_list_push_pop(&ghead_nested.inner.lock, &ghead_nested.inner.head); } SEC("tc") int global_list_array_push_pop(void *ctx) { int r; r = test_list_push_pop(&glock_c, &ghead_array[0]); if (r) return r; r = test_list_push_pop(&glock_c, &ghead_array[1]); if (r) return r; /* Arrays with only one element is a special case, being treated * just like a bpf_list_head variable by the verifier, not an * array. */ return test_list_push_pop(&glock_c, &ghead_array_one[0]); } SEC("tc") int map_list_push_pop_multiple(void *ctx) { struct map_value *v; v = bpf_map_lookup_elem(&array_map, &(int){0}); if (!v) return 1; return test_list_push_pop_multiple(&v->lock, &v->head); } SEC("tc") int inner_map_list_push_pop_multiple(void *ctx) { struct map_value *v; void *map; map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); if (!map) return 1; v = bpf_map_lookup_elem(map, &(int){0}); if (!v) return 1; return test_list_push_pop_multiple(&v->lock, &v->head); } SEC("tc") int global_list_push_pop_multiple(void *ctx) { int ret; ret = list_push_pop_multiple(&glock, &ghead, false); if (ret) return ret; return list_push_pop_multiple(&glock, &ghead, true); } SEC("tc") int map_list_in_list(void *ctx) { struct map_value *v; v = bpf_map_lookup_elem(&array_map, &(int){0}); if (!v) return 1; return test_list_in_list(&v->lock, &v->head); } SEC("tc") int inner_map_list_in_list(void *ctx) { struct map_value *v; void *map; map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); if (!map) return 1; v = bpf_map_lookup_elem(map, &(int){0}); if (!v) return 1; return test_list_in_list(&v->lock, &v->head); } SEC("tc") int global_list_in_list(void *ctx) { return test_list_in_list(&glock, &ghead); } char _license[] SEC("license") = "GPL";
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1