From: Ming Lei <tom.leiming@gmail.com>
To: Jens Axboe <axboe@kernel.dk>, linux-block@vger.kernel.org
Cc: bpf@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>,
Martin KaFai Lau <martin.lau@linux.dev>,
Yonghong Song <yonghong.song@linux.dev>,
Ming Lei <tom.leiming@gmail.com>
Subject: [RFC PATCH 20/22] selftests: add tests for ublk bpf aio
Date: Tue, 7 Jan 2025 20:04:11 +0800 [thread overview]
Message-ID: <20250107120417.1237392-21-tom.leiming@gmail.com> (raw)
In-Reply-To: <20250107120417.1237392-1-tom.leiming@gmail.com>
Create ublk loop target which uses bpf aio to submit & complete FS
IO, then run write & read & verify on the ublk loop disk for making
sure ublk bpf aio works as expected.
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
---
tools/testing/selftests/ublk/Makefile | 3 +
.../selftests/ublk/progs/ublk_bpf_kfunc.h | 11 ++
.../testing/selftests/ublk/progs/ublk_loop.c | 166 ++++++++++++++++++
tools/testing/selftests/ublk/test_common.sh | 47 +++++
tools/testing/selftests/ublk/test_loop_01.sh | 33 ++++
tools/testing/selftests/ublk/test_loop_02.sh | 24 +++
tools/testing/selftests/ublk/ublk_bpf.c | 141 ++++++++++++++-
7 files changed, 419 insertions(+), 6 deletions(-)
create mode 100644 tools/testing/selftests/ublk/progs/ublk_loop.c
create mode 100755 tools/testing/selftests/ublk/test_loop_01.sh
create mode 100755 tools/testing/selftests/ublk/test_loop_02.sh
diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
index 38903f05d99d..2540ae7a75a3 100644
--- a/tools/testing/selftests/ublk/Makefile
+++ b/tools/testing/selftests/ublk/Makefile
@@ -24,6 +24,9 @@ TEST_PROGS += test_null_02.sh
TEST_PROGS += test_null_03.sh
TEST_PROGS += test_null_04.sh
+TEST_PROGS += test_loop_01.sh
+TEST_PROGS += test_loop_02.sh
+
# Order correspond to 'make run_tests' order
TEST_GEN_PROGS_EXTENDED = ublk_bpf
diff --git a/tools/testing/selftests/ublk/progs/ublk_bpf_kfunc.h b/tools/testing/selftests/ublk/progs/ublk_bpf_kfunc.h
index 1db8870b57d6..9fb134e40d49 100644
--- a/tools/testing/selftests/ublk/progs/ublk_bpf_kfunc.h
+++ b/tools/testing/selftests/ublk/progs/ublk_bpf_kfunc.h
@@ -21,6 +21,17 @@ extern int ublk_bpf_get_dev_id(const struct ublk_bpf_io *io) __ksym;
extern int ublk_bpf_get_queue_id(const struct ublk_bpf_io *io) __ksym;
extern int ublk_bpf_get_io_tag(const struct ublk_bpf_io *io) __ksym;
+extern void ublk_bpf_dettach_and_complete_aio(struct bpf_aio *aio) __ksym;
+extern int ublk_bpf_attach_and_prep_aio(const struct ublk_bpf_io *_io, unsigned off, unsigned bytes, struct bpf_aio *aio) __ksym;
+extern struct ublk_bpf_io *ublk_bpf_acquire_io_from_aio(struct bpf_aio *aio) __ksym;
+extern void ublk_bpf_release_io_from_aio(struct ublk_bpf_io *io) __ksym;
+
+extern struct bpf_aio *bpf_aio_alloc(unsigned int op, enum bpf_aio_flag flags) __ksym;
+extern struct bpf_aio *bpf_aio_alloc_sleepable(unsigned int op, enum bpf_aio_flag flags) __ksym;
+extern void bpf_aio_release(struct bpf_aio *aio) __ksym;
+extern int bpf_aio_submit(struct bpf_aio *aio, int fd, loff_t pos,
+ unsigned bytes, unsigned io_flags) __ksym;
+
static inline unsigned long long build_io_key(const struct ublk_bpf_io *io)
{
unsigned long long dev_id = (unsigned short)ublk_bpf_get_dev_id(io);
diff --git a/tools/testing/selftests/ublk/progs/ublk_loop.c b/tools/testing/selftests/ublk/progs/ublk_loop.c
new file mode 100644
index 000000000000..952caf7b7399
--- /dev/null
+++ b/tools/testing/selftests/ublk/progs/ublk_loop.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "vmlinux.h"
+#include <linux/const.h>
+#include <linux/errno.h>
+#include <linux/falloc.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+//#define DEBUG
+#include "ublk_bpf.h"
+
+/* libbpf v1.4.5 is required for struct_ops to work */
+
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(max_entries, 128);
+ __type(key, unsigned int); /* dev id */
+ __type(value, int); /* backing file fd */
+} fd_map SEC(".maps");
+
+static inline void ublk_loop_comp_and_release_aio(struct bpf_aio *aio, int ret)
+{
+ struct ublk_bpf_io *io = ublk_bpf_acquire_io_from_aio(aio);
+
+ ublk_bpf_complete_io(io, ret);
+ ublk_bpf_release_io_from_aio(io);
+
+ ublk_bpf_dettach_and_complete_aio(aio);
+ bpf_aio_release(aio);
+}
+
+SEC("struct_ops/bpf_aio_complete_cb")
+void BPF_PROG(ublk_loop_comp_cb, struct bpf_aio *aio, long ret)
+{
+ BPF_DBG("aio result %d, back_file %s pos %llx", ret,
+ aio->iocb.ki_filp->f_path.dentry->d_name.name,
+ aio->iocb.ki_pos);
+ ublk_loop_comp_and_release_aio(aio, ret);
+}
+
+SEC(".struct_ops.link")
+struct bpf_aio_complete_ops loop_ublk_bpf_aio_ops = {
+ .id = 16,
+ .bpf_aio_complete_cb = (void *)ublk_loop_comp_cb,
+};
+
+static inline int ublk_loop_submit_backing_io(const struct ublk_bpf_io *io,
+ const struct ublksrv_io_desc *iod, int backing_fd)
+{
+ unsigned int op_flags = 0;
+ struct bpf_aio *aio;
+ int res = -EINVAL;
+ int op;
+
+ /* translate ublk opcode into backing file's */
+ switch (iod->op_flags & 0xff) {
+ case 0 /*UBLK_IO_OP_READ*/:
+ op = BPF_AIO_OP_FS_READ;
+ break;
+ case 1 /*UBLK_IO_OP_WRITE*/:
+ op = BPF_AIO_OP_FS_WRITE;
+ break;
+ case 2 /*UBLK_IO_OP_FLUSH*/:
+ op = BPF_AIO_OP_FS_FSYNC;
+ break;
+ case 3 /*UBLK_IO_OP_DISCARD*/:
+ op = BPF_AIO_OP_FS_FALLOCATE;
+ op_flags = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+ break;
+ case 4 /*UBLK_IO_OP_WRITE_SAME*/:
+ op = BPF_AIO_OP_FS_FALLOCATE;
+ op_flags = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+ break;
+ case 5 /*UBLK_IO_OP_WRITE_ZEROES*/:
+ op = BPF_AIO_OP_FS_FALLOCATE;
+ op_flags = FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ res = -ENOMEM;
+ aio = bpf_aio_alloc(op, 0);
+ if (!aio)
+ goto fail;
+
+ /* attach aio into the specified range of this io command */
+ res = ublk_bpf_attach_and_prep_aio(io, 0, iod->nr_sectors << 9, aio);
+ if (res < 0) {
+ bpf_printk("bpf aio attaching failed %d\n", res);
+ goto fail;
+ }
+
+ /* submit this aio onto the backing file */
+ res = bpf_aio_submit(aio, backing_fd, iod->start_sector << 9,
+ iod->nr_sectors << 9, op_flags);
+ if (res < 0) {
+ bpf_printk("aio submit failed %d\n", res);
+ ublk_loop_comp_and_release_aio(aio, res);
+ }
+ return 0;
+fail:
+ return res;
+}
+
+static inline ublk_bpf_return_t __ublk_loop_handle_io_cmd(const struct ublk_bpf_io *io, unsigned int off)
+{
+ const struct ublksrv_io_desc *iod;
+ int res = -EINVAL;
+ int fd_key = ublk_bpf_get_dev_id(io);
+ int *fd;
+ ublk_bpf_return_t ret = ublk_bpf_return_val(UBLK_BPF_IO_QUEUED, 0);
+
+ iod = ublk_bpf_get_iod(io);
+ if (!iod) {
+ ublk_bpf_complete_io(io, res);
+ return ret;
+ }
+
+ BPF_DBG("ublk dev %u qid %u: handle io cmd tag %u op %u %lx-%d off %u",
+ ublk_bpf_get_dev_id(io),
+ ublk_bpf_get_queue_id(io),
+ ublk_bpf_get_io_tag(io),
+ iod->op_flags & 0xff,
+ iod->start_sector << 9,
+ iod->nr_sectors << 9, off);
+
+ /* retrieve backing file descriptor */
+ fd = bpf_map_lookup_elem(&fd_map, &fd_key);
+ if (!fd) {
+ bpf_printk("can't get FD from %d\n", fd_key);
+ return ret;
+ }
+
+ /* handle this io command by submitting IOs on backing file */
+ res = ublk_loop_submit_backing_io(io, iod, *fd);
+
+exit:
+ /* io cmd can't be completes until this reference is dropped */
+ if (res < 0)
+ ublk_bpf_complete_io(io, io->res);
+
+ return ublk_bpf_return_val(UBLK_BPF_IO_QUEUED, 0);
+}
+
+SEC("struct_ops/ublk_bpf_release_io_cmd")
+void BPF_PROG(ublk_loop_release_io_cmd, struct ublk_bpf_io *io)
+{
+ BPF_DBG("%s: released io command %d", __func__, io->res);
+}
+
+SEC("struct_ops.s/ublk_bpf_queue_io_cmd_daemon")
+ublk_bpf_return_t BPF_PROG(ublk_loop_handle_io_cmd, struct ublk_bpf_io *io, unsigned int off)
+{
+ return __ublk_loop_handle_io_cmd(io, off);
+}
+
+SEC(".struct_ops.link")
+struct ublk_bpf_ops loop_ublk_bpf_ops = {
+ .id = 16,
+ .queue_io_cmd_daemon = (void *)ublk_loop_handle_io_cmd,
+ .release_io_cmd = (void *)ublk_loop_release_io_cmd,
+};
+
+char LICENSE[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/ublk/test_common.sh b/tools/testing/selftests/ublk/test_common.sh
index 466b82e77860..4727a6ec9734 100755
--- a/tools/testing/selftests/ublk/test_common.sh
+++ b/tools/testing/selftests/ublk/test_common.sh
@@ -70,3 +70,50 @@ _add_ublk_dev() {
fi
udevadm settle
}
+
+_create_backfile() {
+ local my_size=$1
+ local my_file=`mktemp ublk_bpf_${my_size}_XXXXX`
+
+ truncate -s ${my_size} ${my_file}
+ echo $my_file
+}
+
+_remove_backfile() {
+ local file=$1
+
+ [ -f "$file" ] && rm -f $file
+}
+
+_create_tmp_dir() {
+ local my_file=`mktemp -d ublk_bpf_dir_XXXXX`
+
+ echo $my_file
+}
+
+_remove_tmp_dir() {
+ local dir=$1
+
+ [ -d "$dir" ] && rmdir $dir
+}
+
+_mkfs_mount_test()
+{
+ local dev=$1
+ local err_code=0
+ local mnt_dir=`_create_tmp_dir`
+
+ mkfs.ext4 -F $dev > /dev/null 2>&1
+ err_code=$?
+ if [ $err_code -ne 0 ]; then
+ return $err_code
+ fi
+
+ mount -t ext4 $dev $mnt_dir > /dev/null 2>&1
+ umount $dev
+ err_code=$?
+ _remove_tmp_dir $mnt_dir
+ if [ $err_code -ne 0 ]; then
+ return $err_code
+ fi
+}
diff --git a/tools/testing/selftests/ublk/test_loop_01.sh b/tools/testing/selftests/ublk/test_loop_01.sh
new file mode 100755
index 000000000000..10c73ec0a01a
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_loop_01.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+. test_common.sh
+
+TID="loop_01"
+ERR_CODE=0
+
+# prepare & register and pin bpf prog
+_prep_bpf_test "loop" ublk_loop.bpf.o
+
+backfile_0=`_create_backfile 256M`
+
+# add two ublk null disks with the pinned bpf prog
+_add_ublk_dev -t loop -n 0 --bpf_prog 16 --bpf_aio_prog 16 --quiet $backfile_0
+
+# run fio over the ublk disk
+fio --name=write_and_verify \
+ --filename=/dev/ublkb0 \
+ --ioengine=libaio --iodepth=4 \
+ --rw=write \
+ --size=256M \
+ --direct=1 \
+ --verify=crc32c \
+ --do_verify=1 \
+ --bs=4k > /dev/null 2>&1
+ERR_CODE=$?
+
+# cleanup & unregister and unpin the bpf prog
+_cleanup_bpf_test "loop"
+
+_remove_backfile $backfile_0
+
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/test_loop_02.sh b/tools/testing/selftests/ublk/test_loop_02.sh
new file mode 100755
index 000000000000..05c3a863f517
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_loop_02.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+. test_common.sh
+
+TID="loop_02"
+ERR_CODE=0
+
+# prepare & register and pin bpf prog
+_prep_bpf_test "loop" ublk_loop.bpf.o
+
+backfile_0=`_create_backfile 256M`
+
+# add two ublk null disks with the pinned bpf prog
+_add_ublk_dev -t loop -n 0 --bpf_prog 16 --bpf_aio_prog 16 --quiet $backfile_0
+
+_mkfs_mount_test /dev/ublkb0
+ERR_CODE=$?
+
+# cleanup & unregister and unpin the bpf prog
+_cleanup_bpf_test "loop"
+
+_remove_backfile $backfile_0
+
+_show_result $TID $ERR_CODE
diff --git a/tools/testing/selftests/ublk/ublk_bpf.c b/tools/testing/selftests/ublk/ublk_bpf.c
index e2c2e92268e1..c24d5e18a1b1 100644
--- a/tools/testing/selftests/ublk/ublk_bpf.c
+++ b/tools/testing/selftests/ublk/ublk_bpf.c
@@ -64,6 +64,7 @@ struct dev_ctx {
int nr_files;
char *files[MAX_BACK_FILES];
int bpf_prog_id;
+ int bpf_aio_prog_id;
unsigned int logging:1;
unsigned int all:1;
};
@@ -107,7 +108,10 @@ struct ublk_tgt {
unsigned int cq_depth;
const struct ublk_tgt_ops *ops;
struct ublk_params params;
- char backing_file[1024 - 8 - sizeof(struct ublk_params)];
+
+ int nr_backing_files;
+ unsigned long backing_file_size[MAX_BACK_FILES];
+ char backing_file[MAX_BACK_FILES][PATH_MAX];
};
struct ublk_queue {
@@ -133,12 +137,13 @@ struct ublk_dev {
struct ublksrv_ctrl_dev_info dev_info;
struct ublk_queue q[UBLK_MAX_QUEUES];
- int fds[2]; /* fds[0] points to /dev/ublkcN */
+ int fds[MAX_BACK_FILES + 1]; /* fds[0] points to /dev/ublkcN */
int nr_fds;
int ctrl_fd;
struct io_uring ring;
int bpf_prog_id;
+ int bpf_aio_prog_id;
};
#ifndef offsetof
@@ -983,7 +988,7 @@ static int cmd_dev_add(struct dev_ctx *ctx)
struct ublk_dev *dev;
int dev_id = ctx->dev_id;
char ublkb[64];
- int ret;
+ int ret, i;
ops = ublk_find_tgt(tgt_type);
if (!ops) {
@@ -1022,6 +1027,13 @@ static int cmd_dev_add(struct dev_ctx *ctx)
dev->tgt.sq_depth = depth;
dev->tgt.cq_depth = depth;
dev->bpf_prog_id = ctx->bpf_prog_id;
+ dev->bpf_aio_prog_id = ctx->bpf_aio_prog_id;
+ for (i = 0; i < MAX_BACK_FILES; i++) {
+ if (ctx->files[i]) {
+ strcpy(dev->tgt.backing_file[i], ctx->files[i]);
+ dev->tgt.nr_backing_files++;
+ }
+ }
ret = ublk_ctrl_add_dev(dev);
if (ret < 0) {
@@ -1271,14 +1283,14 @@ static int cmd_dev_reg_bpf(struct dev_ctx *ctx)
static int cmd_dev_help(char *exe)
{
- printf("%s add -t [null] [-q nr_queues] [-d depth] [-n dev_id] [--bpf_prog ublk_prog_id] [backfile1] [backfile2] ...\n", exe);
+ printf("%s add -t [null|loop] [-q nr_queues] [-d depth] [-n dev_id] [--bpf_prog ublk_prog_id] [--bpf_aio_prog ublk_aio_prog_id] [backfile1] [backfile2] ...\n", exe);
printf("\t default: nr_queues=2(max 4), depth=128(max 128), dev_id=-1(auto allocation)\n");
printf("%s del [-n dev_id] -a \n", exe);
printf("\t -a delete all devices -n delete specified device\n");
printf("%s list [-n dev_id] -a \n", exe);
printf("\t -a list all devices, -n list specified device, default -a \n");
- printf("%s reg -t [null] bpf_prog_obj_path \n", exe);
- printf("%s unreg -t [null]\n", exe);
+ printf("%s reg -t [null|loop] bpf_prog_obj_path \n", exe);
+ printf("%s unreg -t [null|loop]\n", exe);
return 0;
}
@@ -1356,12 +1368,125 @@ static int ublk_null_queue_io(struct ublk_queue *q, int tag)
return 0;
}
+static void backing_file_tgt_deinit(struct ublk_dev *dev)
+{
+ int i;
+
+ for (i = 1; i < dev->nr_fds; i++) {
+ fsync(dev->fds[i]);
+ close(dev->fds[i]);
+ }
+}
+
+static int backing_file_tgt_init(struct ublk_dev *dev)
+{
+ int fd, i;
+
+ assert(dev->nr_fds == 1);
+
+ for (i = 0; i < dev->tgt.nr_backing_files; i++) {
+ char *file = dev->tgt.backing_file[i];
+ unsigned long bytes;
+ struct stat st;
+
+ ublk_dbg(UBLK_DBG_DEV, "%s: file %d: %s\n", __func__, i, file);
+
+ fd = open(file, O_RDWR | O_DIRECT);
+ if (fd < 0) {
+ ublk_err("%s: backing file %s can't be opened: %s\n",
+ __func__, file, strerror(errno));
+ return -EBADF;
+ }
+
+ if (fstat(fd, &st) < 0) {
+ close(fd);
+ return -EBADF;
+ }
+
+ if (S_ISREG(st.st_mode))
+ bytes = st.st_size;
+ else if (S_ISBLK(st.st_mode)) {
+ if (ioctl(fd, BLKGETSIZE64, &bytes) != 0)
+ return -1;
+ } else {
+ return -EINVAL;
+ }
+
+ dev->tgt.backing_file_size[i] = bytes;
+ dev->fds[dev->nr_fds] = fd;
+ dev->nr_fds += 1;
+ }
+
+ return 0;
+}
+
+static int loop_bpf_setup_fd(unsigned dev_id, int fd)
+{
+ int map_fd;
+ int err;
+
+ map_fd = bpf_obj_get("/sys/fs/bpf/ublk/loop/fd_map");
+ if (map_fd < 0) {
+ ublk_err("Error getting map file descriptor from pinned map\n");
+ return -EINVAL;
+ }
+
+ err = bpf_map_update_elem(map_fd, &dev_id, &fd, BPF_ANY);
+ if (err) {
+ ublk_err("Error updating map element: %d\n", errno);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ublk_loop_tgt_init(struct ublk_dev *dev)
+{
+ unsigned long long bytes;
+ int ret;
+ struct ublk_params p = {
+ .types = UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_BPF,
+ .basic = {
+ .logical_bs_shift = 9,
+ .physical_bs_shift = 12,
+ .io_opt_shift = 12,
+ .io_min_shift = 9,
+ .max_sectors = dev->dev_info.max_io_buf_bytes >> 9,
+ },
+ .bpf = {
+ .flags = UBLK_BPF_HAS_OPS_ID | UBLK_BPF_HAS_AIO_OPS_ID,
+ .ops_id = dev->bpf_prog_id,
+ .aio_ops_id = dev->bpf_aio_prog_id,
+ },
+ };
+
+ assert(dev->tgt.nr_backing_files == 1);
+ ret = backing_file_tgt_init(dev);
+ if (ret)
+ return ret;
+
+ assert(loop_bpf_setup_fd(dev->dev_info.dev_id, dev->fds[1]) == 0);
+
+ bytes = dev->tgt.backing_file_size[0];
+ dev->tgt.dev_size = bytes;
+ p.basic.dev_sectors = bytes >> 9;
+ dev->tgt.params = p;
+
+ return 0;
+}
+
+
static const struct ublk_tgt_ops tgt_ops_list[] = {
{
.name = "null",
.init_tgt = ublk_null_tgt_init,
.queue_io = ublk_null_queue_io,
},
+ {
+ .name = "loop",
+ .init_tgt = ublk_loop_tgt_init,
+ .deinit_tgt = backing_file_tgt_deinit,
+ },
};
static const struct ublk_tgt_ops *ublk_find_tgt(const char *name)
@@ -1389,6 +1514,7 @@ int main(int argc, char *argv[])
{ "debug_mask", 1, NULL, 0 },
{ "quiet", 0, NULL, 0 },
{ "bpf_prog", 1, NULL, 0 },
+ { "bpf_aio_prog", 1, NULL, 0 },
{ 0, 0, 0, 0 }
};
int option_idx, opt;
@@ -1398,6 +1524,7 @@ int main(int argc, char *argv[])
.nr_hw_queues = 2,
.dev_id = -1,
.bpf_prog_id = -1,
+ .bpf_aio_prog_id = -1,
};
int ret = -EINVAL, i;
@@ -1433,6 +1560,8 @@ int main(int argc, char *argv[])
ctx.bpf_prog_id = strtol(optarg, NULL, 10);
ctx.flags |= UBLK_F_BPF;
}
+ if (!strcmp(longopts[option_idx].name, "bpf_aio_prog"))
+ ctx.bpf_aio_prog_id = strtol(optarg, NULL, 10);
break;
}
}
--
2.47.0
next prev parent reply other threads:[~2025-01-07 12:09 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-07 12:03 [RFC PATCH 00/22] ublk: support bpf Ming Lei
2025-01-07 12:03 ` [RFC PATCH 01/22] ublk: remove two unused fields from 'struct ublk_queue' Ming Lei
2025-01-07 12:03 ` [RFC PATCH 02/22] ublk: convert several bool type fields into bitfield of `ublk_queue` Ming Lei
2025-01-07 12:03 ` [RFC PATCH 03/22] ublk: add helper of ublk_need_map_io() Ming Lei
2025-01-07 12:03 ` [RFC PATCH 04/22] ublk: move ublk into one standalone directory Ming Lei
2025-01-07 12:03 ` [RFC PATCH 05/22] ublk: move private definitions into private header Ming Lei
2025-01-07 12:03 ` [RFC PATCH 06/22] ublk: move several helpers to " Ming Lei
2025-01-07 12:03 ` [RFC PATCH 07/22] ublk: bpf: add bpf prog attach helpers Ming Lei
2025-01-07 12:03 ` [RFC PATCH 08/22] ublk: bpf: add bpf struct_ops Ming Lei
2025-01-10 1:43 ` Alexei Starovoitov
2025-01-13 4:08 ` Ming Lei
2025-01-13 21:30 ` Alexei Starovoitov
2025-01-15 11:58 ` Ming Lei
2025-01-15 20:11 ` Amery Hung
2025-01-07 12:04 ` [RFC PATCH 09/22] ublk: bpf: attach bpf prog to ublk device Ming Lei
2025-01-07 12:04 ` [RFC PATCH 10/22] ublk: bpf: add kfunc for ublk bpf prog Ming Lei
2025-01-07 12:04 ` [RFC PATCH 11/22] ublk: bpf: enable ublk-bpf Ming Lei
2025-01-07 12:04 ` [RFC PATCH 12/22] selftests: ublk: add tests for the ublk-bpf initial implementation Ming Lei
2025-01-07 12:04 ` [RFC PATCH 13/22] selftests: ublk: add tests for covering io split Ming Lei
2025-01-07 12:04 ` [RFC PATCH 14/22] selftests: ublk: add tests for covering redirecting to userspace Ming Lei
2025-01-07 12:04 ` [RFC PATCH 15/22] ublk: bpf: add bpf aio kfunc Ming Lei
2025-01-07 12:04 ` [RFC PATCH 16/22] ublk: bpf: add bpf aio struct_ops Ming Lei
2025-01-07 12:04 ` [RFC PATCH 17/22] ublk: bpf: attach bpf aio prog to ublk device Ming Lei
2025-01-07 12:04 ` [RFC PATCH 18/22] ublk: bpf: add several ublk bpf aio kfuncs Ming Lei
2025-01-07 12:04 ` [RFC PATCH 19/22] ublk: bpf: wire bpf aio with ublk io handling Ming Lei
2025-01-07 12:04 ` Ming Lei [this message]
2025-01-07 12:04 ` [RFC PATCH 21/22] selftests: add tests for covering both bpf aio and split Ming Lei
2025-01-07 12:04 ` [RFC PATCH 22/22] ublk: document ublk-bpf & bpf-aio Ming Lei
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=20250107120417.1237392-21-tom.leiming@gmail.com \
--to=tom.leiming@gmail.com \
--cc=ast@kernel.org \
--cc=axboe@kernel.dk \
--cc=bpf@vger.kernel.org \
--cc=linux-block@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=yonghong.song@linux.dev \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.