Skip to content

Commit 0ccef70

Browse files
ameryhungMartin KaFai Lau
authored andcommitted
bpf: Select bpf_local_storage_map_bucket based on bpf_local_storage
A later bpf_local_storage refactor will acquire all locks before performing any update. To simplified the number of locks needed to take in bpf_local_storage_map_update(), determine the bucket based on the local_storage an selem belongs to instead of the selem pointer. Currently, when a new selem needs to be created to replace the old selem in bpf_local_storage_map_update(), locks of both buckets need to be acquired to prevent racing. This can be simplified if the two selem belongs to the same bucket so that only one bucket needs to be locked. Therefore, instead of hashing selem, hashing the local_storage pointer the selem belongs. Performance wise, this is slightly better as update now requires locking one bucket. It should not change the level of contention on one bucket as the pointers to local storages of selems in a map are just as unique as pointers to selems. Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Amery Hung <ameryhung@gmail.com> Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Link: https://patch.msgid.link/20260205222916.1788211-2-ameryhung@gmail.com
1 parent b8c89f5 commit 0ccef70

3 files changed

Lines changed: 13 additions & 7 deletions

File tree

include/linux/bpf_local_storage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ void bpf_selem_link_storage_nolock(struct bpf_local_storage *local_storage,
179179
void bpf_selem_unlink(struct bpf_local_storage_elem *selem, bool reuse_now);
180180

181181
void bpf_selem_link_map(struct bpf_local_storage_map *smap,
182+
struct bpf_local_storage *local_storage,
182183
struct bpf_local_storage_elem *selem);
183184

184185
struct bpf_local_storage_elem *

kernel/bpf/bpf_local_storage.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919

2020
static struct bpf_local_storage_map_bucket *
2121
select_bucket(struct bpf_local_storage_map *smap,
22-
struct bpf_local_storage_elem *selem)
22+
struct bpf_local_storage *local_storage)
2323
{
24-
return &smap->buckets[hash_ptr(selem, smap->bucket_log)];
24+
return &smap->buckets[hash_ptr(local_storage, smap->bucket_log)];
2525
}
2626

2727
static int mem_charge(struct bpf_local_storage_map *smap, void *owner, u32 size)
@@ -349,6 +349,7 @@ void bpf_selem_link_storage_nolock(struct bpf_local_storage *local_storage,
349349

350350
static void bpf_selem_unlink_map(struct bpf_local_storage_elem *selem)
351351
{
352+
struct bpf_local_storage *local_storage;
352353
struct bpf_local_storage_map *smap;
353354
struct bpf_local_storage_map_bucket *b;
354355
unsigned long flags;
@@ -357,20 +358,24 @@ static void bpf_selem_unlink_map(struct bpf_local_storage_elem *selem)
357358
/* selem has already be unlinked from smap */
358359
return;
359360

361+
local_storage = rcu_dereference_check(selem->local_storage,
362+
bpf_rcu_lock_held());
360363
smap = rcu_dereference_check(SDATA(selem)->smap, bpf_rcu_lock_held());
361-
b = select_bucket(smap, selem);
364+
b = select_bucket(smap, local_storage);
362365
raw_spin_lock_irqsave(&b->lock, flags);
363366
if (likely(selem_linked_to_map(selem)))
364367
hlist_del_init_rcu(&selem->map_node);
365368
raw_spin_unlock_irqrestore(&b->lock, flags);
366369
}
367370

368371
void bpf_selem_link_map(struct bpf_local_storage_map *smap,
372+
struct bpf_local_storage *local_storage,
369373
struct bpf_local_storage_elem *selem)
370374
{
371-
struct bpf_local_storage_map_bucket *b = select_bucket(smap, selem);
375+
struct bpf_local_storage_map_bucket *b;
372376
unsigned long flags;
373377

378+
b = select_bucket(smap, local_storage);
374379
raw_spin_lock_irqsave(&b->lock, flags);
375380
hlist_add_head_rcu(&selem->map_node, &b->list);
376381
raw_spin_unlock_irqrestore(&b->lock, flags);
@@ -448,7 +453,7 @@ int bpf_local_storage_alloc(void *owner,
448453
storage->use_kmalloc_nolock = smap->use_kmalloc_nolock;
449454

450455
bpf_selem_link_storage_nolock(storage, first_selem);
451-
bpf_selem_link_map(smap, first_selem);
456+
bpf_selem_link_map(smap, storage, first_selem);
452457

453458
owner_storage_ptr =
454459
(struct bpf_local_storage **)owner_storage(smap, owner);
@@ -576,7 +581,7 @@ bpf_local_storage_update(void *owner, struct bpf_local_storage_map *smap,
576581

577582
alloc_selem = NULL;
578583
/* First, link the new selem to the map */
579-
bpf_selem_link_map(smap, selem);
584+
bpf_selem_link_map(smap, local_storage, selem);
580585

581586
/* Second, link (and publish) the new selem to local_storage */
582587
bpf_selem_link_storage_nolock(local_storage, selem);

net/core/bpf_sk_storage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ int bpf_sk_storage_clone(const struct sock *sk, struct sock *newsk)
191191
}
192192

193193
if (new_sk_storage) {
194-
bpf_selem_link_map(smap, copy_selem);
194+
bpf_selem_link_map(smap, new_sk_storage, copy_selem);
195195
bpf_selem_link_storage_nolock(new_sk_storage, copy_selem);
196196
} else {
197197
ret = bpf_local_storage_alloc(newsk, smap, copy_selem, GFP_ATOMIC);

0 commit comments

Comments
 (0)