BPF List
 help / color / mirror / Atom feed
From: Mykyta Yatsenko <mykyta.yatsenko5@gmail.com>
To: Eduard Zingerman <eddyz87@gmail.com>,
	bpf@vger.kernel.org, ast@kernel.org, andrii@kernel.org,
	daniel@iogearbox.net, kafai@meta.com, kernel-team@meta.com,
	memxor@gmail.com
Cc: Mykyta Yatsenko <yatsenko@meta.com>
Subject: Re: [PATCH bpf-next v3 4/7] bpf: bpf task work plumbing
Date: Mon, 15 Sep 2025 16:59:17 +0100	[thread overview]
Message-ID: <ac73378d-290c-4ab0-a604-6de693ce6c6f@gmail.com> (raw)
In-Reply-To: <c67790c49ae9ce4e1f34df324ab0b217ab867f03.camel@gmail.com>

On 9/6/25 00:09, Eduard Zingerman wrote:
> On Fri, 2025-09-05 at 17:45 +0100, Mykyta Yatsenko wrote:
>
> [...]
>
>> diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
>> index 3d080916faf9..4130d8e76dff 100644
>> --- a/kernel/bpf/arraymap.c
>> +++ b/kernel/bpf/arraymap.c
> [...]
>
>> @@ -439,12 +439,14 @@ static void array_map_free_timers_wq(struct bpf_map *map)
>>   	/* We don't reset or free fields other than timer and workqueue
>>   	 * on uref dropping to zero.
>>   	 */
>> -	if (btf_record_has_field(map->record, BPF_TIMER | BPF_WORKQUEUE)) {
>> +	if (btf_record_has_field(map->record, BPF_TIMER | BPF_WORKQUEUE | BPF_TASK_WORK)) {
> I think that hashtab.c:htab_free_internal_structs needs to be renamed
> and called here, thus avoiding code duplication.
Sorry for the delayed follow up on this, just was trying to do it. I'm 
not sure if it is possible
to reuse anything from hashtab in arraymap at the moment, there is no 
header file for hashtab.
If we are going to introduce a new file to facilitate code reuse between 
maps, maybe we should go for
map_intern_helpers.c/h or something like that. WDYT?
>
>>   		for (i = 0; i < array->map.max_entries; i++) {
>>   			if (btf_record_has_field(map->record, BPF_TIMER))
>>   				bpf_obj_free_timer(map->record, array_map_elem_ptr(array, i));
>>   			if (btf_record_has_field(map->record, BPF_WORKQUEUE))
>>   				bpf_obj_free_workqueue(map->record, array_map_elem_ptr(array, i));
>> +			if (btf_record_has_field(map->record, BPF_TASK_WORK))
>> +				bpf_obj_free_task_work(map->record, array_map_elem_ptr(array, i));
>>   		}
>>   	}
>>   }
> [...]
>
>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>> index a1a9bc589518..73ca21911b30 100644
>> --- a/kernel/bpf/btf.c
>> +++ b/kernel/bpf/btf.c
> [...]
>
>> @@ -4034,6 +4037,10 @@ struct btf_record *btf_parse_fields(const struct btf *btf, const struct btf_type
>>   		case BPF_LIST_NODE:
>>   		case BPF_RB_NODE:
>>   			break;
>> +		case BPF_TASK_WORK:
>> +			WARN_ON_ONCE(rec->task_work_off >= 0);
>> +			rec->task_work_off = rec->fields[i].offset;
>> +			break;
> Nit: let's move this case up to BPF_WORKQUEUE or BPF_REFCOUNT,
>       so that similar cases are grouped together.
>
>>   		default:
>>   			ret = -EFAULT;
>>   			goto end;
> [...]
>
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index 0fbfa8532c39..7da1ca893dfe 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
> [...]
>
>> @@ -840,6 +849,9 @@ void bpf_obj_free_fields(const struct btf_record *rec, void *obj)
>>   				continue;
>>   			bpf_rb_root_free(field, field_ptr, obj + rec->spin_lock_off);
>>   			break;
>> +		case BPF_TASK_WORK:
>> +			bpf_task_work_cancel_and_free(field_ptr);
>> +			break;
> Nit: same here, let's keep similar cases together.
>
>>   		case BPF_LIST_NODE:
>>   		case BPF_RB_NODE:
>>   		case BPF_REFCOUNT:
> [...]
>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index a5d19a01d488..6152536a834f 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
>> @@ -2240,6 +2240,8 @@ static void mark_ptr_not_null_reg(struct bpf_reg_state *reg)
>>   				reg->map_uid = reg->id;
>>   			if (btf_record_has_field(map->inner_map_meta->record, BPF_WORKQUEUE))
>>   				reg->map_uid = reg->id;
>> +			if (btf_record_has_field(map->inner_map_meta->record, BPF_TASK_WORK))
>> +				reg->map_uid = reg->id;
> Nit: this can be shorter:
>
> 			if (btf_record_has_field(map->inner_map_meta->record,
> 						 BPF_TIMER | BPF_WORKQUEUE | BPF_TASK_WORK))
> 				reg->map_uid = reg->id;
>
>
>>   		} else if (map->map_type == BPF_MAP_TYPE_XSKMAP) {
>>   			reg->type = PTR_TO_XDP_SOCK;
>>   		} else if (map->map_type == BPF_MAP_TYPE_SOCKMAP ||
> [...]
>
>> @@ -10943,6 +10956,35 @@ static int set_rbtree_add_callback_state(struct bpf_verifier_env *env,
>>   	return 0;
>>   }
>>   
>> +static int set_task_work_schedule_callback_state(struct bpf_verifier_env *env,
>> +						 struct bpf_func_state *caller,
>> +						 struct bpf_func_state *callee,
>> +						 int insn_idx)
>> +{
>> +	struct bpf_map *map_ptr = caller->regs[BPF_REG_3].map_ptr;
>> +
>> +	/*
>> +	 * callback_fn(struct bpf_map *map, void *key, void *value);
>> +	 */
>> +	callee->regs[BPF_REG_1].type = CONST_PTR_TO_MAP;
>> +	__mark_reg_known_zero(&callee->regs[BPF_REG_1]);
>> +	callee->regs[BPF_REG_1].map_ptr = map_ptr;
>> +
>> +	callee->regs[BPF_REG_2].type = PTR_TO_MAP_KEY;
>> +	__mark_reg_known_zero(&callee->regs[BPF_REG_2]);
>> +	callee->regs[BPF_REG_2].map_ptr = map_ptr;
>> +
>> +	callee->regs[BPF_REG_3].type = PTR_TO_MAP_VALUE;
>> +	__mark_reg_known_zero(&callee->regs[BPF_REG_3]);
>> +	callee->regs[BPF_REG_3].map_ptr = map_ptr;
>> +
>> +	/* unused */
>> +	__mark_reg_not_init(env, &callee->regs[BPF_REG_4]);
>> +	__mark_reg_not_init(env, &callee->regs[BPF_REG_5]);
>> +	callee->in_callback_fn = true;
> This should be `callee->in_async_callback_fn = true;` to avoid an
> infinite loop check in the is_state_visisted() in some cases.
>
>> +	return 0;
>> +}
>> +
>>   static bool is_rbtree_lock_required_kfunc(u32 btf_id);
>>   
>>   /* Are we currently verifying the callback for a rbtree helper that must
> [...]
>
>> @@ -13171,6 +13235,15 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
>>   					return -EINVAL;
>>   				}
>>   			}
>> +			if (meta->map.ptr && reg->map_ptr->record->task_work_off >= 0) {
>> +				if (meta->map.ptr != reg->map_ptr ||
>> +				    meta->map.uid != reg->map_uid) {
>> +					verbose(env,
>> +						"bpf_task_work pointer in R2 map_uid=%d doesn't match map pointer in R3 map_uid=%d\n",
>> +						meta->map.uid, reg->map_uid);
>> +					return -EINVAL;
>> +				}
>> +			}
> Please merge this with the case for wq_off above.
>
>>   			meta->map.ptr = reg->map_ptr;
>>   			meta->map.uid = reg->map_uid;
>>   			fallthrough;
> [...]


  reply	other threads:[~2025-09-15 15:59 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-05 16:44 [PATCH bpf-next v3 0/7] bpf: Introduce deferred task context execution Mykyta Yatsenko
2025-09-05 16:44 ` [PATCH bpf-next v3 1/7] bpf: refactor special field-type detection Mykyta Yatsenko
2025-09-05 19:36   ` Eduard Zingerman
2025-09-05 21:29   ` Andrii Nakryiko
2025-09-05 16:45 ` [PATCH bpf-next v3 2/7] bpf: extract generic helper from process_timer_func() Mykyta Yatsenko
2025-09-05 21:15   ` Eduard Zingerman
2025-09-05 21:28   ` Eduard Zingerman
2025-09-05 21:31     ` Andrii Nakryiko
2025-09-05 21:32       ` Eduard Zingerman
2025-09-05 21:29   ` Andrii Nakryiko
2025-09-05 16:45 ` [PATCH bpf-next v3 3/7] bpf: htab: extract helper for freeing special structs Mykyta Yatsenko
2025-09-05 21:31   ` Andrii Nakryiko
2025-09-05 21:31   ` Eduard Zingerman
2025-09-05 16:45 ` [PATCH bpf-next v3 4/7] bpf: bpf task work plumbing Mykyta Yatsenko
2025-09-05 21:31   ` Andrii Nakryiko
2025-09-05 23:09   ` Eduard Zingerman
2025-09-15 15:59     ` Mykyta Yatsenko [this message]
2025-09-15 20:12       ` Andrii Nakryiko
2025-09-15 20:20         ` Mykyta Yatsenko
2025-09-15 20:28           ` Andrii Nakryiko
2025-09-05 16:45 ` [PATCH bpf-next v3 5/7] bpf: extract map key pointer calculation Mykyta Yatsenko
2025-09-05 21:31   ` Andrii Nakryiko
2025-09-05 23:19   ` Eduard Zingerman
2025-09-08 13:39     ` Mykyta Yatsenko
2025-09-08 17:18       ` Eduard Zingerman
2025-09-05 16:45 ` [PATCH bpf-next v3 6/7] bpf: task work scheduling kfuncs Mykyta Yatsenko
2025-09-05 21:31   ` Andrii Nakryiko
2025-09-06 20:22   ` Eduard Zingerman
2025-09-08 13:13     ` Mykyta Yatsenko
2025-09-08 17:38       ` Eduard Zingerman
2025-09-09  3:42         ` Andrii Nakryiko
2025-09-09  4:15           ` Eduard Zingerman
2025-09-09  3:33       ` Andrii Nakryiko
2025-09-09  4:05         ` Eduard Zingerman
2025-09-10 14:14           ` Andrii Nakryiko
2025-09-09 17:49   ` Chris Mason
2025-09-09 18:59     ` Mykyta Yatsenko
2025-09-05 16:45 ` [PATCH bpf-next v3 7/7] selftests/bpf: BPF task work scheduling tests Mykyta Yatsenko
2025-09-05 21:31   ` Andrii Nakryiko
2025-09-08  7:43   ` Eduard Zingerman
2025-09-08 13:21     ` Mykyta Yatsenko
2025-09-08 18:23       ` Eduard Zingerman
2025-09-09  3:44         ` Andrii Nakryiko
2025-09-08 18:23   ` Eduard Zingerman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ac73378d-290c-4ab0-a604-6de693ce6c6f@gmail.com \
    --to=mykyta.yatsenko5@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=kafai@meta.com \
    --cc=kernel-team@meta.com \
    --cc=memxor@gmail.com \
    --cc=yatsenko@meta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox