Skip to content

Commit 62d409e

Browse files
Denis Salopekkernel-patches-bot
authored andcommitted
bpf: add lookup_and_delete_elem support to hashtab
Extend the existing bpf_map_lookup_and_delete_elem() functionality to hashtab maps, in addition to stacks and queues. Create a new hashtab bpf_map_ops function that does lookup and deletion of the element under the same bucket lock and add the created map_ops to bpf.h. Add the appropriate test case to 'maps' selftests. Signed-off-by: Denis Salopek <denis.salopek@sartura.hr> Cc: Juraj Vijtiuk <juraj.vijtiuk@sartura.hr> Cc: Luka Oreskovic <luka.oreskovic@sartura.hr> Cc: Luka Perkov <luka.perkov@sartura.hr>
1 parent 871d9f8 commit 62d409e

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct bpf_map_ops {
7777

7878
/* funcs callable from userspace and from eBPF programs */
7979
void *(*map_lookup_elem)(struct bpf_map *map, void *key);
80+
int (*map_lookup_and_delete_elem)(struct bpf_map *map, void *key, void *value);
8081
int (*map_update_elem)(struct bpf_map *map, void *key, void *value, u64 flags);
8182
int (*map_delete_elem)(struct bpf_map *map, void *key);
8283
int (*map_push_elem)(struct bpf_map *map, void *value, u64 flags);

kernel/bpf/hashtab.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,43 @@ static int check_flags(struct bpf_htab *htab, struct htab_elem *l_old,
973973
return 0;
974974
}
975975

976+
/* Called from syscall or from eBPF program */
977+
static int htab_map_lookup_and_delete_elem(struct bpf_map *map, void *key, void *value)
978+
{
979+
struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
980+
struct hlist_nulls_head *head;
981+
struct bucket *b;
982+
struct htab_elem *l;
983+
unsigned long flags;
984+
u32 hash, key_size;
985+
int ret;
986+
987+
WARN_ON_ONCE(!rcu_read_lock_held() && !rcu_read_lock_trace_held());
988+
989+
key_size = map->key_size;
990+
991+
hash = htab_map_hash(key, key_size, htab->hashrnd);
992+
b = __select_bucket(htab, hash);
993+
head = &b->head;
994+
995+
ret = htab_lock_bucket(htab, b, hash, &flags);
996+
if (ret)
997+
return ret;
998+
999+
l = lookup_elem_raw(head, hash, key, key_size);
1000+
1001+
if (l) {
1002+
copy_map_value(map, value, l->key + round_up(key_size, 8));
1003+
hlist_nulls_del_rcu(&l->hash_node);
1004+
free_htab_elem(htab, l);
1005+
} else {
1006+
ret = -ENOENT;
1007+
}
1008+
1009+
htab_unlock_bucket(htab, b, hash, flags);
1010+
return ret;
1011+
}
1012+
9761013
/* Called from syscall or from eBPF program */
9771014
static int htab_map_update_elem(struct bpf_map *map, void *key, void *value,
9781015
u64 map_flags)
@@ -1877,6 +1914,7 @@ const struct bpf_map_ops htab_map_ops = {
18771914
.map_free = htab_map_free,
18781915
.map_get_next_key = htab_map_get_next_key,
18791916
.map_lookup_elem = htab_map_lookup_elem,
1917+
.map_lookup_and_delete_elem = htab_map_lookup_and_delete_elem,
18801918
.map_update_elem = htab_map_update_elem,
18811919
.map_delete_elem = htab_map_delete_elem,
18821920
.map_gen_lookup = htab_map_gen_lookup,

kernel/bpf/syscall.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,15 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
15051505
if (map->map_type == BPF_MAP_TYPE_QUEUE ||
15061506
map->map_type == BPF_MAP_TYPE_STACK) {
15071507
err = map->ops->map_pop_elem(map, value);
1508+
} else if (map->map_type == BPF_MAP_TYPE_HASH) {
1509+
if (!bpf_map_is_dev_bound(map)) {
1510+
bpf_disable_instrumentation();
1511+
rcu_read_lock();
1512+
err = map->ops->map_lookup_and_delete_elem(map, key, value);
1513+
rcu_read_unlock();
1514+
bpf_enable_instrumentation();
1515+
maybe_wait_bpf_programs(map);
1516+
}
15081517
} else {
15091518
err = -ENOTSUPP;
15101519
}

tools/testing/selftests/bpf/test_maps.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ static void test_hashmap(unsigned int task, void *data)
6565
assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
6666

6767
key = 2;
68+
value = 1234;
69+
/* Insert key=2 element. */
70+
assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
71+
72+
/* Check that key=2 matches the value and delete it */
73+
assert(bpf_map_lookup_and_delete_elem(fd, &key, &value) == 0 && value == 1234);
74+
6875
/* Check that key=2 is not found. */
6976
assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
7077

0 commit comments

Comments
 (0)