BPF controlled io_uring
Subsystems (4)
Pavel Begunkov
maintainerv4 cover BPF controlled io_uring
Note: I'll be targeting 7.1 as it's rc7 and it can use some time to settle down.
This series introduces a way to override the standard io_uring_enter syscall execution with an extendible event loop, which can be controlled by BPF via new io_uring struct_ops or from within the kernel.
There are multiple use cases I want to cover with this:
- Syscall avoidance. Instead of returning to the userspace for CQE processing, a part of the logic can be moved into BPF to avoid excessive number of syscalls.
- Access to in-kernel io_uring resources. For example, there are registered buffers that can't be directly accessed by the userspace, however we can give BPF the ability to peek at them. It can be used to take a look at in-buffer app level headers to decide what to do with data next and issuing IO using it.
- Smarter request ordering and linking. Request links are pretty limited and inflexible as they can't pass information from one request to another. With BPF we can peek at CQEs and memory and compile a subsequent request.
- Feature semi-deprecation. It can be used to simplify handling of deprecated features by moving it into the callback out core io_uring. For example, it should be trivial to simulate IOSQE_IO_DRAIN. Another target could be request linking logic.
- It can serve as a base for custom algorithms and fine tuning. Often, it'd be impractical to introduce a generic feature because it's either niche or requires a lot of configuration. For example, there is support min-wait, however BPF can help to further fine tune it by doing it in multiple steps with different number of CQEs / timeouts. Another feature people were asking about is allowing to over queue SQEs but make the kernel to maintain a given QD.
- Smarter polling. Napi polling is performed only once per syscall and then it switches to waiting. We can do smarter and intermix polling with waiting using the hook.
It might need more specialised kfuncs in the future, but the core functionality is implemented with just two simple functions. One returns region memory, which gives BPF access to CQ/SQ/etc. And the second is for submitting requests. It's also given a structure as an argument, which is used to pass waiting parameters.
It showed good numbers in a test that sequentially executes N nop requests, where BPF was more than twice as fast than a 2-nop request link implementation.
Pavel Begunkov (6):
io_uring: introduce callback driven main loop io_uring/bpf-ops: add basic bpf struct_ops boilerplate io_uring/bpf-ops: add loop_step struct_ops callback io_uring/bpf-ops: add kfunc helpers io_uring/bpf-ops: add bpf struct ops registration selftests/io_uring: add a bpf io_uring selftest
include/linux/io_uring_types.h | 10 + io_uring/Kconfig | 5 + io_uring/Makefile | 3 +- io_uring/bpf-ops.c | 265 +++++++++++++++++++ io_uring/bpf-ops.h | 28 ++ io_uring/io_uring.c | 8 + io_uring/loop.c | 88 ++++++ io_uring/loop.h | 27 ++ tools/testing/selftests/Makefile | 3 +- tools/testing/selftests/io_uring/Makefile | 143 ++++++++++ tools/testing/selftests/io_uring/basic.bpf.c | 116 ++++++++ tools/testing/selftests/io_uring/common.h | 6 + tools/testing/selftests/io_uring/runner.c | 107 ++++++++ tools/testing/selftests/io_uring/types.bpf.h | 131 +++++++++ 14 files changed, 938 insertions(+), 2 deletions(-) create mode 100644 io_uring/bpf-ops.c create mode 100644 io_uring/bpf-ops.h create mode 100644 io_uring/loop.c create mode 100644 io_uring/loop.h create mode 100644 tools/testing/selftests/io_uring/Makefile create mode 100644 tools/testing/selftests/io_uring/basic.bpf.c create mode 100644 tools/testing/selftests/io_uring/common.h create mode 100644 tools/testing/selftests/io_uring/runner.c create mode 100644 tools/testing/selftests/io_uring/types.bpf.h
Signature · 1 line
2.52.0
Pavel Begunkov
maintainerPATCH v4 1/6 io_uring: introduce callback driven main loop
The io_uring_enter() has a fixed order of execution: it submits requests, waits for completions, and returns to the user. Allow to optionally replace it with a custom loop driven by a callback called loop_step. The basic requirements to the callback is that it should be able to submit requests, wait for completions, parse them and repeat. Most of the communication including parameter passing can be implemented via shared memory.
The callback should return IOU_LOOP_CONTINUE to continue execution or IOU_LOOP_STOP to return to the user space. Note that the kernel may decide to prematurely terminate it as well, e.g. in case the process was signalled or killed.
The hook takes a structure with parameters. It can be used to ask the kernel to wait for CQEs by setting cq_wait_idx to the CQE index it wants to wait for. Spurious wake ups are possible and even likely, the callback is expected to handle it. There will be more parameters in the future like timeout.
It can be used with kernel callbacks, for example, as a slow path deprecation mechanism overwiting SQEs and emulating the wanted behaviour, however it's more useful together with BPF programs implemented in following patches.
Note that keeping it separately from the normal io_uring wait loop makes things much simpler and cleaner. It keeps it in one place instead of spreading a bunch of checks in different places including disabling the submission path. It holds the lock by default, which is a better fit for BPF synchronisation and the loop execution model. It nicely avoids existing quirks like forced wake ups on timeout request completion. And it should be easier to implement new features.
--- include/linux/io_uring_types.h | 5 ++ io_uring/Makefile | 2 +- io_uring/io_uring.c | 6 +++ io_uring/loop.c | 88 ++++++++++++++++++++++++++++++++++ io_uring/loop.h | 27 +++++++++++ 5 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 io_uring/loop.c create mode 100644 io_uring/loop.h
include/linux/io_uring_types.h +5 -0
@@ -41,6 +41,8 @@ enum io_uring_cmd_flags { IO_URING_F_COMPAT = (1 << 12), }; +struct iou_loop_params ; +struct io_wq_work_node {struct io_wq_work_node *next; };
@@ -342,6 +344,9 @@ struct io_ring_ctx {struct io_alloc_cache rw_cache;struct io_alloc_cache cmd_cache; +int (*loop_step)(struct io_ring_ctx *ctx, +struct iou_loop_params *); +/* * Any cancelable uring_cmd is added to this list in * ->uring_cmd() by io_uring_cmd_insert_cancelable()
io_uring/Makefile +1 -1
@@ -14,7 +14,7 @@ obj-$(CONFIG_IO_URING) += io_uring.o opdef.o kbuf.o rsrc.o notif.o \ advise.o openclose.o statx.o timeout.o \ cancel.o waitid.o register.o \ truncate.o memmap.o alloc_cache.o \ - query.o + query.o loop.o obj-$(CONFIG_IO_URING_ZCRX) += zcrx.o obj-$(CONFIG_IO_WQ) += io-wq.o
io_uring/io_uring.c +6 -0
@@ -94,6 +94,7 @@#include "alloc_cache.h" #include "eventfd.h" #include "wait.h" +#include "loop.h" #define SQE_COMMON_FLAGS (IOSQE_FIXED_FILE | IOSQE_IO_LINK | \ IOSQE_IO_HARDLINK | IOSQE_ASYNC)
@@ -2557,6 +2558,11 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,if (unlikely (smp_load_acquire (&ctx->flags) &IORING_SETUP_R_DISABLED )) goto out; +if (io_has_loop_ops (ctx)) { + ret =io_run_loop (ctx); + goto out; + } +/* * For SQ polling, the thread will do all submissions and completions. * Just return the requested submit count, and wake the thread if
io_uring/loop.c new file +88 -0
88 lines not on this page · raw message
io_uring/loop.h new file +27 -0
@@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef IOU_LOOP_H +#define IOU_LOOP_H + +#include <linux/io_uring_types.h> + +struct iou_loop_params { +/* +* The CQE index to wait for. Only serves as a hint and can still be +* woken up earlier. +*/ +__u32 cq_wait_idx; +}; + +enum { +IOU_LOOP_CONTINUE =0 , +IOU_LOOP_STOP , +}; + +static inline bool io_has_loop_ops (struct io_ring_ctx *ctx) +{ +return data_race (ctx->loop_step); +} + +int io_run_loop (struct io_ring_ctx *ctx); + +#endif
Signature · 1 line
2.52.0
Pavel Begunkov
maintainerPATCH v4 2/6 io_uring/bpf-ops: add basic bpf struct_ops boilerplate
In reply to Pavel BegunkovAdd boilerplate code with a basic bpf_struct_ops implementation and related files and definitions. It'll be used in following patches to add support for io_uring bpf ops.
--- io_uring/Kconfig | 5 +++ io_uring/Makefile | 1 + io_uring/bpf-ops.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ io_uring/bpf-ops.h | 10 +++++ io_uring/io_uring.c | 1 + 5 files changed, 108 insertions(+) create mode 100644 io_uring/bpf-ops.c create mode 100644 io_uring/bpf-ops.h
io_uring/Kconfig +5 -0
@@ -9,3 +9,8 @@ config IO_URING_ZCRX depends on PAGE_POOL depends on INET depends on NET_RX_BUSY_POLL + +config IO_URING_BPF + def_bool y + depends on IO_URING + depends on BPF_SYSCALL && BPF_JIT && DEBUG_INFO_BTF
io_uring/Makefile +1 -0
@@ -24,3 +24,4 @@ obj-$(CONFIG_NET_RX_BUSY_POLL) += napi.o obj-$(CONFIG_NET) += net.o cmd_net.o obj-$(CONFIG_PROC_FS) += fdinfo.o obj-$(CONFIG_IO_URING_MOCK_FILE) += mock_file.o +obj-$(CONFIG_IO_URING_BPF) += bpf-ops.o
io_uring/bpf-ops.c new file +91 -0
91 lines not on this page · raw message
io_uring/bpf-ops.h new file +10 -0
@@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef IOU_BPF_OPS_H +#define IOU_BPF_OPS_H + +#include <linux/io_uring_types.h> + +struct io_uring_bpf_ops { +}; + +#endif /* IOU_BPF_OPS_H */
io_uring/io_uring.c +1 -0
@@ -87,6 +87,7 @@#include "msg_ring.h" #include "memmap.h" #include "zcrx.h" +#include "bpf-ops.h" #include "timeout.h" #include "poll.h"
Signature · 1 line
2.52.0
Pavel Begunkov
maintainerPATCH v4 3/6 io_uring/bpf-ops: add loop_step struct_ops callback
In reply to Pavel BegunkovAllow BPF to implement the loop_step callback to overwrite the main loop logic. As described in the patch introducing the callback, it receives iou_loop_params as an argument, which BPF can directly use to control the loop.
--- io_uring/bpf-ops.c | 36 ++++++++++++++++++++++++++++++++++++ io_uring/bpf-ops.h | 4 ++++ 2 files changed, 40 insertions(+)
io_uring/bpf-ops.c +36 -0
@@ -1,11 +1,22 @@#include <linux/mutex.h> #include <linux/bpf.h> +#include <linux/bpf_verifier.h> #include "io_uring.h" #include "register.h" #include "bpf-ops.h" +#include "loop.h" + +static const struct btf_type *loop_params_type; + +static int io_bpf_ops__loop_step (struct io_ring_ctx *ctx, +struct iou_loop_params *lp) +{ +return IOU_LOOP_STOP ; +}static struct io_uring_bpf_ops io_bpf_ops_stubs = { + .loop_step = io_bpf_ops__loop_step, }; static bool bpf_io_is_valid_access(int off, int size,
@@ -27,6 +38,14 @@ static int bpf_io_btf_struct_access(struct bpf_verifier_log *log, const struct bpf_reg_state *reg, int off, int size) { + const struct btf_type *t = btf_type_by_id(reg->btf, reg->btf_id); + +if (t == loop_params_type) { +if (off >= offsetof(struct iou_loop_params , cq_wait_idx) && + off + size <= offsetofend(struct iou_loop_params, cq_wait_idx)) +return SCALAR_VALUE ; + } +return -EACCES ; }
@@ -36,8 +55,25 @@ static const struct bpf_verifier_ops bpf_io_verifier_ops = { .btf_struct_access = bpf_io_btf_struct_access, }; +static const struct btf_type * +io_lookup_struct_type (struct btf *btf,const char *name) +{ +s32 type_id; + + type_id =btf_find_by_name_kind (btf, name,BTF_KIND_STRUCT ); +if (type_id <0 ) +return NULL ; +return btf_type_by_id (btf, type_id); +} +static int bpf_io_init (struct btf *btf) { + loop_params_type =io_lookup_struct_type (btf,"iou_loop_params" ); +if (!loop_params_type) { +pr_err ("io_uring: Failed to locate iou_loop_params\n" ); +return -EINVAL ; + } +return 0 ; }
io_uring/bpf-ops.h +4 -0
@@ -5,6 +5,10 @@#include <linux/io_uring_types.h> struct io_uring_bpf_ops { +int (*loop_step)(struct io_ring_ctx *ctx,struct iou_loop_params *lp); + +__u32 ring_fd; +void *priv; };#endif /* IOU_BPF_OPS_H */
Signature · 1 line
2.52.0
Pavel Begunkov
maintainerPATCH v4 4/6 io_uring/bpf-ops: add kfunc helpers
In reply to Pavel BegunkovAdd two kfuncs that should cover most of the needs:
1. bpf_io_uring_submit_sqes(), which allows to submit io_uring requests. It mirrors the normal user space submission path and follows all related io_uring_enter(2) rules. i.e. SQEs are taken from the SQ according to head/tail values. In case of IORING_SETUP_SQ_REWIND, it'll submit first N entries.
2. bpf_io_uring_get_region() returns a pointer to the specified region, where io_uring regions are kernel-userspace shared chunks of memory. It takes the size as an argument, which should be a load time constant. There are 3 types of regions:
- IOU_REGION_SQ returns the submission queue.
- IOU_REGION_CQ stores the CQ, SQ/CQ headers and the sqarray. In other words, it gives same memory that would normally be mmap'ed with IORING_FEAT_SINGLE_MMAP enabled IORING_OFF_SQ_RING.
- IOU_REGION_MEM represents the memory / parameter region. It can be used to store request indirect parameters and for kernel - user communication.
It intentionally provides a thin but flexible API and expects BPF programs to implement CQ/SQ header parsing, CQ walking, etc. That mirrors how the normal user space works with rings and should help to minimise kernel / kfunc helpers changes while introducing new generic io_uring features.
--- io_uring/bpf-ops.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++ io_uring/bpf-ops.h | 6 ++++++ 2 files changed, 59 insertions(+)
io_uring/bpf-ops.c +53 -0
@@ -4,11 +4,56 @@#include "io_uring.h" #include "register.h" +#include "memmap.h" #include "bpf-ops.h" #include "loop.h" static const struct btf_type *loop_params_type; +__bpf_kfunc_start_defs (); + +__bpf_kfunc int bpf_io_uring_submit_sqes(struct io_ring_ctx *ctx, u32 nr) +{ +return io_submit_sqes (ctx, nr); +} + +__bpf_kfunc +__u8 *bpf_io_uring_get_region(struct io_ring_ctx *ctx, __u32 region_id, +const size_t rdwr_buf_size) +{ +struct io_mapped_region *r; + +switch (region_id) { +case IOU_REGION_MEM : + r = &ctx->param_region; +break ; +case IOU_REGION_CQ : + r = &ctx->ring_region; +break ; +case IOU_REGION_SQ : + r = &ctx->sq_region; +break ; +default : +return NULL ; + } + +if (unlikely (rdwr_buf_size >io_region_size (r))) +return NULL ; +return io_region_get_ptr (r); +} + +__bpf_kfunc_end_defs (); + +BTF_KFUNCS_START (io_uring_kfunc_set) +BTF_ID_FLAGS(func, bpf_io_uring_submit_sqes, KF_SLEEPABLE | KF_TRUSTED_ARGS); +BTF_ID_FLAGS (func, bpf_io_uring_get_region,KF_RET_NULL |KF_TRUSTED_ARGS ); +BTF_KFUNCS_END (io_uring_kfunc_set) + +static const struct btf_kfunc_id_set bpf_io_uring_kfunc_set = { + .owner =THIS_MODULE , + .set = &io_uring_kfunc_set, +}; +static int io_bpf_ops__loop_step (struct io_ring_ctx *ctx,struct iou_loop_params *lp) {
@@ -68,12 +113,20 @@ io_lookup_struct_type(struct btf *btf, const char *name)static int bpf_io_init (struct btf *btf) { +int ret; + loop_params_type =io_lookup_struct_type (btf,"iou_loop_params" );if (!loop_params_type) {pr_err ("io_uring: Failed to locate iou_loop_params\n" );return -EINVAL ; } + ret =register_btf_kfunc_id_set (BPF_PROG_TYPE_STRUCT_OPS , + &bpf_io_uring_kfunc_set); +if (ret) { +pr_err ("io_uring: Failed to register kfuncs (%d)\n" , ret); +return ret; + }return 0 ; }
io_uring/bpf-ops.h +6 -0
@@ -4,6 +4,12 @@#include <linux/io_uring_types.h> +enum { +IOU_REGION_MEM , +IOU_REGION_CQ , +IOU_REGION_SQ , +}; +struct io_uring_bpf_ops {int (*loop_step)(struct io_ring_ctx *ctx,struct iou_loop_params *lp);
Signature · 1 line
2.52.0
Pavel Begunkov
maintainerPATCH v4 5/6 io_uring/bpf-ops: add bpf struct ops registration
In reply to Pavel BegunkovImplement BPF struct ops registration. It's registered from the BPF path, and can be removed by BPF as well as io_uring, which is why it's protected by a global lock io_bpf_ctrl_mutex.
--- include/linux/io_uring_types.h | 5 ++ io_uring/bpf-ops.c | 87 +++++++++++++++++++++++++++++++++- io_uring/bpf-ops.h | 8 ++++ io_uring/io_uring.c | 1 + 4 files changed, 100 insertions(+), 1 deletion(-)
include/linux/io_uring_types.h +5 -0
@@ -8,6 +8,9 @@#include <linux/llist.h> #include <uapi/linux/io_uring.h> +struct iou_loop_params ; +struct io_uring_bpf_ops ; +enum {/* * A hint to not wake right away but delay until there are enough of
@@ -462,6 +465,8 @@ struct io_ring_ctx {DECLARE_HASHTABLE (napi_ht,4 );#endif +struct io_uring_bpf_ops *bpf_ops; +/* * Protection for resize vs mmap races - both the mmap and resize * side will need to grab this lock, to prevent either side from
io_uring/bpf-ops.c +86 -1
112 lines not on this page · raw message
io_uring/bpf-ops.h +8 -0
@@ -17,4 +17,12 @@ struct io_uring_bpf_ops { void *priv; }; +#ifdef CONFIG_IO_URING_BPF +void io_unregister_bpf_ops (struct io_ring_ctx *ctx); +#else +static inline void io_unregister_bpf_ops (struct io_ring_ctx *ctx) +{ +} +#endif +#endif /* IOU_BPF_OPS_H */
io_uring/io_uring.c +1 -0
@@ -2141,6 +2141,7 @@ static __cold void io_req_caches_free(struct io_ring_ctx *ctx)static __cold void io_ring_ctx_free (struct io_ring_ctx *ctx) { +io_unregister_bpf_ops (ctx);io_sq_thread_finish (ctx);mutex_lock (&ctx->uring_lock);
Signature · 1 line
2.52.0
Pavel Begunkov
maintainerPATCH v4 6/6 selftests/io_uring: add a bpf io_uring selftest
In reply to Pavel BegunkovAdd a simple io_uring BPF selftest, where the BPF program implemented in basic.bpf.c executes a given number of NOP requests with QD=1, writes some stats and returns back. The makefile is borrowed from sched_ext tests.
--- tools/testing/selftests/Makefile | 3 +- tools/testing/selftests/io_uring/Makefile | 143 +++++++++++++++++++ tools/testing/selftests/io_uring/basic.bpf.c | 116 +++++++++++++++ tools/testing/selftests/io_uring/common.h | 6 + tools/testing/selftests/io_uring/runner.c | 107 ++++++++++++++ tools/testing/selftests/io_uring/types.bpf.h | 131 +++++++++++++++++ 6 files changed, 505 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/io_uring/Makefile create mode 100644 tools/testing/selftests/io_uring/basic.bpf.c create mode 100644 tools/testing/selftests/io_uring/common.h create mode 100644 tools/testing/selftests/io_uring/runner.c create mode 100644 tools/testing/selftests/io_uring/types.bpf.h
tools/testing/selftests/Makefile +2 -1
@@ -130,6 +130,7 @@ TARGETS += vfio TARGETS += x86 TARGETS += x86/bugs TARGETS += zram +TARGETS += io_uring #Please keep the TARGETS list alphabetically sorted # Run "make quicktest=1 run_tests" or # "make quicktest=1 kselftest" from top level Makefile
@@ -147,7 +148,7 @@ endif # User can optionally provide a TARGETS skiplist. By default we skip # targets using BPF since it has cutting edge build time dependencies # which require more effort to install. -SKIP_TARGETS ?= bpf sched_ext +SKIP_TARGETS ?= bpf sched_ext io_uring ifneq ($(SKIP_TARGETS),) TMP := $(filter-out $(SKIP_TARGETS), $(TARGETS)) override TARGETS := $(TMP)
tools/testing/selftests/io_uring/Makefile new file +143 -0
143 lines not on this page · raw message
tools/testing/selftests/io_uring/basic.bpf.c new file +116 -0
116 lines not on this page · raw message
tools/testing/selftests/io_uring/common.h new file +6 -0
@@ -0,0 +1,6 @@ +#define CQ_ENTRIES 8 +#define SQ_ENTRIES 8 + +#define SLOT_RES 0 +#define SLOT_NR_CQES 1 +#define SLOT_NR_SQES 2
tools/testing/selftests/io_uring/runner.c new file +107 -0
107 lines not on this page · raw message
tools/testing/selftests/io_uring/types.bpf.h new file +131 -0
131 lines not on this page · raw message
Signature · 1 line
2.52.0
Re: [PATCH v4 6/6] selftests/io_uring: add a bpf io_uring selftest
Quoted 7 lines · Pavel Begunkov
index 000000000000..7a170cb2f388
tools/testing/selftests/io_uring/types.bpf.h new file +2
-0@@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +#include <linux/types.h>
tools/testing/selftests/io_uring/types.bpf.h line 12
Quoted 10 lines
tools/testing/selftests/io_uring/types.bpf.h new file +10
-0+#include <bpf/bpf_helpers.h> + +struct io_ring_ctx { +}; + +struct io_uring_sqe { +__u8 opcode;/* type of operation for this sqe */ +__u8 flags;/* IOSQE_ flags */ +__u16 ioprio;/* ioprio for the request */ +__s32 fd;/* file descriptor to do IO on */
1.
No need to copy paste. Just include vmlinux.h. It's there.
2.
drop KF_TRUSTED_ARGS from kfunc. It's a default now and this flag was removed.
3.
add a runtime logic to check that the return value is either IOU_LOOP_CONTINUE or IOU_LOOP_STOP or instruct the verifier do it statically. Otherwise it will be less convenient to extend to other commands, since the way I read it IOU_LOOP_CONTINUE == 0 aliases to any value > 1.
Pavel Begunkov
maintainerRe: [PATCH v4 6/6] selftests/io_uring: add a bpf io_uring selftest
Quoted 22 lines · Alexei Starovoitov
Quoted 7 lines · Pavel Begunkov
index 000000000000..7a170cb2f388
tools/testing/selftests/io_uring/types.bpf.h new file +2
-0@@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +#include <linux/types.h> tools/testing/selftests/io_uring/types.bpf.h line 12
Quoted 10 lines
tools/testing/selftests/io_uring/types.bpf.h new file +10
-0+#include <bpf/bpf_helpers.h> + +struct io_ring_ctx { +}; + +struct io_uring_sqe { +__u8 opcode;/* type of operation for this sqe */ +__u8 flags;/* IOSQE_ flags */ +__u16 ioprio;/* ioprio for the request */ +__s32 fd;/* file descriptor to do IO on */ 1.
No need to copy paste. Just includevmlinux.h. It's there.
Quoted 3 lines
2.
dropKF_TRUSTED_ARGSfrom kfunc. It's a default now and this flag was removed.
Got it, will change both, thanks
Quoted 5 lines
3.
add a runtime logic to check that the return value is eitherIOU_LOOP_CONTINUEorIOU_LOOP_STOPor instruct the verifier do it statically. Otherwise it will be less convenient to extend to other commands, since the way I read itIOU_LOOP_CONTINUE== 0 aliases to any value > 1.
Is there a struct_ops hook that can help with that? check_return_code() has some hard-coded checks, but I can't find anything customizable for struct_ops.
Signature · 1 line
Pavel Begunkov
Re: [PATCH v4 6/6] selftests/io_uring: add a bpf io_uring selftest
Quoted 36 lines · Pavel Begunkov
Quoted 22 lines · Alexei Starovoitov
Quoted 7 lines · Pavel Begunkov
index 000000000000..7a170cb2f388
tools/testing/selftests/io_uring/types.bpf.h new file +2
-0@@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +#include <linux/types.h> tools/testing/selftests/io_uring/types.bpf.h line 12
Quoted 10 lines
tools/testing/selftests/io_uring/types.bpf.h new file +10
-0+#include <bpf/bpf_helpers.h> + +struct io_ring_ctx { +}; + +struct io_uring_sqe { +__u8 opcode;/* type of operation for this sqe */ +__u8 flags;/* IOSQE_ flags */ +__u16 ioprio;/* ioprio for the request */ +__s32 fd;/* file descriptor to do IO on */ 1.
No need to copy paste. Just includevmlinux.h. It's there.Quoted 3 lines
2.
dropKF_TRUSTED_ARGSfrom kfunc. It's a default now and this flag was removed.Got it, will change both, thanks
Quoted 5 lines
3.
add a runtime logic to check that the return value is eitherIOU_LOOP_CONTINUEorIOU_LOOP_STOPor instruct the verifier do it statically. Otherwise it will be less convenient to extend to other commands, since the way I read itIOU_LOOP_CONTINUE== 0 aliases to any value > 1.
Quoted 3 lines
Is there a
struct_opshook that can help with that?check_return_code()has some hard-coded checks, but I can't find anything customizable forstruct_ops.
yep. check_return_code() is the one and you're correct. It's not customizable atm. Much simpler to do a runtime check for now and improve through the verifier support later.
Pavel Begunkov
maintainerRe: [PATCH v4 6/6] selftests/io_uring: add a bpf io_uring selftest
Quoted 37 lines · Alexei Starovoitov
Quoted 36 lines · Pavel Begunkov
Quoted 22 lines · Alexei Starovoitov
Quoted 7 lines · Pavel Begunkov
index 000000000000..7a170cb2f388
tools/testing/selftests/io_uring/types.bpf.h new file +2
-0@@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +#include <linux/types.h> tools/testing/selftests/io_uring/types.bpf.h line 12
Quoted 10 lines
tools/testing/selftests/io_uring/types.bpf.h new file +10
-0+#include <bpf/bpf_helpers.h> + +struct io_ring_ctx { +}; + +struct io_uring_sqe { +__u8 opcode;/* type of operation for this sqe */ +__u8 flags;/* IOSQE_ flags */ +__u16 ioprio;/* ioprio for the request */ +__s32 fd;/* file descriptor to do IO on */ 1.
No need to copy paste. Just includevmlinux.h. It's there.Quoted 3 lines
2.
dropKF_TRUSTED_ARGSfrom kfunc. It's a default now and this flag was removed.Got it, will change both, thanks
Quoted 5 lines
3.
add a runtime logic to check that the return value is eitherIOU_LOOP_CONTINUEorIOU_LOOP_STOPor instruct the verifier do it statically. Otherwise it will be less convenient to extend to other commands, since the way I read itIOU_LOOP_CONTINUE== 0 aliases to any value > 1.
Quoted 7 lines
Quoted 3 lines
Is there a
struct_opshook that can help with that?check_return_code()has some hard-coded checks, but I can't find anything customizable forstruct_ops.yep.
check_return_code()is the one and you're correct. It's not customizable atm. Much simpler to do a runtime check for now and improve through the verifier support later.
Makes sense, thanks!
Signature · 1 line
Pavel Begunkov