Add bpf prog attach helpers and prepare for supporting ublk bpf, in which multiple ublk device may attach to same bpf prog, and there can be multiple bpf progs. `bpf_prog_consumer` will be embedded in the bpf prog user side, such as ublk device, `bpf_prog_provider` will be embedded in the bpf struct_ops prog side. Signed-off-by: Ming Lei <tom.leiming@xxxxxxxxx> --- drivers/block/ublk/bpf_reg.h | 77 ++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 drivers/block/ublk/bpf_reg.h diff --git a/drivers/block/ublk/bpf_reg.h b/drivers/block/ublk/bpf_reg.h new file mode 100644 index 000000000000..79d02e93aea8 --- /dev/null +++ b/drivers/block/ublk/bpf_reg.h @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#ifndef UBLK_INT_BPF_REG_HEADER +#define UBLK_INT_BPF_REG_HEADER + +#include <linux/types.h> + +struct bpf_prog_consumer; +struct bpf_prog_provider; + +typedef int (*bpf_prog_attach_t)(struct bpf_prog_consumer *consumer, + struct bpf_prog_provider *provider); +typedef void (*bpf_prog_detach_t)(struct bpf_prog_consumer *consumer, + bool unreg); + +struct bpf_prog_consumer_ops { + bpf_prog_attach_t attach_fn; + bpf_prog_detach_t detach_fn; +}; + +struct bpf_prog_consumer { + const struct bpf_prog_consumer_ops *ops; + unsigned int prog_id; + struct list_head node; + struct bpf_prog_provider *provider; +}; + +struct bpf_prog_provider { + struct list_head list; +}; + +static inline void bpf_prog_provider_init(struct bpf_prog_provider *provider) +{ + INIT_LIST_HEAD(&provider->list); +} + +static inline bool bpf_prog_provider_is_empty( + struct bpf_prog_provider *provider) +{ + return list_empty(&provider->list); +} + +static inline int bpf_prog_consumer_attach(struct bpf_prog_consumer *consumer, + struct bpf_prog_provider *provider) +{ + const struct bpf_prog_consumer_ops *ops = consumer->ops; + + if (!ops || !ops->attach_fn) + return -EINVAL; + + if (ops->attach_fn) { + int ret = ops->attach_fn(consumer, provider); + + if (ret) + return ret; + } + consumer->provider = provider; + list_add(&consumer->node, &provider->list); + return 0; +} + +static inline void bpf_prog_consumer_detach(struct bpf_prog_consumer *consumer, + bool unreg) +{ + const struct bpf_prog_consumer_ops *ops = consumer->ops; + + if (!consumer->provider) + return; + + if (!list_empty(&consumer->node)) { + if (ops && ops->detach_fn) + ops->detach_fn(consumer, unreg); + list_del_init(&consumer->node); + consumer->provider = NULL; + } +} + +#endif -- 2.47.0