Skip to content

Commit 4a98c2e

Browse files
ameryhungMartin KaFai Lau
authored andcommitted
bpf: Remove task local storage percpu counter
The percpu counter in task local storage is no longer needed as the underlying bpf_local_storage can now handle deadlock with the help of rqspinlock. Remove the percpu counter and related migrate_{disable, enable}. Since the percpu counter is removed, merge back bpf_task_storage_get() and bpf_task_storage_get_recur(). This will allow the bpf syscalls and helpers to run concurrently on the same CPU, removing the spurious -EBUSY error. bpf_task_storage_get(..., F_CREATE) will now always succeed with enough free memory unless being called recursively. 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-7-ameryhung@gmail.com
1 parent 8dabe34 commit 4a98c2e

2 files changed

Lines changed: 18 additions & 136 deletions

File tree

kernel/bpf/bpf_task_storage.c

Lines changed: 18 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,6 @@
2020

2121
DEFINE_BPF_STORAGE_CACHE(task_cache);
2222

23-
static DEFINE_PER_CPU(int, bpf_task_storage_busy);
24-
25-
static void bpf_task_storage_lock(void)
26-
{
27-
cant_migrate();
28-
this_cpu_inc(bpf_task_storage_busy);
29-
}
30-
31-
static void bpf_task_storage_unlock(void)
32-
{
33-
this_cpu_dec(bpf_task_storage_busy);
34-
}
35-
36-
static bool bpf_task_storage_trylock(void)
37-
{
38-
cant_migrate();
39-
if (unlikely(this_cpu_inc_return(bpf_task_storage_busy) != 1)) {
40-
this_cpu_dec(bpf_task_storage_busy);
41-
return false;
42-
}
43-
return true;
44-
}
45-
4623
static struct bpf_local_storage __rcu **task_storage_ptr(void *owner)
4724
{
4825
struct task_struct *task = owner;
@@ -70,17 +47,15 @@ void bpf_task_storage_free(struct task_struct *task)
7047
{
7148
struct bpf_local_storage *local_storage;
7249

73-
rcu_read_lock_dont_migrate();
50+
rcu_read_lock();
7451

7552
local_storage = rcu_dereference(task->bpf_storage);
7653
if (!local_storage)
7754
goto out;
7855

79-
bpf_task_storage_lock();
8056
bpf_local_storage_destroy(local_storage);
81-
bpf_task_storage_unlock();
8257
out:
83-
rcu_read_unlock_migrate();
58+
rcu_read_unlock();
8459
}
8560

8661
static void *bpf_pid_task_storage_lookup_elem(struct bpf_map *map, void *key)
@@ -106,9 +81,7 @@ static void *bpf_pid_task_storage_lookup_elem(struct bpf_map *map, void *key)
10681
goto out;
10782
}
10883

109-
bpf_task_storage_lock();
11084
sdata = task_storage_lookup(task, map, true);
111-
bpf_task_storage_unlock();
11285
put_pid(pid);
11386
return sdata ? sdata->data : NULL;
11487
out:
@@ -143,30 +116,24 @@ static long bpf_pid_task_storage_update_elem(struct bpf_map *map, void *key,
143116
goto out;
144117
}
145118

146-
bpf_task_storage_lock();
147119
sdata = bpf_local_storage_update(
148120
task, (struct bpf_local_storage_map *)map, value, map_flags,
149121
true, GFP_ATOMIC);
150-
bpf_task_storage_unlock();
151122

152123
err = PTR_ERR_OR_ZERO(sdata);
153124
out:
154125
put_pid(pid);
155126
return err;
156127
}
157128

158-
static int task_storage_delete(struct task_struct *task, struct bpf_map *map,
159-
bool nobusy)
129+
static int task_storage_delete(struct task_struct *task, struct bpf_map *map)
160130
{
161131
struct bpf_local_storage_data *sdata;
162132

163133
sdata = task_storage_lookup(task, map, false);
164134
if (!sdata)
165135
return -ENOENT;
166136

167-
if (!nobusy)
168-
return -EBUSY;
169-
170137
return bpf_selem_unlink(SELEM(sdata), false);
171138
}
172139

