summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/ublk/kublk.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/ublk/kublk.c')
-rw-r--r--tools/testing/selftests/ublk/kublk.c64
1 files changed, 58 insertions, 6 deletions
diff --git a/tools/testing/selftests/ublk/kublk.c b/tools/testing/selftests/ublk/kublk.c
index f8fa102a627f..185ba553686a 100644
--- a/tools/testing/selftests/ublk/kublk.c
+++ b/tools/testing/selftests/ublk/kublk.c
@@ -596,6 +596,38 @@ static void ublk_set_auto_buf_reg(const struct ublk_queue *q,
sqe->addr = ublk_auto_buf_reg_to_sqe_addr(&buf);
}
+/* Copy in pieces to test the buffer offset logic */
+#define UBLK_USER_COPY_LEN 2048
+
+static void ublk_user_copy(const struct ublk_io *io, __u8 match_ublk_op)
+{
+ const struct ublk_queue *q = ublk_io_to_queue(io);
+ const struct ublksrv_io_desc *iod = ublk_get_iod(q, io->tag);
+ __u64 off = ublk_user_copy_offset(q->q_id, io->tag);
+ __u8 ublk_op = ublksrv_get_op(iod);
+ __u32 len = iod->nr_sectors << 9;
+ void *addr = io->buf_addr;
+
+ if (ublk_op != match_ublk_op)
+ return;
+
+ while (len) {
+ __u32 copy_len = min(len, UBLK_USER_COPY_LEN);
+ ssize_t copied;
+
+ if (ublk_op == UBLK_IO_OP_WRITE)
+ copied = pread(q->ublk_fd, addr, copy_len, off);
+ else if (ublk_op == UBLK_IO_OP_READ)
+ copied = pwrite(q->ublk_fd, addr, copy_len, off);
+ else
+ assert(0);
+ assert(copied == (ssize_t)copy_len);
+ addr += copy_len;
+ off += copy_len;
+ len -= copy_len;
+ }
+}
+
int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
{
struct ublk_queue *q = ublk_io_to_queue(io);
@@ -618,9 +650,12 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
if (io->flags & UBLKS_IO_NEED_GET_DATA)
cmd_op = UBLK_U_IO_NEED_GET_DATA;
- else if (io->flags & UBLKS_IO_NEED_COMMIT_RQ_COMP)
+ else if (io->flags & UBLKS_IO_NEED_COMMIT_RQ_COMP) {
+ if (ublk_queue_use_user_copy(q))
+ ublk_user_copy(io, UBLK_IO_OP_READ);
+
cmd_op = UBLK_U_IO_COMMIT_AND_FETCH_REQ;
- else if (io->flags & UBLKS_IO_NEED_FETCH_RQ)
+ } else if (io->flags & UBLKS_IO_NEED_FETCH_RQ)
cmd_op = UBLK_U_IO_FETCH_REQ;
if (io_uring_sq_space_left(&t->ring) < 1)
@@ -649,7 +684,7 @@ int ublk_queue_io_cmd(struct ublk_thread *t, struct ublk_io *io)
sqe[0]->rw_flags = 0;
cmd->tag = io->tag;
cmd->q_id = q->q_id;
- if (!ublk_queue_no_buf(q))
+ if (!ublk_queue_no_buf(q) && !ublk_queue_use_user_copy(q))
cmd->addr = (__u64) (uintptr_t) io->buf_addr;
else
cmd->addr = 0;
@@ -751,6 +786,10 @@ static void ublk_handle_uring_cmd(struct ublk_thread *t,
if (cqe->res == UBLK_IO_RES_OK) {
assert(tag < q->q_depth);
+
+ if (ublk_queue_use_user_copy(q))
+ ublk_user_copy(io, UBLK_IO_OP_WRITE);
+
if (q->tgt_ops->queue_io)
q->tgt_ops->queue_io(t, q, tag);
} else if (cqe->res == UBLK_IO_RES_NEED_GET_DATA) {
@@ -1507,7 +1546,7 @@ static void __cmd_create_help(char *exe, bool recovery)
printf("%s %s -t [null|loop|stripe|fault_inject] [-q nr_queues] [-d depth] [-n dev_id]\n",
exe, recovery ? "recover" : "add");
- printf("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1 ] [-g]\n");
+ printf("\t[--foreground] [--quiet] [-z] [--auto_zc] [--auto_zc_fallback] [--debug_mask mask] [-r 0|1] [-g] [-u]\n");
printf("\t[-e 0|1 ] [-i 0|1] [--no_ublk_fixed_fd]\n");
printf("\t[--nthreads threads] [--per_io_tasks]\n");
printf("\t[target options] [backfile1] [backfile2] ...\n");
@@ -1568,6 +1607,7 @@ int main(int argc, char *argv[])
{ "get_data", 1, NULL, 'g'},
{ "auto_zc", 0, NULL, 0 },
{ "auto_zc_fallback", 0, NULL, 0 },
+ { "user_copy", 0, NULL, 'u'},
{ "size", 1, NULL, 's'},
{ "nthreads", 1, NULL, 0 },
{ "per_io_tasks", 0, NULL, 0 },
@@ -1593,7 +1633,7 @@ int main(int argc, char *argv[])
opterr = 0;
optind = 2;
- while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:s:gaz",
+ while ((opt = getopt_long(argc, argv, "t:n:d:q:r:e:i:s:gazu",
longopts, &option_idx)) != -1) {
switch (opt) {
case 'a':
@@ -1613,7 +1653,7 @@ int main(int argc, char *argv[])
ctx.queue_depth = strtol(optarg, NULL, 10);
break;
case 'z':
- ctx.flags |= UBLK_F_SUPPORT_ZERO_COPY | UBLK_F_USER_COPY;
+ ctx.flags |= UBLK_F_SUPPORT_ZERO_COPY;
break;
case 'r':
value = strtol(optarg, NULL, 10);
@@ -1633,6 +1673,9 @@ int main(int argc, char *argv[])
case 'g':
ctx.flags |= UBLK_F_NEED_GET_DATA;
break;
+ case 'u':
+ ctx.flags |= UBLK_F_USER_COPY;
+ break;
case 's':
ctx.size = strtoull(optarg, NULL, 10);
break;
@@ -1686,6 +1729,15 @@ int main(int argc, char *argv[])
return -EINVAL;
}
+ if (!!(ctx.flags & UBLK_F_NEED_GET_DATA) +
+ !!(ctx.flags & UBLK_F_USER_COPY) +
+ (ctx.flags & UBLK_F_SUPPORT_ZERO_COPY && !ctx.auto_zc_fallback) +
+ (ctx.flags & UBLK_F_AUTO_BUF_REG && !ctx.auto_zc_fallback) +
+ ctx.auto_zc_fallback > 1) {
+ fprintf(stderr, "too many data copy modes specified\n");
+ return -EINVAL;
+ }
+
i = optind;
while (i < argc && ctx.nr_files < MAX_BACK_FILES) {
ctx.files[ctx.nr_files++] = argv[i++];