From: Ming Lei <ming.lei@redhat.com>
To: Jens Axboe <axboe@kernel.dk>, linux-block@vger.kernel.org
Cc: Caleb Sander Mateos <csander@purestorage.com>,
Ming Lei <ming.lei@redhat.com>
Subject: [PATCH v2 10/10] selftests/ublk: add read-only buffer registration test
Date: Tue, 31 Mar 2026 23:32:01 +0800 [thread overview]
Message-ID: <20260331153207.3635125-11-ming.lei@redhat.com> (raw)
In-Reply-To: <20260331153207.3635125-1-ming.lei@redhat.com>
Add --rdonly_shmem_buf option to kublk that registers shared memory
buffers with UBLK_SHMEM_BUF_READ_ONLY (read-only pinning without
FOLL_WRITE) and mmaps with PROT_READ only.
Add test_shmemzc_04.sh which exercises the new flag with a null target,
hugetlbfs buffer, and write workload. Write I/O works because the
server only reads from the shared buffer — the data flows from client
to kernel to the shared pages, and the server reads them out.
Signed-off-by: Ming Lei <ming.lei@redhat.com>
---
tools/testing/selftests/ublk/Makefile | 1 +
tools/testing/selftests/ublk/kublk.c | 17 +++--
tools/testing/selftests/ublk/kublk.h | 1 +
.../testing/selftests/ublk/test_shmemzc_04.sh | 72 +++++++++++++++++++
4 files changed, 86 insertions(+), 5 deletions(-)
create mode 100755 tools/testing/selftests/ublk/test_shmemzc_04.sh
diff --git a/tools/testing/selftests/ublk/Makefile b/tools/testing/selftests/ublk/Makefile
index 3d1ad1730d93..d07f90fdd5b8 100644
--- a/tools/testing/selftests/ublk/Makefile
+++ b/tools/testing/selftests/ublk/Makefile
@@ -54,6 +54,7 @@ TEST_PROGS += test_part_02.sh
TEST_PROGS += test_shmemzc_01.sh
TEST_PROGS += test_shmemzc_02.sh
TEST_PROGS += test_shmemzc_03.sh
+TEST_PROGS += test_shmemzc_04.sh
TEST_PROGS += test_stress_01.sh
TEST_PROGS += test_stress_02.sh
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index bd97e34f131b..7ed2fd5d6a0e 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -1212,11 +1212,13 @@ static void ublk_shmem_unregister_all(void)
shmem_count = 0;
}
-static int ublk_ctrl_reg_buf(struct ublk_dev *dev, void *addr, size_t size)
+static int ublk_ctrl_reg_buf(struct ublk_dev *dev, void *addr, size_t size,
+ __u32 flags)
{
- struct ublk_buf_reg buf_reg = {
+ struct ublk_shmem_buf_reg buf_reg = {
.addr = (unsigned long)addr,
.len = size,
+ .flags = flags,
};
struct ublk_ctrl_cmd_data data = {
.cmd_op = UBLK_U_CMD_REG_BUF,
@@ -1265,7 +1267,7 @@ static void ublk_shmem_handle_client(int sock_fd, struct ublk_dev *dev)
}
/* Register server's VA range with kernel for PFN matching */
- ret = ublk_ctrl_reg_buf(dev, base, size);
+ ret = ublk_ctrl_reg_buf(dev, base, size, 0);
if (ret < 0) {
ublk_dbg(UBLK_DBG_DEV,
"shmem_zc: kernel reg failed %d\n", ret);
@@ -1350,7 +1352,8 @@ static int ublk_shmem_htlb_setup(const struct dev_ctx *ctx,
return -EINVAL;
}
- base = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE,
+ base = mmap(NULL, st.st_size,
+ ctx->rdonly_shmem_buf ? PROT_READ : PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, fd, 0);
if (base == MAP_FAILED) {
ublk_err("htlb: mmap failed\n");
@@ -1358,7 +1361,8 @@ static int ublk_shmem_htlb_setup(const struct dev_ctx *ctx,
return -ENOMEM;
}
- ret = ublk_ctrl_reg_buf(dev, base, st.st_size);
+ ret = ublk_ctrl_reg_buf(dev, base, st.st_size,
+ ctx->rdonly_shmem_buf ? UBLK_SHMEM_BUF_READ_ONLY : 0);
if (ret < 0) {
ublk_err("htlb: reg_buf failed: %d\n", ret);
munmap(base, st.st_size);
@@ -2122,6 +2126,7 @@ int main(int argc, char *argv[])
{ "no_auto_part_scan", 0, NULL, 0 },
{ "shmem_zc", 0, NULL, 0 },
{ "htlb", 1, NULL, 0 },
+ { "rdonly_shmem_buf", 0, NULL, 0 },
{ 0, 0, 0, 0 }
};
const struct ublk_tgt_ops *ops = NULL;
@@ -2241,6 +2246,8 @@ int main(int argc, char *argv[])
ctx.flags |= UBLK_F_SHMEM_ZC;
if (!strcmp(longopts[option_idx].name, "htlb"))
ctx.htlb_path = strdup(optarg);
+ if (!strcmp(longopts[option_idx].name, "rdonly_shmem_buf"))
+ ctx.rdonly_shmem_buf = 1;
break;
case '?':
/*
diff --git a/tools/testing/selftests/ublk/kublk.h b/tools/testing/selftests/ublk/kublk.h
index 20d0a1eab41f..467af9f487e9 100644
--- a/tools/testing/selftests/ublk/kublk.h
+++ b/tools/testing/selftests/ublk/kublk.h
@@ -80,6 +80,7 @@ struct dev_ctx {
unsigned int no_ublk_fixed_fd:1;
unsigned int safe_stop:1;
unsigned int no_auto_part_scan:1;
+ unsigned int rdonly_shmem_buf:1;
__u32 integrity_flags;
__u8 metadata_size;
__u8 pi_offset;
diff --git a/tools/testing/selftests/ublk/test_shmemzc_04.sh b/tools/testing/selftests/ublk/test_shmemzc_04.sh
new file mode 100755
index 000000000000..899de088ece4
--- /dev/null
+++ b/tools/testing/selftests/ublk/test_shmemzc_04.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Test: shmem_zc with read-only buffer registration on null target
+#
+# Same as test_shmemzc_01 but with --rdonly_shmem_buf: pages are pinned
+# without FOLL_WRITE (UBLK_BUF_F_READ). Write I/O works because
+# the server only reads from the shared buffer.
+
+. "$(cd "$(dirname "$0")" && pwd)"/test_common.sh
+
+ERR_CODE=0
+
+_prep_test "shmem_zc" "null target hugetlbfs shmem zero-copy rdonly_buf test"
+
+if ! _have_program fio; then
+ echo "SKIP: fio not available"
+ exit "$UBLK_SKIP_CODE"
+fi
+
+if ! grep -q hugetlbfs /proc/filesystems; then
+ echo "SKIP: hugetlbfs not supported"
+ exit "$UBLK_SKIP_CODE"
+fi
+
+# Allocate hugepages
+OLD_NR_HP=$(cat /proc/sys/vm/nr_hugepages)
+echo 10 > /proc/sys/vm/nr_hugepages
+NR_HP=$(cat /proc/sys/vm/nr_hugepages)
+if [ "$NR_HP" -lt 2 ]; then
+ echo "SKIP: cannot allocate hugepages"
+ echo "$OLD_NR_HP" > /proc/sys/vm/nr_hugepages
+ exit "$UBLK_SKIP_CODE"
+fi
+
+# Mount hugetlbfs
+HTLB_MNT=$(mktemp -d "${UBLK_TEST_DIR}/htlb_mnt_XXXXXX")
+if ! mount -t hugetlbfs none "$HTLB_MNT"; then
+ echo "SKIP: cannot mount hugetlbfs"
+ rmdir "$HTLB_MNT"
+ echo "$OLD_NR_HP" > /proc/sys/vm/nr_hugepages
+ exit "$UBLK_SKIP_CODE"
+fi
+
+HTLB_FILE="$HTLB_MNT/ublk_buf"
+fallocate -l 4M "$HTLB_FILE"
+
+dev_id=$(_add_ublk_dev -t null --shmem_zc --htlb "$HTLB_FILE" --rdonly_shmem_buf)
+_check_add_dev $TID $?
+
+fio --name=htlb_zc_rdonly \
+ --filename=/dev/ublkb"${dev_id}" \
+ --ioengine=io_uring \
+ --rw=randwrite \
+ --direct=1 \
+ --bs=4k \
+ --size=4M \
+ --iodepth=32 \
+ --mem=mmaphuge:"$HTLB_FILE" \
+ > /dev/null 2>&1
+ERR_CODE=$?
+
+# Delete device first so daemon releases the htlb mmap
+_ublk_del_dev "${dev_id}"
+
+rm -f "$HTLB_FILE"
+umount "$HTLB_MNT"
+rmdir "$HTLB_MNT"
+echo "$OLD_NR_HP" > /proc/sys/vm/nr_hugepages
+
+_cleanup_test "shmem_zc"
+
+_show_result $TID $ERR_CODE
--
2.53.0
next prev parent reply other threads:[~2026-03-31 15:33 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-31 15:31 [PATCH v2 00/10] ublk: add shared memory zero-copy support Ming Lei
2026-03-31 15:31 ` [PATCH v2 01/10] ublk: add UBLK_U_CMD_REG_BUF/UNREG_BUF control commands Ming Lei
2026-04-07 19:35 ` Caleb Sander Mateos
2026-04-08 2:23 ` Ming Lei
2026-04-08 15:20 ` Caleb Sander Mateos
2026-04-09 12:18 ` Ming Lei
2026-04-09 21:22 ` Caleb Sander Mateos
2026-04-10 2:28 ` Ming Lei
2026-03-31 15:31 ` [PATCH v2 02/10] ublk: add PFN-based buffer matching in I/O path Ming Lei
2026-04-07 19:47 ` Caleb Sander Mateos
2026-04-08 2:36 ` Ming Lei
2026-04-08 15:28 ` Caleb Sander Mateos
2026-03-31 15:31 ` [PATCH v2 03/10] ublk: enable UBLK_F_SHMEM_ZC feature flag Ming Lei
2026-04-07 19:47 ` Caleb Sander Mateos
2026-04-08 2:50 ` Ming Lei
2026-03-31 15:31 ` [PATCH v2 04/10] ublk: eliminate permanent pages[] array from struct ublk_buf Ming Lei
2026-04-07 19:50 ` Caleb Sander Mateos
2026-04-08 2:58 ` Ming Lei
2026-03-31 15:31 ` [PATCH v2 05/10] selftests/ublk: add shared memory zero-copy support in kublk Ming Lei
2026-03-31 15:31 ` [PATCH v2 06/10] selftests/ublk: add UBLK_F_SHMEM_ZC support for loop target Ming Lei
2026-03-31 15:31 ` [PATCH v2 07/10] selftests/ublk: add shared memory zero-copy test Ming Lei
2026-03-31 15:31 ` [PATCH v2 08/10] selftests/ublk: add hugetlbfs shmem_zc test for loop target Ming Lei
2026-03-31 15:32 ` [PATCH v2 09/10] selftests/ublk: add filesystem fio verify test for shmem_zc Ming Lei
2026-03-31 15:32 ` Ming Lei [this message]
2026-04-07 2:38 ` [PATCH v2 00/10] ublk: add shared memory zero-copy support Ming Lei
2026-04-07 13:34 ` Jens Axboe
2026-04-07 19:29 ` Caleb Sander Mateos
2026-04-08 3:03 ` Ming Lei
2026-04-08 12:52 ` Jens Axboe
2026-04-07 13:44 ` Jens Axboe
2026-04-14 18:56 ` Keith Busch
2026-04-15 8:38 ` 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=20260331153207.3635125-11-ming.lei@redhat.com \
--to=ming.lei@redhat.com \
--cc=axboe@kernel.dk \
--cc=csander@purestorage.com \
--cc=linux-block@vger.kernel.org \
/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.