@@ -192,111 +159,50 @@ static long bpf_pid_task_storage_delete_elem(struct bpf_map *map, void *key)
192159
goto out;
193160
}
194161

195-
bpf_task_storage_lock();
196-
err = task_storage_delete(task, map, true);
197-
bpf_task_storage_unlock();
162+
err = task_storage_delete(task, map);
198163
out:
199164
put_pid(pid);
200165
return err;
201166
}
202167

203-
/* Called by bpf_task_storage_get*() helpers */
204-
static void *__bpf_task_storage_get(struct bpf_map *map,
205-
struct task_struct *task, void *value,
206-
u64 flags, gfp_t gfp_flags, bool nobusy)
168+
/* *gfp_flags* is a hidden argument provided by the verifier */
169+
BPF_CALL_5(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
170+
task, void *, value, u64, flags, gfp_t, gfp_flags)
207171
{
208172
struct bpf_local_storage_data *sdata;
209173

210-
sdata = task_storage_lookup(task, map, nobusy);
174+
WARN_ON_ONCE(!bpf_rcu_lock_held());
175+
if (flags & ~BPF_LOCAL_STORAGE_GET_F_CREATE || !task)
176+
return (unsigned long)NULL;
177+
178+
sdata = task_storage_lookup(task, map, true);
211179
if (sdata)
212-
return sdata->data;
180+
return (unsigned long)sdata->data;
213181

214182
/* only allocate new storage, when the task is refcounted */
215183
if (refcount_read(&task->usage) &&
216-
(flags & BPF_LOCAL_STORAGE_GET_F_CREATE) && nobusy) {
184+
(flags & BPF_LOCAL_STORAGE_GET_F_CREATE)) {
217185
sdata = bpf_local_storage_update(
218186
task, (struct bpf_local_storage_map *)map, value,
219187
BPF_NOEXIST, false, gfp_flags);
220-
return IS_ERR(sdata) ? NULL : sdata->data;
188+
return IS_ERR(sdata) ? (unsigned long)NULL : (unsigned long)sdata->data;
221189
}
222190

223-
return NULL;
224-
}
225-
226-
/* *gfp_flags* is a hidden argument provided by the verifier */
227-
BPF_CALL_5(bpf_task_storage_get_recur, struct bpf_map *, map, struct task_struct *,
228-
task, void *, value, u64, flags, gfp_t, gfp_flags)
229-
{
230-
bool nobusy;
231-
void *data;
232-
233-
WARN_ON_ONCE(!bpf_rcu_lock_held());
234-
if (flags & ~BPF_LOCAL_STORAGE_GET_F_CREATE || !task)
235-
return (unsigned long)NULL;
236-
237-
nobusy = bpf_task_storage_trylock();
238-
data = __bpf_task_storage_get(map, task, value, flags,
239-
gfp_flags, nobusy);
240-
if (nobusy)
241-
bpf_task_storage_unlock();
242-
return (unsigned long)data;
243-
}
244-
245-
/* *gfp_flags* is a hidden argument provided by the verifier */
246-
BPF_CALL_5(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
247-
task, void *, value, u64, flags, gfp_t, gfp_flags)
248-
{
249-
void *data;
250-
251-
WARN_ON_ONCE(!bpf_rcu_lock_held());
252-
if (flags & ~BPF_LOCAL_STORAGE_GET_F_CREATE || !task)
253-
return (unsigned long)NULL;
254-
255-
bpf_task_storage_lock();
256-
data = __bpf_task_storage_get(map, task, value, flags,
257-
gfp_flags, true);
258-
bpf_task_storage_unlock();
259-
return (unsigned long)data;
260-
}
261-
262-
BPF_CALL_2(bpf_task_storage_delete_recur, struct bpf_map *, map, struct task_struct *,
263-
task)
264-
{
265-
bool nobusy;
266-
int ret;
267-
268-
WARN_ON_ONCE(!bpf_rcu_lock_held());
269-
if (!task)
270-
return -EINVAL;
271-
272-
nobusy = bpf_task_storage_trylock();
273-
/* This helper must only be called from places where the lifetime of the task
274-
* is guaranteed. Either by being refcounted or by being protected
275-
* by an RCU read-side critical section.
276-
*/
277-
ret = task_storage_delete(task, map, nobusy);
278-
if (nobusy)
279-
bpf_task_storage_unlock();
280-
return ret;
191+
return (unsigned long)NULL;
281192
}
282193

