@@ -129,6 +129,154 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
129
129
return map ;
130
130
}
131
131
132
+ static u32 bpf_map_value_size (struct bpf_map * map )
133
+ {
134
+ if (map -> map_type == BPF_MAP_TYPE_PERCPU_HASH ||
135
+ map -> map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
136
+ map -> map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
137
+ map -> map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE )
138
+ return round_up (map -> value_size , 8 ) * num_possible_cpus ();
139
+ else if (IS_FD_MAP (map ))
140
+ return sizeof (u32 );
141
+ else
142
+ return map -> value_size ;
143
+ }
144
+
145
+ static void maybe_wait_bpf_programs (struct bpf_map * map )
146
+ {
147
+ /* Wait for any running BPF programs to complete so that
148
+ * userspace, when we return to it, knows that all programs
149
+ * that could be running use the new map value.
150
+ */
151
+ if (map -> map_type == BPF_MAP_TYPE_HASH_OF_MAPS ||
152
+ map -> map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS )
153
+ synchronize_rcu ();
154
+ }
155
+
156
+ static int bpf_map_update_value (struct bpf_map * map , struct fd f , void * key ,
157
+ void * value , __u64 flags )
158
+ {
159
+ int err ;
160
+
161
+ /* Need to create a kthread, thus must support schedule */
162
+ if (bpf_map_is_dev_bound (map )) {
163
+ return bpf_map_offload_update_elem (map , key , value , flags );
164
+ } else if (map -> map_type == BPF_MAP_TYPE_CPUMAP ||
165
+ map -> map_type == BPF_MAP_TYPE_SOCKHASH ||
166
+ map -> map_type == BPF_MAP_TYPE_SOCKMAP ||
167
+ map -> map_type == BPF_MAP_TYPE_STRUCT_OPS ) {
168
+ return map -> ops -> map_update_elem (map , key , value , flags );
169
+ } else if (IS_FD_PROG_ARRAY (map )) {
170
+ return bpf_fd_array_map_update_elem (map , f .file , key , value ,
171
+ flags );
172
+ }
173
+
174
+ /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
175
+ * inside bpf map update or delete otherwise deadlocks are possible
176
+ */
177
+ preempt_disable ();
178
+ __this_cpu_inc (bpf_prog_active );
179
+ if (map -> map_type == BPF_MAP_TYPE_PERCPU_HASH ||
180
+ map -> map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ) {
181
+ err = bpf_percpu_hash_update (map , key , value , flags );
182
+ } else if (map -> map_type == BPF_MAP_TYPE_PERCPU_ARRAY ) {
183
+ err = bpf_percpu_array_update (map , key , value , flags );
184
+ } else if (map -> map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE ) {
185
+ err = bpf_percpu_cgroup_storage_update (map , key , value ,
186
+ flags );
187
+ } else if (IS_FD_ARRAY (map )) {
188
+ rcu_read_lock ();
189
+ err = bpf_fd_array_map_update_elem (map , f .file , key , value ,
190
+ flags );
191
+ rcu_read_unlock ();
192
+ } else if (map -> map_type == BPF_MAP_TYPE_HASH_OF_MAPS ) {
193
+ rcu_read_lock ();
194
+ err = bpf_fd_htab_map_update_elem (map , f .file , key , value ,
195
+ flags );
196
+ rcu_read_unlock ();
197
+ } else if (map -> map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY ) {
198
+ /* rcu_read_lock() is not needed */
199
+ err = bpf_fd_reuseport_array_update_elem (map , key , value ,
200
+ flags );
201
+ } else if (map -> map_type == BPF_MAP_TYPE_QUEUE ||
202
+ map -> map_type == BPF_MAP_TYPE_STACK ) {
203
+ err = map -> ops -> map_push_elem (map , value , flags );
204
+ } else {
205
+ rcu_read_lock ();
206
+ err = map -> ops -> map_update_elem (map , key , value , flags );
207
+ rcu_read_unlock ();
208
+ }
209
+ __this_cpu_dec (bpf_prog_active );
210
+ preempt_enable ();
211
+ maybe_wait_bpf_programs (map );
212
+
213
+ return err ;
214
+ }
215
+
216
+ static int bpf_map_copy_value (struct bpf_map * map , void * key , void * value ,
217
+ __u64 flags )
218
+ {
219
+ void * ptr ;
220
+ int err ;
221
+
222
+ if (bpf_map_is_dev_bound (map )) {
223
+ err = bpf_map_offload_lookup_elem (map , key , value );
224
+ return err ;
225
+ }
226
+
227
+ preempt_disable ();
228
+ this_cpu_inc (bpf_prog_active );
229
+ if (map -> map_type == BPF_MAP_TYPE_PERCPU_HASH ||
230
+ map -> map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ) {
231
+ err = bpf_percpu_hash_copy (map , key , value );
232
+ } else if (map -> map_type == BPF_MAP_TYPE_PERCPU_ARRAY ) {
233
+ err = bpf_percpu_array_copy (map , key , value );
234
+ } else if (map -> map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE ) {
235
+ err = bpf_percpu_cgroup_storage_copy (map , key , value );
236
+ } else if (map -> map_type == BPF_MAP_TYPE_STACK_TRACE ) {
237
+ err = bpf_stackmap_copy (map , key , value );
238
+ } else if (IS_FD_ARRAY (map ) || IS_FD_PROG_ARRAY (map )) {
239
+ err = bpf_fd_array_map_lookup_elem (map , key , value );
240
+ } else if (IS_FD_HASH (map )) {
241
+ err = bpf_fd_htab_map_lookup_elem (map , key , value );
242
+ } else if (map -> map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY ) {
243
+ err = bpf_fd_reuseport_array_lookup_elem (map , key , value );
244
+ } else if (map -> map_type == BPF_MAP_TYPE_QUEUE ||
245
+ map -> map_type == BPF_MAP_TYPE_STACK ) {
246
+ err = map -> ops -> map_peek_elem (map , value );
247
+ } else if (map -> map_type == BPF_MAP_TYPE_STRUCT_OPS ) {
248
+ /* struct_ops map requires directly updating "value" */
249
+ err = bpf_struct_ops_map_sys_lookup_elem (map , key , value );
250
+ } else {
251
+ rcu_read_lock ();
252
+ if (map -> ops -> map_lookup_elem_sys_only )
253
+ ptr = map -> ops -> map_lookup_elem_sys_only (map , key );
254
+ else
255
+ ptr = map -> ops -> map_lookup_elem (map , key );
256
+ if (IS_ERR (ptr )) {
257
+ err = PTR_ERR (ptr );
258
+ } else if (!ptr ) {
259
+ err = - ENOENT ;
260
+ } else {
261
+ err = 0 ;
262
+ if (flags & BPF_F_LOCK )
263
+ /* lock 'ptr' and copy everything but lock */
264
+ copy_map_value_locked (map , value , ptr , true);
265
+ else
266
+ copy_map_value (map , value , ptr );
267
+ /* mask lock, since value wasn't zero inited */
268
+ check_and_init_map_lock (map , value );
269
+ }
270
+ rcu_read_unlock ();
271
+ }
272
+
273
+ this_cpu_dec (bpf_prog_active );
274
+ preempt_enable ();
275
+ maybe_wait_bpf_programs (map );
276
+
277
+ return err ;
278
+ }
279
+
132
280
static void * __bpf_map_area_alloc (u64 size , int numa_node , bool mmapable )
133
281
{
134
282
/* We really just want to fail instead of triggering OOM killer
@@ -827,7 +975,7 @@ static int map_lookup_elem(union bpf_attr *attr)
827
975
void __user * uvalue = u64_to_user_ptr (attr -> value );
828
976
int ufd = attr -> map_fd ;
829
977
struct bpf_map * map ;
830
- void * key , * value , * ptr ;
978
+ void * key , * value ;
831
979
u32 value_size ;
832
980
struct fd f ;
833
981
int err ;
@@ -859,75 +1007,14 @@ static int map_lookup_elem(union bpf_attr *attr)
859
1007
goto err_put ;
860
1008
}
861
1009
862
- if (map -> map_type == BPF_MAP_TYPE_PERCPU_HASH ||
863
- map -> map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
864
- map -> map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
865
- map -> map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE )
866
- value_size = round_up (map -> value_size , 8 ) * num_possible_cpus ();
867
- else if (IS_FD_MAP (map ))
868
- value_size = sizeof (u32 );
869
- else
870
- value_size = map -> value_size ;
1010
+ value_size = bpf_map_value_size (map );
871
1011
872
1012
err = - ENOMEM ;
873
1013
value = kmalloc (value_size , GFP_USER | __GFP_NOWARN );
874
1014
if (!value )
875
1015
goto free_key ;
876
1016
877
- if (bpf_map_is_dev_bound (map )) {
878
- err = bpf_map_offload_lookup_elem (map , key , value );
879
- goto done ;
880
- }
881
-
882
- preempt_disable ();
883
- this_cpu_inc (bpf_prog_active );
884
- if (map -> map_type == BPF_MAP_TYPE_PERCPU_HASH ||
885
- map -> map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ) {
886
- err = bpf_percpu_hash_copy (map , key , value );
887
- } else if (map -> map_type == BPF_MAP_TYPE_PERCPU_ARRAY ) {
888
- err = bpf_percpu_array_copy (map , key , value );
889
- } else if (map -> map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE ) {
890
- err = bpf_percpu_cgroup_storage_copy (map , key , value );
891
- } else if (map -> map_type == BPF_MAP_TYPE_STACK_TRACE ) {
892
- err = bpf_stackmap_copy (map , key , value );
893
- } else if (IS_FD_ARRAY (map ) || IS_FD_PROG_ARRAY (map )) {
894
- err = bpf_fd_array_map_lookup_elem (map , key , value );
895
- } else if (IS_FD_HASH (map )) {
896
- err = bpf_fd_htab_map_lookup_elem (map , key , value );
897
- } else if (map -> map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY ) {
898
- err = bpf_fd_reuseport_array_lookup_elem (map , key , value );
899
- } else if (map -> map_type == BPF_MAP_TYPE_QUEUE ||
900
- map -> map_type == BPF_MAP_TYPE_STACK ) {
901
- err = map -> ops -> map_peek_elem (map , value );
902
- } else if (map -> map_type == BPF_MAP_TYPE_STRUCT_OPS ) {
903
- /* struct_ops map requires directly updating "value" */
904
- err = bpf_struct_ops_map_sys_lookup_elem (map , key , value );
905
- } else {
906
- rcu_read_lock ();
907
- if (map -> ops -> map_lookup_elem_sys_only )
908
- ptr = map -> ops -> map_lookup_elem_sys_only (map , key );
909
- else
910
- ptr = map -> ops -> map_lookup_elem (map , key );
911
- if (IS_ERR (ptr )) {
912
- err = PTR_ERR (ptr );
913
- } else if (!ptr ) {
914
- err = - ENOENT ;
915
- } else {
916
- err = 0 ;
917
- if (attr -> flags & BPF_F_LOCK )
918
- /* lock 'ptr' and copy everything but lock */
919
- copy_map_value_locked (map , value , ptr , true);
920
- else
921
- copy_map_value (map , value , ptr );
922
- /* mask lock, since value wasn't zero inited */
923
- check_and_init_map_lock (map , value );
924
- }
925
- rcu_read_unlock ();
926
- }
927
- this_cpu_dec (bpf_prog_active );
928
- preempt_enable ();
929
-
930
- done :
1017
+ err = bpf_map_copy_value (map , key , value , attr -> flags );
931
1018
if (err )
932
1019
goto free_value ;
933
1020
@@ -946,16 +1033,6 @@ static int map_lookup_elem(union bpf_attr *attr)
946
1033
return err ;
947
1034
}
948
1035
949
- static void maybe_wait_bpf_programs (struct bpf_map * map )
950
- {
951
- /* Wait for any running BPF programs to complete so that
952
- * userspace, when we return to it, knows that all programs
953
- * that could be running use the new map value.
954
- */
955
- if (map -> map_type == BPF_MAP_TYPE_HASH_OF_MAPS ||
956
- map -> map_type == BPF_MAP_TYPE_ARRAY_OF_MAPS )
957
- synchronize_rcu ();
958
- }
959
1036
960
1037
#define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
961
1038
@@ -1011,61 +1088,8 @@ static int map_update_elem(union bpf_attr *attr)
1011
1088
if (copy_from_user (value , uvalue , value_size ) != 0 )
1012
1089
goto free_value ;
1013
1090
1014
- /* Need to create a kthread, thus must support schedule */
1015
- if (bpf_map_is_dev_bound (map )) {
1016
- err = bpf_map_offload_update_elem (map , key , value , attr -> flags );
1017
- goto out ;
1018
- } else if (map -> map_type == BPF_MAP_TYPE_CPUMAP ||
1019
- map -> map_type == BPF_MAP_TYPE_SOCKHASH ||
1020
- map -> map_type == BPF_MAP_TYPE_SOCKMAP ||
1021
- map -> map_type == BPF_MAP_TYPE_STRUCT_OPS ) {
1022
- err = map -> ops -> map_update_elem (map , key , value , attr -> flags );
1023
- goto out ;
1024
- } else if (IS_FD_PROG_ARRAY (map )) {
1025
- err = bpf_fd_array_map_update_elem (map , f .file , key , value ,
1026
- attr -> flags );
1027
- goto out ;
1028
- }
1091
+ err = bpf_map_update_value (map , f , key , value , attr -> flags );
1029
1092
1030
- /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
1031
- * inside bpf map update or delete otherwise deadlocks are possible
1032
- */
1033
- preempt_disable ();
1034
- __this_cpu_inc (bpf_prog_active );
1035
- if (map -> map_type == BPF_MAP_TYPE_PERCPU_HASH ||
1036
- map -> map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ) {
1037
- err = bpf_percpu_hash_update (map , key , value , attr -> flags );
1038
- } else if (map -> map_type == BPF_MAP_TYPE_PERCPU_ARRAY ) {
1039
- err = bpf_percpu_array_update (map , key , value , attr -> flags );
1040
- } else if (map -> map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE ) {
1041
- err = bpf_percpu_cgroup_storage_update (map , key , value ,
1042
- attr -> flags );
1043
- } else if (IS_FD_ARRAY (map )) {
1044
- rcu_read_lock ();
1045
- err = bpf_fd_array_map_update_elem (map , f .file , key , value ,
1046
- attr -> flags );
1047
- rcu_read_unlock ();
1048
- } else if (map -> map_type == BPF_MAP_TYPE_HASH_OF_MAPS ) {
1049
- rcu_read_lock ();
1050
- err = bpf_fd_htab_map_update_elem (map , f .file , key , value ,
1051
- attr -> flags );
1052
- rcu_read_unlock ();
1053
- } else if (map -> map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY ) {
1054
- /* rcu_read_lock() is not needed */
1055
- err = bpf_fd_reuseport_array_update_elem (map , key , value ,
1056
- attr -> flags );
1057
- } else if (map -> map_type == BPF_MAP_TYPE_QUEUE ||
1058
- map -> map_type == BPF_MAP_TYPE_STACK ) {
1059
- err = map -> ops -> map_push_elem (map , value , attr -> flags );
1060
- } else {
1061
- rcu_read_lock ();
1062
- err = map -> ops -> map_update_elem (map , key , value , attr -> flags );
1063
- rcu_read_unlock ();
1064
- }
1065
- __this_cpu_dec (bpf_prog_active );
1066
- preempt_enable ();
1067
- maybe_wait_bpf_programs (map );
1068
- out :
1069
1093
free_value :
1070
1094
kfree (value );
1071
1095
free_key :
0 commit comments