@@ -184,14 +184,18 @@ static int bpf_pid_task_storage_update_elem(struct bpf_map *map, void *key,
184184 return err ;
185185}
186186
187- static int task_storage_delete (struct task_struct * task , struct bpf_map * map )
187+ static int task_storage_delete (struct task_struct * task , struct bpf_map * map ,
188+ bool nobusy )
188189{
189190 struct bpf_local_storage_data * sdata ;
190191
191192 sdata = task_storage_lookup (task , map , false);
192193 if (!sdata )
193194 return - ENOENT ;
194195
196+ if (!nobusy )
197+ return - EBUSY ;
198+
195199 bpf_selem_unlink (SELEM (sdata ), true);
196200
197201 return 0 ;
@@ -220,63 +224,108 @@ static int bpf_pid_task_storage_delete_elem(struct bpf_map *map, void *key)
220224 }
221225
222226 bpf_task_storage_lock ();
223- err = task_storage_delete (task , map );
227+ err = task_storage_delete (task , map , true );
224228 bpf_task_storage_unlock ();
225229out :
226230 put_pid (pid );
227231 return err ;
228232}
229233
230- /* *gfp_flags* is a hidden argument provided by the verifier */
231- BPF_CALL_5 (bpf_task_storage_get , struct bpf_map * , map , struct task_struct * ,
232- task , void * , value , u64 , flags , gfp_t , gfp_flags )
234+ /* Called by bpf_task_storage_get*() helpers */
235+ static void * __bpf_task_storage_get (struct bpf_map * map ,
236+ struct task_struct * task , void * value ,
237+ u64 flags , gfp_t gfp_flags , bool nobusy )
233238{
234239 struct bpf_local_storage_data * sdata ;
235240
236- WARN_ON_ONCE (!bpf_rcu_lock_held ());
237- if (flags & ~(BPF_LOCAL_STORAGE_GET_F_CREATE ))
238- return (unsigned long )NULL ;
239-
240- if (!task )
241- return (unsigned long )NULL ;
242-
243- if (!bpf_task_storage_trylock ())
244- return (unsigned long )NULL ;
245-
246- sdata = task_storage_lookup (task , map , true);
241+ sdata = task_storage_lookup (task , map , nobusy );
247242 if (sdata )
248- goto unlock ;
243+ return sdata -> data ;
249244
250245 /* only allocate new storage, when the task is refcounted */
251246 if (refcount_read (& task -> usage ) &&
252- (flags & BPF_LOCAL_STORAGE_GET_F_CREATE ))
247+ (flags & BPF_LOCAL_STORAGE_GET_F_CREATE ) && nobusy ) {
253248 sdata = bpf_local_storage_update (
254249 task , (struct bpf_local_storage_map * )map , value ,
255250 BPF_NOEXIST , gfp_flags );
251+ return IS_ERR (sdata ) ? NULL : sdata -> data ;
252+ }
253+
254+ return NULL ;
255+ }
256256
257- unlock :
257+ /* *gfp_flags* is a hidden argument provided by the verifier */
258+ BPF_CALL_5 (bpf_task_storage_get_recur , struct bpf_map * , map , struct task_struct * ,
259+ task , void * , value , u64 , flags , gfp_t , gfp_flags )
260+ {
261+ bool nobusy ;
262+ void * data ;
263+
264+ WARN_ON_ONCE (!bpf_rcu_lock_held ());
265+ if (flags & ~BPF_LOCAL_STORAGE_GET_F_CREATE || !task )
266+ return (unsigned long )NULL ;
267+
268+ nobusy = bpf_task_storage_trylock ();
269+ data = __bpf_task_storage_get (map , task , value , flags ,
270+ gfp_flags , nobusy );
271+ if (nobusy )
272+ bpf_task_storage_unlock ();
273+ return (unsigned long )data ;
274+ }
275+
276+ /* *gfp_flags* is a hidden argument provided by the verifier */
277+ BPF_CALL_5 (bpf_task_storage_get , struct bpf_map * , map , struct task_struct * ,
278+ task , void * , value , u64 , flags , gfp_t , gfp_flags )
279+ {
280+ void * data ;
281+
282+ WARN_ON_ONCE (!bpf_rcu_lock_held ());
283+ if (flags & ~BPF_LOCAL_STORAGE_GET_F_CREATE || !task )
284+ return (unsigned long )NULL ;
285+
286+ bpf_task_storage_lock ();
287+ data = __bpf_task_storage_get (map , task , value , flags ,
288+ gfp_flags , true);
258289 bpf_task_storage_unlock ();
259- return IS_ERR_OR_NULL (sdata ) ? (unsigned long )NULL :
260- (unsigned long )sdata -> data ;
290+ return (unsigned long )data ;
261291}
262292
263- BPF_CALL_2 (bpf_task_storage_delete , struct bpf_map * , map , struct task_struct * ,
293+ BPF_CALL_2 (bpf_task_storage_delete_recur , struct bpf_map * , map , struct task_struct * ,
264294 task )
265295{
296+ bool nobusy ;
266297 int ret ;
267298
268299 WARN_ON_ONCE (!bpf_rcu_lock_held ());
269300 if (!task )
270301 return - EINVAL ;
271302
272- if (!bpf_task_storage_trylock ())
273- return - EBUSY ;
303+ nobusy = bpf_task_storage_trylock ();
304+ /* This helper must only be called from places where the lifetime of the task
305+ * is guaranteed. Either by being refcounted or by being protected
306+ * by an RCU read-side critical section.
307+ */
308+ ret = task_storage_delete (task , map , nobusy );
309+ if (nobusy )
310+ bpf_task_storage_unlock ();
311+ return ret ;
312+ }
313+
314+ BPF_CALL_2 (bpf_task_storage_delete , struct bpf_map * , map , struct task_struct * ,
315+ task )
316+ {
317+ int ret ;
318+
319+ WARN_ON_ONCE (!bpf_rcu_lock_held ());
320+ if (!task )
321+ return - EINVAL ;
274322
323+ bpf_task_storage_lock ();
275324 /* This helper must only be called from places where the lifetime of the task
276325 * is guaranteed. Either by being refcounted or by being protected
277326 * by an RCU read-side critical section.
278327 */
279- ret = task_storage_delete (task , map );
328+ ret = task_storage_delete (task , map , true );
280329 bpf_task_storage_unlock ();
281330 return ret ;
282331}
@@ -322,6 +371,17 @@ const struct bpf_map_ops task_storage_map_ops = {
322371 .map_owner_storage_ptr = task_storage_ptr ,
323372};
324373
374+ const struct bpf_func_proto bpf_task_storage_get_recur_proto = {
375+ .func = bpf_task_storage_get_recur ,
376+ .gpl_only = false,
377+ .ret_type = RET_PTR_TO_MAP_VALUE_OR_NULL ,
378+ .arg1_type = ARG_CONST_MAP_PTR ,
379+ .arg2_type = ARG_PTR_TO_BTF_ID ,
380+ .arg2_btf_id = & btf_tracing_ids [BTF_TRACING_TYPE_TASK ],
381+ .arg3_type = ARG_PTR_TO_MAP_VALUE_OR_NULL ,
382+ .arg4_type = ARG_ANYTHING ,
383+ };
384+
325385const struct bpf_func_proto bpf_task_storage_get_proto = {
326386 .func = bpf_task_storage_get ,
327387 .gpl_only = false,
@@ -333,6 +393,15 @@ const struct bpf_func_proto bpf_task_storage_get_proto = {
333393 .arg4_type = ARG_ANYTHING ,
334394};
335395
396+ const struct bpf_func_proto bpf_task_storage_delete_recur_proto = {
397+ .func = bpf_task_storage_delete_recur ,
398+ .gpl_only = false,
399+ .ret_type = RET_INTEGER ,
400+ .arg1_type = ARG_CONST_MAP_PTR ,
401+ .arg2_type = ARG_PTR_TO_BTF_ID ,
402+ .arg2_btf_id = & btf_tracing_ids [BTF_TRACING_TYPE_TASK ],
403+ };
404+
336405const struct bpf_func_proto bpf_task_storage_delete_proto = {
337406 .func = bpf_task_storage_delete ,
338407 .gpl_only = false,
0 commit comments