Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'bpf-introduce-and-use-rcu_read_lock_dont_migrate'

Menglong Dong says:

====================
bpf: introduce and use rcu_read_lock_dont_migrate

migrate_disable() and rcu_read_lock() are used to together in many case in
bpf. However, when PREEMPT_RCU is not enabled, rcu_read_lock() will
disable preemption, which indicate migrate_disable(), so we don't need to
call it in this case.

In this series, we introduce rcu_read_lock_dont_migrate and
rcu_read_unlock_migrate, which will call migrate_disable and
migrate_enable only when PREEMPT_RCU enabled. And use
rcu_read_lock_dont_migrate in bpf subsystem.

Changes since V2:
* make rcu_read_lock_dont_migrate() more compatible by using IS_ENABLED()

Changes since V1:
* introduce rcu_read_lock_dont_migrate() instead of
rcu_migrate_disable() + rcu_read_lock()
====================

Link: https://patch.msgid.link/20250821090609.42508-1-dongml2@chinatelecom.cn
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+30 -32
+14
include/linux/rcupdate.h
··· 962 962 preempt_enable_notrace(); 963 963 } 964 964 965 + static __always_inline void rcu_read_lock_dont_migrate(void) 966 + { 967 + if (IS_ENABLED(CONFIG_PREEMPT_RCU)) 968 + migrate_disable(); 969 + rcu_read_lock(); 970 + } 971 + 972 + static inline void rcu_read_unlock_migrate(void) 973 + { 974 + rcu_read_unlock(); 975 + if (IS_ENABLED(CONFIG_PREEMPT_RCU)) 976 + migrate_enable(); 977 + } 978 + 965 979 /** 966 980 * RCU_INIT_POINTER() - initialize an RCU protected pointer 967 981 * @p: The pointer to be initialized.
+2 -4
kernel/bpf/bpf_cgrp_storage.c
··· 45 45 { 46 46 struct bpf_local_storage *local_storage; 47 47 48 - migrate_disable(); 49 - rcu_read_lock(); 48 + rcu_read_lock_dont_migrate(); 50 49 local_storage = rcu_dereference(cgroup->bpf_cgrp_storage); 51 50 if (!local_storage) 52 51 goto out; ··· 54 55 bpf_local_storage_destroy(local_storage); 55 56 bpf_cgrp_storage_unlock(); 56 57 out: 57 - rcu_read_unlock(); 58 - migrate_enable(); 58 + rcu_read_unlock_migrate(); 59 59 } 60 60 61 61 static struct bpf_local_storage_data *
+2 -4
kernel/bpf/bpf_inode_storage.c
··· 62 62 if (!bsb) 63 63 return; 64 64 65 - migrate_disable(); 66 - rcu_read_lock(); 65 + rcu_read_lock_dont_migrate(); 67 66 68 67 local_storage = rcu_dereference(bsb->storage); 69 68 if (!local_storage) ··· 70 71 71 72 bpf_local_storage_destroy(local_storage); 72 73 out: 73 - rcu_read_unlock(); 74 - migrate_enable(); 74 + rcu_read_unlock_migrate(); 75 75 } 76 76 77 77 static void *bpf_fd_inode_storage_lookup_elem(struct bpf_map *map, void *key)
+2 -4
kernel/bpf/bpf_iter.c
··· 705 705 migrate_enable(); 706 706 rcu_read_unlock_trace(); 707 707 } else { 708 - rcu_read_lock(); 709 - migrate_disable(); 708 + rcu_read_lock_dont_migrate(); 710 709 old_run_ctx = bpf_set_run_ctx(&run_ctx); 711 710 ret = bpf_prog_run(prog, ctx); 712 711 bpf_reset_run_ctx(old_run_ctx); 713 - migrate_enable(); 714 - rcu_read_unlock(); 712 + rcu_read_unlock_migrate(); 715 713 } 716 714 717 715 /* bpf program can only return 0 or 1:
+2 -4
kernel/bpf/bpf_task_storage.c
··· 70 70 { 71 71 struct bpf_local_storage *local_storage; 72 72 73 - migrate_disable(); 74 - rcu_read_lock(); 73 + rcu_read_lock_dont_migrate(); 75 74 76 75 local_storage = rcu_dereference(task->bpf_storage); 77 76 if (!local_storage) ··· 80 81 bpf_local_storage_destroy(local_storage); 81 82 bpf_task_storage_unlock(); 82 83 out: 83 - rcu_read_unlock(); 84 - migrate_enable(); 84 + rcu_read_unlock_migrate(); 85 85 } 86 86 87 87 static void *bpf_pid_task_storage_lookup_elem(struct bpf_map *map, void *key)
+2 -4
kernel/bpf/cgroup.c
··· 71 71 u32 func_ret; 72 72 73 73 run_ctx.retval = retval; 74 - migrate_disable(); 75 - rcu_read_lock(); 74 + rcu_read_lock_dont_migrate(); 76 75 array = rcu_dereference(cgrp->effective[atype]); 77 76 item = &array->items[0]; 78 77 old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx); ··· 87 88 item++; 88 89 } 89 90 bpf_reset_run_ctx(old_run_ctx); 90 - rcu_read_unlock(); 91 - migrate_enable(); 91 + rcu_read_unlock_migrate(); 92 92 return run_ctx.retval; 93 93 } 94 94
+6 -12
kernel/bpf/trampoline.c
··· 899 899 static u64 notrace __bpf_prog_enter_recur(struct bpf_prog *prog, struct bpf_tramp_run_ctx *run_ctx) 900 900 __acquires(RCU) 901 901 { 902 - rcu_read_lock(); 903 - migrate_disable(); 902 + rcu_read_lock_dont_migrate(); 904 903 905 904 run_ctx->saved_run_ctx = bpf_set_run_ctx(&run_ctx->run_ctx); 906 905 ··· 948 949 949 950 update_prog_stats(prog, start); 950 951 this_cpu_dec(*(prog->active)); 951 - migrate_enable(); 952 - rcu_read_unlock(); 952 + rcu_read_unlock_migrate(); 953 953 } 954 954 955 955 static u64 notrace __bpf_prog_enter_lsm_cgroup(struct bpf_prog *prog, ··· 958 960 /* Runtime stats are exported via actual BPF_LSM_CGROUP 959 961 * programs, not the shims. 960 962 */ 961 - rcu_read_lock(); 962 - migrate_disable(); 963 + rcu_read_lock_dont_migrate(); 963 964 964 965 run_ctx->saved_run_ctx = bpf_set_run_ctx(&run_ctx->run_ctx); 965 966 ··· 971 974 { 972 975 bpf_reset_run_ctx(run_ctx->saved_run_ctx); 973 976 974 - migrate_enable(); 975 - rcu_read_unlock(); 977 + rcu_read_unlock_migrate(); 976 978 } 977 979 978 980 u64 notrace __bpf_prog_enter_sleepable_recur(struct bpf_prog *prog, ··· 1029 1033 struct bpf_tramp_run_ctx *run_ctx) 1030 1034 __acquires(RCU) 1031 1035 { 1032 - rcu_read_lock(); 1033 - migrate_disable(); 1036 + rcu_read_lock_dont_migrate(); 1034 1037 1035 1038 run_ctx->saved_run_ctx = bpf_set_run_ctx(&run_ctx->run_ctx); 1036 1039 ··· 1043 1048 bpf_reset_run_ctx(run_ctx->saved_run_ctx); 1044 1049 1045 1050 update_prog_stats(prog, start); 1046 - migrate_enable(); 1047 - rcu_read_unlock(); 1051 + rcu_read_unlock_migrate(); 1048 1052 } 1049 1053 1050 1054 void notrace __bpf_tramp_enter(struct bpf_tramp_image *tr)