bpf: bpf_task_storage_delete_recur does lookup first before the deadlock check
Similar to the earlier change in bpf_task_storage_get_recur. This patch changes bpf_task_storage_delete_recur such that it does the lookup first. It only returns -EBUSY if it needs to take the spinlock to do the deletion when potential deadlock is detected. Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org> Link: https://lore.kernel.org/r/20221025184524.3526117-7-martin.lau@linux.dev Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
4279adb094
commit
fda64ae0bb
1 changed files with 11 additions and 7 deletions
|
@ -184,7 +184,8 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int task_storage_delete(struct task_struct *task, struct bpf_map *map)
|
static int task_storage_delete(struct task_struct *task, struct bpf_map *map,
|
||||||
|
bool nobusy)
|
||||||
{
|
{
|
||||||
struct bpf_local_storage_data *sdata;
|
struct bpf_local_storage_data *sdata;
|
||||||
|
|
||||||
|
@ -192,6 +193,9 @@ static int task_storage_delete(struct task_struct *task, struct bpf_map *map)
|
||||||
if (!sdata)
|
if (!sdata)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
if (!nobusy)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
bpf_selem_unlink(SELEM(sdata), true);
|
bpf_selem_unlink(SELEM(sdata), true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -220,7 +224,7 @@ static int bpf_pid_task_storage_delete_elem(struct bpf_map *map, void *key)
|
||||||
}
|
}
|
||||||
|
|
||||||
bpf_task_storage_lock();
|
bpf_task_storage_lock();
|
||||||
err = task_storage_delete(task, map);
|
err = task_storage_delete(task, map, true);
|
||||||
bpf_task_storage_unlock();
|
bpf_task_storage_unlock();
|
||||||
out:
|
out:
|
||||||
put_pid(pid);
|
put_pid(pid);
|
||||||
|
@ -289,21 +293,21 @@ BPF_CALL_5(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
|
||||||
BPF_CALL_2(bpf_task_storage_delete_recur, struct bpf_map *, map, struct task_struct *,
|
BPF_CALL_2(bpf_task_storage_delete_recur, struct bpf_map *, map, struct task_struct *,
|
||||||
task)
|
task)
|
||||||
{
|
{
|
||||||
|
bool nobusy;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
WARN_ON_ONCE(!bpf_rcu_lock_held());
|
WARN_ON_ONCE(!bpf_rcu_lock_held());
|
||||||
if (!task)
|
if (!task)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!bpf_task_storage_trylock())
|
nobusy = bpf_task_storage_trylock();
|
||||||
return -EBUSY;
|
|
||||||
|
|
||||||
/* This helper must only be called from places where the lifetime of the task
|
/* This helper must only be called from places where the lifetime of the task
|
||||||
* is guaranteed. Either by being refcounted or by being protected
|
* is guaranteed. Either by being refcounted or by being protected
|
||||||
* by an RCU read-side critical section.
|
* by an RCU read-side critical section.
|
||||||
*/
|
*/
|
||||||
ret = task_storage_delete(task, map);
|
ret = task_storage_delete(task, map, nobusy);
|
||||||
bpf_task_storage_unlock();
|
if (nobusy)
|
||||||
|
bpf_task_storage_unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue