mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-29 05:46:18 -04:00
Now that BPF __arg_arena has been subsumed by __arena, remove __arg_arena from the codebase. This way the user has one fewer annotation to worry about. To remove __arg_arena we remove the typedefs we were previously using to minimize __arena annotations. This is because __arena now also includes a BTF type tag, which is ignored for non-pointer types. As a result, we cannot capture the whole __arena annotation inside a typedef and need to directly annotate the pointer type when declaring the variable. The extra verbosity is worth it because the use of the __arena tag is intuitive to the programmer and removes the __arg_arena tag that has been a consistent source of confusion for users. The typedefs can be reintroduced later (without __arg_arena) once compilers start supporting BTF type tags for non-pointer types. Acked-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com> Link: https://lore.kernel.org/r/20260602004120.17087-5-emil@etsalapatis.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
100 lines
2.1 KiB
C
100 lines
2.1 KiB
C
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
|
/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
|
|
#pragma once
|
|
#include <errno.h>
|
|
#include "bpf_arena_alloc.h"
|
|
#include "bpf_arena_list.h"
|
|
|
|
struct htab_bucket {
|
|
struct arena_list_head head;
|
|
};
|
|
typedef struct htab_bucket __arena htab_bucket_t;
|
|
|
|
struct htab {
|
|
htab_bucket_t *buckets;
|
|
int n_buckets;
|
|
};
|
|
|
|
static inline htab_bucket_t *__select_bucket(struct htab __arena *htab, __u32 hash)
|
|
{
|
|
htab_bucket_t *b = htab->buckets;
|
|
|
|
cast_kern(b);
|
|
return &b[hash & (htab->n_buckets - 1)];
|
|
}
|
|
|
|
static inline arena_list_head_t *select_bucket(struct htab __arena *htab, __u32 hash)
|
|
{
|
|
return &__select_bucket(htab, hash)->head;
|
|
}
|
|
|
|
struct hashtab_elem {
|
|
int hash;
|
|
int key;
|
|
int value;
|
|
struct arena_list_node hash_node;
|
|
};
|
|
typedef struct hashtab_elem __arena hashtab_elem_t;
|
|
|
|
static hashtab_elem_t *lookup_elem_raw(arena_list_head_t *head, __u32 hash, int key)
|
|
{
|
|
hashtab_elem_t *l;
|
|
|
|
list_for_each_entry(l, head, hash_node)
|
|
if (l->hash == hash && l->key == key)
|
|
return l;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int htab_hash(int key)
|
|
{
|
|
return key;
|
|
}
|
|
|
|
__weak int htab_lookup_elem(struct htab __arena *htab, int key)
|
|
{
|
|
hashtab_elem_t *l_old;
|
|
arena_list_head_t *head;
|
|
|
|
cast_kern(htab);
|
|
head = select_bucket(htab, key);
|
|
l_old = lookup_elem_raw(head, htab_hash(key), key);
|
|
if (l_old)
|
|
return l_old->value;
|
|
return 0;
|
|
}
|
|
|
|
__weak int htab_update_elem(struct htab __arena *htab, int key, int value)
|
|
{
|
|
hashtab_elem_t *l_new = NULL, *l_old;
|
|
arena_list_head_t *head;
|
|
|
|
cast_kern(htab);
|
|
head = select_bucket(htab, key);
|
|
l_old = lookup_elem_raw(head, htab_hash(key), key);
|
|
|
|
l_new = bpf_alloc(sizeof(*l_new));
|
|
if (!l_new)
|
|
return -ENOMEM;
|
|
l_new->key = key;
|
|
l_new->hash = htab_hash(key);
|
|
l_new->value = value;
|
|
|
|
list_add_head(&l_new->hash_node, head);
|
|
if (l_old) {
|
|
list_del(&l_old->hash_node);
|
|
bpf_free(l_old);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void htab_init(struct htab __arena *htab)
|
|
{
|
|
void __arena *buckets = bpf_arena_alloc_pages(&arena, NULL, 2, NUMA_NO_NODE, 0);
|
|
|
|
cast_user(buckets);
|
|
htab->buckets = buckets;
|
|
htab->n_buckets = 2 * PAGE_SIZE / sizeof(struct htab_bucket);
|
|
}
|