On Mon, Apr 8, 2024 at 3:36 PM Eduard Zingerman <eddyz87@xxxxxxxxx> wrote: > > On Mon, 2024-04-08 at 10:09 +0200, Benjamin Tissoires wrote: > > Now that we have bpf_timer_set_sleepable_cb() available and working, we > > can tag the attached callback as sleepable, and let the verifier check > > in the correct context the calls and kfuncs. > > > > Signed-off-by: Benjamin Tissoires <bentiss@xxxxxxxxxx> > > > > --- > > I think this patch is fine with one nit regarding in_sleepable(). > Acked-by: Eduard Zingerman <eddyz87@xxxxxxxxx> > > > @@ -5279,7 +5281,8 @@ static int map_kptr_match_type(struct bpf_verifier_env *env, > > > > static bool in_sleepable(struct bpf_verifier_env *env) > > { > > - return env->prog->sleepable; > > + return env->prog->sleepable || > > + (env->cur_state && env->cur_state->in_sleepable); > > } > > Sorry, I already raised this before. > As far as I understand the 'env->cur_state' check is needed because > this function is used from do_misc_fixups(): > > if (is_storage_get_function(insn->imm)) { > if (!in_sleepable(env) || > env->insn_aux_data[i + delta].storage_get_func_atomic) > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_ATOMIC); > else > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_5, (__force __s32)GFP_KERNEL); > insn_buf[1] = *insn; > cnt = 2; > ... > } > > For a timer callback function 'env->prog->sleepable' would be false. > Which means that inside sleepable callback function GFP_ATOMIC would > be used in cases where GFP_KERNEL would be sufficient. > An alternative would be to check (and set) sleepable flag not for a > full program but for a subprogram. At this point all subprograms are still part of the main program. jit_subprogs() hasn't been called yet. So there is only one 'prog' object. So cannot really set prog->sleepable for callback subprog. But you've raised a good point. We can remove "!in_sleepable(env)" part in do_misc_fixups() with: - if (in_sleepable(env) && is_storage_get_function(func_id)) - env->insn_aux_data[insn_idx].storage_get_func_atomic = true; + if (is_storage_get_function(func_id)) + env->insn_aux_data[insn_idx].storage_get_func_atomic = !in_sleepable(env);