On Tue, Jul 1, 2025 at 11:17 PM Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> wrote: > > Refactor code to be able to get and put bprintf buffers and use > bpf_printf_prepare independently. This will be used in the next patch to > implement BPF streams support, particularly as a staging buffer for > strings that need to be formatted and then allocated and pushed into a > stream. > > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> > --- > include/linux/bpf.h | 15 ++++++++++++++- > kernel/bpf/helpers.c | 26 +++++++++++--------------- > 2 files changed, 25 insertions(+), 16 deletions(-) > Reviewed-by: Emil Tsalapatis <emil@xxxxxxxxxxxxxxx> > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index 5dd556e89cce..4fff0cee8622 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -3550,6 +3550,16 @@ bool btf_id_set_contains(const struct btf_id_set *set, u32 id); > #define MAX_BPRINTF_VARARGS 12 > #define MAX_BPRINTF_BUF 1024 > > +/* Per-cpu temp buffers used by printf-like helpers to store the bprintf binary > + * arguments representation. > + */ > +#define MAX_BPRINTF_BIN_ARGS 512 > + > +struct bpf_bprintf_buffers { > + char bin_args[MAX_BPRINTF_BIN_ARGS]; > + char buf[MAX_BPRINTF_BUF]; > +}; > + > struct bpf_bprintf_data { > u32 *bin_args; > char *buf; > @@ -3557,9 +3567,12 @@ struct bpf_bprintf_data { > bool get_buf; > }; > > -int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args, > +int bpf_bprintf_prepare(const char *fmt, u32 fmt_size, const u64 *raw_args, > u32 num_args, struct bpf_bprintf_data *data); > void bpf_bprintf_cleanup(struct bpf_bprintf_data *data); > +int bpf_try_get_buffers(struct bpf_bprintf_buffers **bufs); > +void bpf_put_buffers(void); > + > > #ifdef CONFIG_BPF_LSM > void bpf_cgroup_atype_get(u32 attach_btf_id, int cgroup_atype); > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c > index f48fa3fe8dec..8f1cc1d525db 100644 > --- a/kernel/bpf/helpers.c > +++ b/kernel/bpf/helpers.c > @@ -764,22 +764,13 @@ static int bpf_trace_copy_string(char *buf, void *unsafe_ptr, char fmt_ptype, > return -EINVAL; > } > > -/* Per-cpu temp buffers used by printf-like helpers to store the bprintf binary > - * arguments representation. > - */ > -#define MAX_BPRINTF_BIN_ARGS 512 > - > /* Support executing three nested bprintf helper calls on a given CPU */ > #define MAX_BPRINTF_NEST_LEVEL 3 > -struct bpf_bprintf_buffers { > - char bin_args[MAX_BPRINTF_BIN_ARGS]; > - char buf[MAX_BPRINTF_BUF]; > -}; > > static DEFINE_PER_CPU(struct bpf_bprintf_buffers[MAX_BPRINTF_NEST_LEVEL], bpf_bprintf_bufs); > static DEFINE_PER_CPU(int, bpf_bprintf_nest_level); > > -static int try_get_buffers(struct bpf_bprintf_buffers **bufs) > +int bpf_try_get_buffers(struct bpf_bprintf_buffers **bufs) > { > int nest_level; > > @@ -795,16 +786,21 @@ static int try_get_buffers(struct bpf_bprintf_buffers **bufs) > return 0; > } > > -void bpf_bprintf_cleanup(struct bpf_bprintf_data *data) > +void bpf_put_buffers(void) > { > - if (!data->bin_args && !data->buf) > - return; > if (WARN_ON_ONCE(this_cpu_read(bpf_bprintf_nest_level) == 0)) > return; > this_cpu_dec(bpf_bprintf_nest_level); > preempt_enable(); > } > > +void bpf_bprintf_cleanup(struct bpf_bprintf_data *data) > +{ > + if (!data->bin_args && !data->buf) > + return; > + bpf_put_buffers(); > +} > + > /* > * bpf_bprintf_prepare - Generic pass on format strings for bprintf-like helpers > * > @@ -819,7 +815,7 @@ void bpf_bprintf_cleanup(struct bpf_bprintf_data *data) > * In argument preparation mode, if 0 is returned, safe temporary buffers are > * allocated and bpf_bprintf_cleanup should be called to free them after use. > */ > -int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args, > +int bpf_bprintf_prepare(const char *fmt, u32 fmt_size, const u64 *raw_args, > u32 num_args, struct bpf_bprintf_data *data) > { > bool get_buffers = (data->get_bin_args && num_args) || data->get_buf; > @@ -835,7 +831,7 @@ int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args, > return -EINVAL; > fmt_size = fmt_end - fmt; > > - if (get_buffers && try_get_buffers(&buffers)) > + if (get_buffers && bpf_try_get_buffers(&buffers)) > return -EBUSY; > > if (data->get_bin_args) { > -- > 2.47.1 >