summaryrefslogtreecommitdiffstats
path: root/kernel/bpf/map_in_map.c
diff options
context:
space:
mode:
authorHou Tao <houtao1@huawei.com>2023-12-04 22:04:23 +0800
committerAlexei Starovoitov <ast@kernel.org>2023-12-04 17:50:26 -0800
commitaf66bfd3c8538ed21cf72af18426fc4a408665cf (patch)
tree3171b12b303ea941f111d3f6769257e44fc08104 /kernel/bpf/map_in_map.c
parent876673364161da50eed6b472d746ef88242b2368 (diff)
downloadlinux-stable-af66bfd3c8538ed21cf72af18426fc4a408665cf.tar.gz
linux-stable-af66bfd3c8538ed21cf72af18426fc4a408665cf.tar.bz2
linux-stable-af66bfd3c8538ed21cf72af18426fc4a408665cf.zip
bpf: Optimize the free of inner map
When removing the inner map from the outer map, the inner map will be freed after one RCU grace period and one RCU tasks trace grace period, so it is certain that the bpf program, which may access the inner map, has exited before the inner map is freed. However there is no need to wait for one RCU tasks trace grace period if the outer map is only accessed by non-sleepable program. So adding sleepable_refcnt in bpf_map and increasing sleepable_refcnt when adding the outer map into env->used_maps for sleepable program. Although the max number of bpf program is INT_MAX - 1, the number of bpf programs which are being loaded may be greater than INT_MAX, so using atomic64_t instead of atomic_t for sleepable_refcnt. When removing the inner map from the outer map, using sleepable_refcnt to decide whether or not a RCU tasks trace grace period is needed before freeing the inner map. Signed-off-by: Hou Tao <houtao1@huawei.com> Link: https://lore.kernel.org/r/20231204140425.1480317-6-houtao@huaweicloud.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel/bpf/map_in_map.c')
-rw-r--r--kernel/bpf/map_in_map.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/kernel/bpf/map_in_map.c b/kernel/bpf/map_in_map.c
index 3248ff5d8161..8ef269e66ba5 100644
--- a/kernel/bpf/map_in_map.c
+++ b/kernel/bpf/map_in_map.c
@@ -131,12 +131,16 @@ void bpf_map_fd_put_ptr(struct bpf_map *map, void *ptr, bool need_defer)
{
struct bpf_map *inner_map = ptr;
- /* The inner map may still be used by both non-sleepable and sleepable
- * bpf program, so free it after one RCU grace period and one tasks
- * trace RCU grace period.
+ /* Defer the freeing of inner map according to the sleepable attribute
+ * of bpf program which owns the outer map, so unnecessary waiting for
+ * RCU tasks trace grace period can be avoided.
*/
- if (need_defer)
- WRITE_ONCE(inner_map->free_after_mult_rcu_gp, true);
+ if (need_defer) {
+ if (atomic64_read(&map->sleepable_refcnt))
+ WRITE_ONCE(inner_map->free_after_mult_rcu_gp, true);
+ else
+ WRITE_ONCE(inner_map->free_after_rcu_gp, true);
+ }
bpf_map_put(inner_map);
}