283194
BPF_CALL_2(bpf_task_storage_delete, struct bpf_map *, map, struct task_struct *,
284195
task)
285196
{
286-
int ret;
287-
288197
WARN_ON_ONCE(!bpf_rcu_lock_held());
289198
if (!task)
290199
return -EINVAL;
291200

292-
bpf_task_storage_lock();
293201
/* This helper must only be called from places where the lifetime of the task
294202
* is guaranteed. Either by being refcounted or by being protected
295203
* by an RCU read-side critical section.
296204
*/
297-
ret = task_storage_delete(task, map, true);
298-
bpf_task_storage_unlock();
299-
return ret;
205+
return task_storage_delete(task, map);
300206
}
301207

302208
static int notsupp_get_next_key(struct bpf_map *map, void *key, void *next_key)
@@ -311,7 +217,7 @@ static struct bpf_map *task_storage_map_alloc(union bpf_attr *attr)
311217

312218
static void task_storage_map_free(struct bpf_map *map)
313219
{
314-
bpf_local_storage_map_free(map, &task_cache, &bpf_task_storage_busy);
220+
bpf_local_storage_map_free(map, &task_cache, NULL);
315221
}
316222

317223
BTF_ID_LIST_GLOBAL_SINGLE(bpf_local_storage_map_btf_id, struct, bpf_local_storage_map)
@@ -330,17 +236,6 @@ const struct bpf_map_ops task_storage_map_ops = {
330236
.map_owner_storage_ptr = task_storage_ptr,
331237
};
332238

333-
const struct bpf_func_proto bpf_task_storage_get_recur_proto = {
334-
.func = bpf_task_storage_get_recur,
335-
.gpl_only = false,
336-
.ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL,
337-
.arg1_type = ARG_CONST_MAP_PTR,
338-
.arg2_type = ARG_PTR_TO_BTF_ID_OR_NULL,
339-
.arg2_btf_id = &btf_tracing_ids[BTF_TRACING_TYPE_TASK],
340-
.arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL,
341-
.arg4_type = ARG_ANYTHING,
342-
};
343-
344239
const struct bpf_func_proto bpf_task_storage_get_proto = {
345240
.func = bpf_task_storage_get,
346241
.gpl_only = false,
@@ -352,15 +247,6 @@ const struct bpf_func_proto bpf_task_storage_get_proto = {
352247
.arg4_type = ARG_ANYTHING,
353248
};
354249

355-
const struct bpf_func_proto bpf_task_storage_delete_recur_proto = {
356-
.func = bpf_task_storage_delete_recur,
357-
.gpl_only = false,
358-
.ret_type = RET_INTEGER,
359-
.arg1_type = ARG_CONST_MAP_PTR,
360-
.arg2_type = ARG_PTR_TO_BTF_ID_OR_NULL,
361-
.arg2_btf_id = &btf_tracing_ids[BTF_TRACING_TYPE_TASK],
362-
};
363-
364250
const struct bpf_func_proto bpf_task_storage_delete_proto = {
365251
.func = bpf_task_storage_delete,
366252
.gpl_only = false,

kernel/bpf/helpers.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,12 +2167,8 @@ bpf_base_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
21672167
return &bpf_get_cgroup_classid_curr_proto;
21682168
#endif
21692169
case BPF_FUNC_task_storage_get:
2170-
if (bpf_prog_check_recur(prog))
2171-
return &bpf_task_storage_get_recur_proto;
21722170
return &bpf_task_storage_get_proto;
21732171
case BPF_FUNC_task_storage_delete:
2174-
if (bpf_prog_check_recur(prog))
2175-
return &bpf_task_storage_delete_recur_proto;
21762172
return &bpf_task_storage_delete_proto;
21772173
default:
21782174
break;

0 commit comments

Comments
 (0)