Skip to content

Commit 403e935

Browse files
ameryhungMartin KaFai Lau
authored andcommitted
bpf: Convert bpf_selem_unlink to failable
To prepare changing both bpf_local_storage_map_bucket::lock and bpf_local_storage::lock to rqspinlock, convert bpf_selem_unlink() to failable. It still always succeeds and returns 0 until the change happens. No functional change. Open code bpf_selem_unlink_storage() in the only caller, bpf_selem_unlink(), since unlink_map and unlink_storage must be done together after all the necessary locks are acquired. For bpf_local_storage_map_free(), ignore the return from bpf_selem_unlink() for now. A later patch will allow it to unlink selems even when failing to acquire locks. 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-5-ameryhung@gmail.com
1 parent fd103ff commit 403e935

6 files changed

Lines changed: 39 additions & 49 deletions

File tree

include/linux/bpf_local_storage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ int bpf_local_storage_map_check_btf(const struct bpf_map *map,
176176
void bpf_selem_link_storage_nolock(struct bpf_local_storage *local_storage,
177177
struct bpf_local_storage_elem *selem);
178178

179-
void bpf_selem_unlink(struct bpf_local_storage_elem *selem, bool reuse_now);
179+
int bpf_selem_unlink(struct bpf_local_storage_elem *selem, bool reuse_now);
180180

181181
int bpf_selem_link_map(struct bpf_local_storage_map *smap,
182182
struct bpf_local_storage *local_storage,

kernel/bpf/bpf_cgrp_storage.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ static int cgroup_storage_delete(struct cgroup *cgroup, struct bpf_map *map)
118118
if (!sdata)
119119
return -ENOENT;
120120

121-
bpf_selem_unlink(SELEM(sdata), false);
122-
return 0;
121+
return bpf_selem_unlink(SELEM(sdata), false);
123122
}
124123

125124
static long bpf_cgrp_storage_delete_elem(struct bpf_map *map, void *key)

kernel/bpf/bpf_inode_storage.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,7 @@ static int inode_storage_delete(struct inode *inode, struct bpf_map *map)
110110
if (!sdata)
111111
return -ENOENT;
112112

113-
bpf_selem_unlink(SELEM(sdata), false);
114-
115-
return 0;
113+
return bpf_selem_unlink(SELEM(sdata), false);
116114
}
117115

118116
static long bpf_fd_inode_storage_delete_elem(struct bpf_map *map, void *key)

kernel/bpf/bpf_local_storage.c

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -308,33 +308,6 @@ static bool bpf_selem_unlink_storage_nolock(struct bpf_local_storage *local_stor
308308
return free_local_storage;
309309
}
310310

311-
static void bpf_selem_unlink_storage(struct bpf_local_storage_elem *selem,
312-
bool reuse_now)
313-
{
314-
struct bpf_local_storage *local_storage;
315-
bool free_local_storage = false;
316-
HLIST_HEAD(selem_free_list);
317-
unsigned long flags;
318-
319-
if (unlikely(!selem_linked_to_storage_lockless(selem)))
320-
/* selem has already been unlinked from sk */
321-
return;
322-
323-
local_storage = rcu_dereference_check(selem->local_storage,
324-
bpf_rcu_lock_held());
325-
326-
raw_spin_lock_irqsave(&local_storage->lock, flags);
327-
if (likely(selem_linked_to_storage(selem)))
328-
free_local_storage = bpf_selem_unlink_storage_nolock(
329-
local_storage, selem, &selem_free_list);
330-
raw_spin_unlock_irqrestore(&local_storage->lock, flags);
331-
332-
bpf_selem_free_list(&selem_free_list, reuse_now);
333-
334-
if (free_local_storage)
335-
bpf_local_storage_free(local_storage, reuse_now);
336-
}
337-
338311
void bpf_selem_link_storage_nolock(struct bpf_local_storage *local_storage,
339312
struct bpf_local_storage_elem *selem)
340313
{
@@ -386,19 +359,43 @@ static void bpf_selem_link_map_nolock(struct bpf_local_storage_map_bucket *b,
386359
hlist_add_head_rcu(&selem->map_node, &b->list);
387360
}
388361

389-
void bpf_selem_unlink(struct bpf_local_storage_elem *selem, bool reuse_now)
362+
int bpf_selem_unlink(struct bpf_local_storage_elem *selem, bool reuse_now)
390363
{
391-
int err;
364+
struct bpf_local_storage *local_storage;
365+
bool free_local_storage = false;
366+
HLIST_HEAD(selem_free_list);
367+
unsigned long flags;
368+
int err = 0;
392369

393-
/* Always unlink from map before unlinking from local_storage
394-
* because selem will be freed after successfully unlinked from
395-
* the local_storage.
396-
*/
397-
err = bpf_selem_unlink_map(selem);
398-
if (err)
399-
return;
370+
if (unlikely(!selem_linked_to_storage_lockless(selem)))
371+
/* selem has already been unlinked from sk */
372+
return 0;
373+
374+
local_storage = rcu_dereference_check(selem->local_storage,
375+
bpf_rcu_lock_held());
376+
377+
raw_spin_lock_irqsave(&local_storage->lock, flags);
378+
if (likely(selem_linked_to_storage(selem))) {
379+
/* Always unlink from map before unlinking from local_storage
380+
* because selem will be freed after successfully unlinked from
381+
* the local_storage.
382+
*/
383+
err = bpf_selem_unlink_map(selem);
384+
if (err)
385+
goto out;
386+
387+
free_local_storage = bpf_selem_unlink_storage_nolock(
388+
local_storage, selem, &selem_free_list);
389+
}
390+
out:
391+
raw_spin_unlock_irqrestore(&local_storage->lock, flags);
400392

401-
bpf_selem_unlink_storage(selem, reuse_now);
393+
bpf_selem_free_list(&selem_free_list, reuse_now);
394+
395+
if (free_local_storage)
396+
bpf_local_storage_free(local_storage, reuse_now);
397+
398+
return err;
402399
}
403400

404401
void __bpf_local_storage_insert_cache(struct bpf_local_storage *local_storage,

kernel/bpf/bpf_task_storage.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,7 @@ static int task_storage_delete(struct task_struct *task, struct bpf_map *map,
167167
if (!nobusy)
168168
return -EBUSY;
169169

170-
bpf_selem_unlink(SELEM(sdata), false);
171-
172-
return 0;
170+
return bpf_selem_unlink(SELEM(sdata), false);
173171
}
174172

175173
static long bpf_pid_task_storage_delete_elem(struct bpf_map *map, void *key)

net/core/bpf_sk_storage.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ static int bpf_sk_storage_del(struct sock *sk, struct bpf_map *map)
4040
if (!sdata)
4141
return -ENOENT;
4242

43-
bpf_selem_unlink(SELEM(sdata), false);
44-
45-
return 0;
43+
return bpf_selem_unlink(SELEM(sdata), false);
4644
}
4745

4846
/* Called by __sk_destruct() & bpf_sk_storage_clone() */

0 commit comments

Comments
 (0)