tools/testing/selftests/bpf/progs/refcounted_kptr.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/progs/refcounted_kptr.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/progs/refcounted_kptr.c
Extension
.c
Size
22320 bytes
Lines
1071
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct node_data {
	long key;
	long list_data;
	struct bpf_rb_node r;
	struct bpf_list_node l;
	struct bpf_refcount ref;
};

struct map_value {
	struct node_data __kptr *node;
};

struct {
	__uint(type, BPF_MAP_TYPE_ARRAY);
	__type(key, int);
	__type(value, struct map_value);
	__uint(max_entries, 2);
} stashed_nodes SEC(".maps");

struct node_acquire {
	long key;
	long data;
	struct bpf_rb_node node;
	struct bpf_refcount refcount;
};

#define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8)))
private(A) struct bpf_spin_lock lock;
private(A) struct bpf_rb_root root __contains(node_data, r);
private(A) struct bpf_list_head head __contains(node_data, l);

private(B) struct bpf_spin_lock alock;
private(B) struct bpf_rb_root aroot __contains(node_acquire, node);

private(C) struct bpf_spin_lock block;
private(C) struct bpf_rb_root broot __contains(node_data, r);

static bool less(struct bpf_rb_node *node_a, const struct bpf_rb_node *node_b)
{
	struct node_data *a;
	struct node_data *b;

	a = container_of(node_a, struct node_data, r);
	b = container_of(node_b, struct node_data, r);

	return a->key < b->key;
}

static bool less_a(struct bpf_rb_node *a, const struct bpf_rb_node *b)
{
	struct node_acquire *node_a;
	struct node_acquire *node_b;

	node_a = container_of(a, struct node_acquire, node);
	node_b = container_of(b, struct node_acquire, node);

	return node_a->key < node_b->key;
}

static long __insert_in_tree_and_list(struct bpf_list_head *head,
				      struct bpf_rb_root *root,
				      struct bpf_spin_lock *lock)
{
	struct node_data *n, *m;

	n = bpf_obj_new(typeof(*n));
	if (!n)
		return -1;

	m = bpf_refcount_acquire(n);
	m->key = 123;
	m->list_data = 456;

	bpf_spin_lock(lock);
	if (bpf_rbtree_add(root, &n->r, less)) {
		/* Failure to insert - unexpected */
		bpf_spin_unlock(lock);
		bpf_obj_drop(m);
		return -2;
	}
	bpf_spin_unlock(lock);

	bpf_spin_lock(lock);
	if (bpf_list_push_front(head, &m->l)) {
		/* Failure to insert - unexpected */
		bpf_spin_unlock(lock);
		return -3;
	}
	bpf_spin_unlock(lock);
	return 0;

Annotation

Implementation Notes