uringmachine 0.19.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +3 -4
  3. data/CHANGELOG.md +32 -1
  4. data/TODO.md +0 -39
  5. data/examples/bm_fileno.rb +33 -0
  6. data/examples/bm_mutex.rb +85 -0
  7. data/examples/bm_mutex_single.rb +33 -0
  8. data/examples/bm_queue.rb +29 -29
  9. data/examples/bm_send.rb +2 -5
  10. data/examples/bm_snooze.rb +20 -42
  11. data/examples/bm_write.rb +4 -1
  12. data/examples/fiber_scheduler_demo.rb +15 -51
  13. data/examples/fiber_scheduler_fork.rb +24 -0
  14. data/examples/nc_ssl.rb +71 -0
  15. data/ext/um/extconf.rb +5 -15
  16. data/ext/um/um.c +310 -74
  17. data/ext/um/um.h +66 -29
  18. data/ext/um/um_async_op.c +1 -1
  19. data/ext/um/um_async_op_class.c +2 -2
  20. data/ext/um/um_buffer.c +1 -1
  21. data/ext/um/um_class.c +178 -31
  22. data/ext/um/um_const.c +51 -3
  23. data/ext/um/um_mutex_class.c +1 -1
  24. data/ext/um/um_op.c +37 -0
  25. data/ext/um/um_queue_class.c +1 -1
  26. data/ext/um/um_stream.c +5 -5
  27. data/ext/um/um_stream_class.c +3 -0
  28. data/ext/um/um_sync.c +28 -39
  29. data/ext/um/um_utils.c +59 -19
  30. data/grant-2025/journal.md +353 -0
  31. data/grant-2025/tasks.md +135 -0
  32. data/lib/uringmachine/fiber_scheduler.rb +316 -57
  33. data/lib/uringmachine/version.rb +1 -1
  34. data/lib/uringmachine.rb +6 -0
  35. data/test/test_fiber_scheduler.rb +640 -0
  36. data/test/test_stream.rb +2 -2
  37. data/test/test_um.rb +722 -54
  38. data/uringmachine.gemspec +5 -5
  39. data/vendor/liburing/.github/workflows/ci.yml +94 -1
  40. data/vendor/liburing/.github/workflows/test_build.c +9 -0
  41. data/vendor/liburing/configure +27 -0
  42. data/vendor/liburing/examples/Makefile +6 -0
  43. data/vendor/liburing/examples/helpers.c +8 -0
  44. data/vendor/liburing/examples/helpers.h +5 -0
  45. data/vendor/liburing/liburing.spec +1 -1
  46. data/vendor/liburing/src/Makefile +9 -3
  47. data/vendor/liburing/src/include/liburing/barrier.h +11 -5
  48. data/vendor/liburing/src/include/liburing/io_uring/query.h +41 -0
  49. data/vendor/liburing/src/include/liburing/io_uring.h +51 -0
  50. data/vendor/liburing/src/include/liburing/sanitize.h +16 -4
  51. data/vendor/liburing/src/include/liburing.h +458 -121
  52. data/vendor/liburing/src/liburing-ffi.map +16 -0
  53. data/vendor/liburing/src/liburing.map +8 -0
  54. data/vendor/liburing/src/sanitize.c +4 -1
  55. data/vendor/liburing/src/setup.c +7 -4
  56. data/vendor/liburing/test/232c93d07b74.c +4 -16
  57. data/vendor/liburing/test/Makefile +15 -1
  58. data/vendor/liburing/test/accept.c +2 -13
  59. data/vendor/liburing/test/bind-listen.c +175 -13
  60. data/vendor/liburing/test/conn-unreach.c +132 -0
  61. data/vendor/liburing/test/fd-pass.c +32 -7
  62. data/vendor/liburing/test/fdinfo.c +39 -12
  63. data/vendor/liburing/test/fifo-futex-poll.c +114 -0
  64. data/vendor/liburing/test/fifo-nonblock-read.c +1 -12
  65. data/vendor/liburing/test/futex.c +1 -1
  66. data/vendor/liburing/test/helpers.c +99 -2
  67. data/vendor/liburing/test/helpers.h +9 -0
  68. data/vendor/liburing/test/io_uring_passthrough.c +6 -12
  69. data/vendor/liburing/test/mock_file.c +379 -0
  70. data/vendor/liburing/test/mock_file.h +47 -0
  71. data/vendor/liburing/test/nop.c +2 -2
  72. data/vendor/liburing/test/nop32-overflow.c +150 -0
  73. data/vendor/liburing/test/nop32.c +126 -0
  74. data/vendor/liburing/test/pipe.c +166 -0
  75. data/vendor/liburing/test/poll-race-mshot.c +13 -1
  76. data/vendor/liburing/test/read-write.c +4 -4
  77. data/vendor/liburing/test/recv-mshot-fair.c +81 -34
  78. data/vendor/liburing/test/recvsend_bundle.c +1 -1
  79. data/vendor/liburing/test/resize-rings.c +2 -0
  80. data/vendor/liburing/test/ring-query.c +322 -0
  81. data/vendor/liburing/test/ringbuf-loop.c +87 -0
  82. data/vendor/liburing/test/ringbuf-read.c +4 -4
  83. data/vendor/liburing/test/runtests.sh +2 -2
  84. data/vendor/liburing/test/send-zerocopy.c +43 -5
  85. data/vendor/liburing/test/send_recv.c +103 -32
  86. data/vendor/liburing/test/shutdown.c +2 -12
  87. data/vendor/liburing/test/socket-nb.c +3 -14
  88. data/vendor/liburing/test/socket-rw-eagain.c +2 -12
  89. data/vendor/liburing/test/socket-rw-offset.c +2 -12
  90. data/vendor/liburing/test/socket-rw.c +2 -12
  91. data/vendor/liburing/test/sqe-mixed-bad-wrap.c +87 -0
  92. data/vendor/liburing/test/sqe-mixed-nop.c +82 -0
  93. data/vendor/liburing/test/sqe-mixed-uring_cmd.c +153 -0
  94. data/vendor/liburing/test/timestamp.c +56 -19
  95. data/vendor/liburing/test/vec-regbuf.c +2 -4
  96. data/vendor/liburing/test/wq-aff.c +7 -0
  97. metadata +37 -15
@@ -57,7 +57,7 @@ static void fdinfo_read(struct io_uring *ring)
57
57
 
58
58
  static int __test_io(const char *file, struct io_uring *ring, int write,
59
59
  int buffered, int sqthread, int fixed, int nonvec,
60
- int buf_select, int seq, int exp_len)
60
+ int buf_select, int seq, int exp_len, int mixed)
61
61
  {
62
62
  struct io_uring_sqe *sqe;
63
63
  struct io_uring_cqe *cqe;
@@ -66,9 +66,9 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
66
66
  off_t offset;
67
67
 
68
68
  #ifdef VERBOSE
69
- fprintf(stdout, "%s: start %d/%d/%d/%d/%d: ", __FUNCTION__, write,
69
+ fprintf(stdout, "%s: start %d/%d/%d/%d/%d/%d: ", __FUNCTION__, write,
70
70
  buffered, sqthread,
71
- fixed, nonvec);
71
+ fixed, nonvec, mixed);
72
72
  #endif
73
73
  if (write)
74
74
  open_flags = O_WRONLY;
@@ -107,6 +107,17 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
107
107
 
108
108
  offset = 0;
109
109
  for (i = 0; i < BUFFERS; i++) {
110
+ if (mixed && i & 1) {
111
+ sqe = io_uring_get_sqe128(ring);
112
+ if (!sqe) {
113
+ fprintf(stderr, "sqe get failed\n");
114
+ goto err;
115
+ }
116
+ io_uring_prep_nop128(sqe);
117
+ sqe->user_data = i;
118
+ continue;
119
+ }
120
+
110
121
  sqe = io_uring_get_sqe(ring);
111
122
  if (!sqe) {
112
123
  fprintf(stderr, "sqe get failed\n");
@@ -167,12 +178,17 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
167
178
  offset += BS;
168
179
  }
169
180
 
181
+ __io_uring_flush_sq(ring);
170
182
  fdinfo_read(ring);
171
183
 
172
184
  ret = io_uring_submit(ring);
173
- if (ret != BUFFERS) {
185
+ if (!mixed && ret != BUFFERS) {
174
186
  fprintf(stderr, "submit got %d, wanted %d\n", ret, BUFFERS);
175
187
  goto err;
188
+ } else if (mixed && ret != BUFFERS + (BUFFERS >> 1)) {
189
+ fprintf(stderr, "submit got %d, wanted %d\n", ret,
190
+ BUFFERS + (BUFFERS >> 1));
191
+ goto err;
176
192
  }
177
193
 
178
194
  for (i = 0; i < 10; i++) {
@@ -186,7 +202,13 @@ static int __test_io(const char *file, struct io_uring *ring, int write,
186
202
  fprintf(stderr, "wait_cqe=%d\n", ret);
187
203
  goto err;
188
204
  }
189
- if (cqe->res == -EINVAL && nonvec) {
205
+ if (mixed && cqe->user_data & 1) {
206
+ if (cqe->user_data > 32) {
207
+ fprintf(stderr, "cqe user data %lld, max expected %d\n",
208
+ cqe->user_data, BUFFERS - 1);
209
+ goto err;
210
+ }
211
+ } else if (cqe->res == -EINVAL && nonvec) {
190
212
  if (!warned) {
191
213
  fprintf(stdout, "Non-vectored IO not "
192
214
  "supported, skipping\n");
@@ -252,15 +274,19 @@ err:
252
274
  return 1;
253
275
  }
254
276
  static int test_io(const char *file, int write, int buffered, int sqthread,
255
- int fixed, int nonvec, int exp_len)
277
+ int fixed, int nonvec, int exp_len, int mixed)
256
278
  {
257
279
  struct io_uring ring;
258
- int ret, ring_flags = 0;
280
+ int ret, ring_flags = 0, entries = 64;
259
281
 
260
282
  if (sqthread)
261
283
  ring_flags = IORING_SETUP_SQPOLL;
284
+ if (mixed) {
285
+ ring_flags |= IORING_SETUP_SQE_MIXED;
286
+ entries = 128;
287
+ }
262
288
 
263
- ret = t_create_ring(64, &ring, ring_flags);
289
+ ret = t_create_ring(entries, &ring, ring_flags);
264
290
  if (ret == T_SETUP_SKIP)
265
291
  return 0;
266
292
  if (ret != T_SETUP_OK) {
@@ -269,7 +295,7 @@ static int test_io(const char *file, int write, int buffered, int sqthread,
269
295
  }
270
296
 
271
297
  ret = __test_io(file, &ring, write, buffered, sqthread, fixed, nonvec,
272
- 0, 0, exp_len);
298
+ 0, 0, exp_len, mixed);
273
299
  io_uring_queue_exit(&ring);
274
300
  return ret;
275
301
  }
@@ -379,17 +405,18 @@ int main(int argc, char *argv[])
379
405
  vecs = t_create_buffers(BUFFERS, BS);
380
406
 
381
407
  /* if we don't have nonvec read, skip testing that */
382
- nr = has_nonvec_read() ? 32 : 16;
408
+ nr = has_nonvec_read() ? 64 : 32;
383
409
 
384
410
  for (i = 0; i < nr; i++) {
385
411
  int write = (i & 1) != 0;
386
412
  int buffered = (i & 2) != 0;
387
413
  int sqthread = (i & 4) != 0;
388
414
  int fixed = (i & 8) != 0;
389
- int nonvec = (i & 16) != 0;
415
+ int mixed = (i & 16) != 0;
416
+ int nonvec = (i & 32) != 0;
390
417
 
391
418
  ret = test_io(fname, write, buffered, sqthread, fixed, nonvec,
392
- BS);
419
+ BS, mixed);
393
420
  if (ret == T_EXIT_SKIP)
394
421
  continue;
395
422
  if (ret) {
@@ -0,0 +1,114 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: Run a failing futex wait command followed up a POLL_ADD
4
+ * on a fifo.
5
+ *
6
+ */
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+ #include <linux/futex.h>
10
+ #include <linux/poll.h>
11
+ #include <unistd.h>
12
+
13
+ #include "liburing.h"
14
+ #include "helpers.h"
15
+
16
+ #ifndef FUTEX2_SIZE_U32
17
+ #define FUTEX2_SIZE_U32 0x02
18
+ #endif
19
+
20
+ int main(int argc, char *argv[])
21
+ {
22
+ struct io_uring_sqe *sqe;
23
+ struct io_uring_cqe *cqe;
24
+ struct io_uring ring;
25
+ int ret, pipe;
26
+
27
+ if (argc > 1)
28
+ return T_EXIT_SKIP;
29
+
30
+ /*
31
+ * Setup a FIFO for polling. FIFOs are interesting because they end
32
+ * up using two wait queue entries for poll, hitting double poll
33
+ * in io_uring.
34
+ */
35
+ ret = mkfifo("fifo", 0644);
36
+ if (ret < 0) {
37
+ perror("mkfifo");
38
+ return 1;
39
+ }
40
+ pipe = open("fifo", O_RDWR);
41
+ if (pipe < 0) {
42
+ perror("open fifo");
43
+ ret = T_EXIT_FAIL;
44
+ goto err;
45
+ }
46
+
47
+ ret = io_uring_queue_init(64, &ring, 0);
48
+ if (ret) {
49
+ ret = T_EXIT_FAIL;
50
+ goto err;
51
+ }
52
+
53
+ /*
54
+ * Submit invalid futex wait, will error inline.
55
+ */
56
+ sqe = io_uring_get_sqe(&ring);
57
+ io_uring_prep_futex_wait(sqe, NULL, 0, FUTEX_BITSET_MATCH_ANY, FUTEX2_SIZE_U32, 0);
58
+ sqe->user_data = 1;
59
+ io_uring_submit(&ring);
60
+
61
+ ret = io_uring_wait_cqe(&ring, &cqe);
62
+ if (ret) {
63
+ fprintf(stderr, "wait %d \n", ret);
64
+ ret = T_EXIT_FAIL;
65
+ goto err_ring;
66
+ }
67
+ if (cqe->res != -EFAULT) {
68
+ if (cqe->res == -EINVAL) {
69
+ ret = T_EXIT_SKIP;
70
+ goto err_ring;
71
+ }
72
+ fprintf(stderr, "Unexpected futex return: %d\n", cqe->res);
73
+ ret = T_EXIT_FAIL;
74
+ goto err_ring;
75
+ }
76
+ io_uring_cqe_seen(&ring, cqe);
77
+
78
+ ret = io_uring_register_files(&ring, &pipe, 1);
79
+ if (ret < 0) {
80
+ fprintf(stderr, "io_uring register files failed \n");
81
+ ret = T_EXIT_FAIL;
82
+ goto err_ring;
83
+ }
84
+
85
+ /*
86
+ * Submit poll request for POLLIN on the fifo
87
+ */
88
+ sqe = io_uring_get_sqe(&ring);
89
+ io_uring_prep_poll_add(sqe, 0, POLLIN);
90
+ sqe->flags |= IOSQE_FIXED_FILE;
91
+ sqe->user_data = 2;
92
+ io_uring_submit(&ring);
93
+
94
+ /*
95
+ * Trigger the poll request
96
+ */
97
+ ret = write(pipe, "FIFO test\n", 10);
98
+ if (ret < 0)
99
+ perror("fifo write");
100
+
101
+ ret = io_uring_wait_cqe(&ring, &cqe);
102
+ if (ret) {
103
+ fprintf(stderr, "wait %d \n", ret);
104
+ ret = T_EXIT_FAIL;
105
+ }
106
+ io_uring_cqe_seen(&ring, cqe);
107
+ err_ring:
108
+ io_uring_queue_exit(&ring);
109
+ err:
110
+ if (pipe != -1)
111
+ close(pipe);
112
+ unlink("fifo");
113
+ return ret;
114
+ }
@@ -18,7 +18,6 @@ int main(int argc, char *argv[])
18
18
  struct io_uring ring;
19
19
  char buf[32];
20
20
  int fds[2];
21
- int flags;
22
21
  int ret;
23
22
 
24
23
  io_uring_queue_init(1, &ring, 0);
@@ -28,17 +27,7 @@ int main(int argc, char *argv[])
28
27
  return T_EXIT_FAIL;
29
28
  }
30
29
 
31
- flags = fcntl(fds[0], F_GETFL, 0);
32
- if (flags < 0) {
33
- perror("fcntl get");
34
- return T_EXIT_FAIL;
35
- }
36
- flags |= O_NONBLOCK;
37
- ret = fcntl(fds[0], F_SETFL, flags);
38
- if (ret < 0) {
39
- perror("fcntl set");
40
- return T_EXIT_FAIL;
41
- }
30
+ t_set_nonblock(fds[0]);
42
31
 
43
32
  sqe = io_uring_get_sqe(&ring);
44
33
  io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
@@ -149,7 +149,7 @@ static int test(int flags, int vectored)
149
149
  return ret;
150
150
 
151
151
  for (i = 0; i < LOOPS; i++) {
152
- int async_cancel = (!i % 2);
152
+ int async_cancel = !(i % 2);
153
153
  int async_wait = !(i % 3);
154
154
  ret = __test(&ring, vectored, async_wait, async_cancel);
155
155
  if (ret) {
@@ -136,9 +136,10 @@ enum t_setup_ret t_create_ring_params(int depth, struct io_uring *ring,
136
136
  fprintf(stdout, "SQPOLL skipped for regular user\n");
137
137
  return T_SETUP_SKIP;
138
138
  }
139
+ if (ret == -EINVAL)
140
+ return T_SETUP_SKIP;
139
141
 
140
- if (ret != -EINVAL)
141
- fprintf(stderr, "queue_init: %s\n", strerror(-ret));
142
+ fprintf(stderr, "queue_init: %s\n", strerror(-ret));
142
143
  return ret;
143
144
  }
144
145
 
@@ -484,3 +485,99 @@ int t_create_socketpair_ip(struct sockaddr_storage *addr,
484
485
  }
485
486
  return 0;
486
487
  }
488
+
489
+ static void __t_toggle_nonblock(int fd, int set)
490
+ {
491
+ int flags;
492
+
493
+ flags = fcntl(fd, F_GETFL, 0);
494
+ if (flags < 0)
495
+ t_error(1, errno, "fcntl F_GETFL");
496
+ if (set)
497
+ flags |= O_NONBLOCK;
498
+ else
499
+ flags &= ~O_NONBLOCK;
500
+ if (fcntl(fd, F_SETFL, flags) < 0)
501
+ t_error(1, errno, "fcntl F_SETFL");
502
+ }
503
+
504
+ void t_set_nonblock(int fd)
505
+ {
506
+ __t_toggle_nonblock(fd, 1);
507
+ }
508
+
509
+ void t_clear_nonblock(int fd)
510
+ {
511
+ __t_toggle_nonblock(fd, 0);
512
+ }
513
+
514
+ int t_submit_and_wait_single(struct io_uring *ring, struct io_uring_cqe **cqe)
515
+ {
516
+ int ret;
517
+
518
+ ret = io_uring_submit(ring);
519
+ if (ret <= 0) {
520
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
521
+ return -1;
522
+ }
523
+ ret = io_uring_wait_cqe(ring, cqe);
524
+ if (ret < 0) {
525
+ fprintf(stderr, "wait completion %d\n", ret);
526
+ return ret;
527
+ }
528
+ return 0;
529
+ }
530
+
531
+ size_t t_iovec_data_length(struct iovec *iov, unsigned iov_len)
532
+ {
533
+ size_t sz = 0;
534
+ int i;
535
+
536
+ for (i = 0; i < iov_len; i++)
537
+ sz += iov[i].iov_len;
538
+ return sz;
539
+ }
540
+
541
+ #define t_min(a, b) ((a) < (b) ? (a) : (b))
542
+
543
+ unsigned long t_compare_data_iovec(struct iovec *iov_src, unsigned nr_src,
544
+ struct iovec *iov_dst, unsigned nr_dst)
545
+ {
546
+ size_t src_len = t_iovec_data_length(iov_src, nr_src);
547
+ size_t dst_len = t_iovec_data_length(iov_dst, nr_dst);
548
+ size_t len_left = t_min(src_len, dst_len);
549
+ unsigned long src_off = 0, dst_off = 0;
550
+ unsigned long offset = 0;
551
+
552
+ while (offset != len_left) {
553
+ size_t len = len_left - offset;
554
+ unsigned long i;
555
+
556
+ len = t_min(len, iov_src->iov_len - src_off);
557
+ len = t_min(len, iov_dst->iov_len - dst_off);
558
+
559
+ for (i = 0; i < len; i++) {
560
+ char csrc = ((char *)iov_src->iov_base)[src_off + i];
561
+ char cdst = ((char *)iov_dst->iov_base)[dst_off + i];
562
+
563
+ if (csrc != cdst) {
564
+ fprintf(stderr, "data mismatch, %i vs %i\n",
565
+ csrc, cdst);
566
+ return -EINVAL;
567
+ }
568
+ }
569
+
570
+ src_off += len;
571
+ dst_off += len;
572
+ if (src_off == iov_src->iov_len) {
573
+ src_off = 0;
574
+ iov_src++;
575
+ }
576
+ if (dst_off == iov_dst->iov_len) {
577
+ dst_off = 0;
578
+ iov_dst++;
579
+ }
580
+ offset += len;
581
+ }
582
+ return 0;
583
+ }
@@ -99,6 +99,8 @@ enum t_setup_ret t_register_buffers(struct io_uring *ring,
99
99
  unsigned nr_iovecs);
100
100
 
101
101
  bool t_probe_defer_taskrun(void);
102
+ void t_set_nonblock(int fd);
103
+ void t_clear_nonblock(int fd);
102
104
 
103
105
  unsigned __io_uring_flush_sq(struct io_uring *ring);
104
106
 
@@ -120,6 +122,13 @@ unsigned long long mtime_since_now(struct timeval *tv);
120
122
  unsigned long long utime_since(const struct timeval *s, const struct timeval *e);
121
123
  unsigned long long utime_since_now(struct timeval *tv);
122
124
 
125
+ int t_submit_and_wait_single(struct io_uring *ring, struct io_uring_cqe **cqe);
126
+
127
+ size_t t_iovec_data_length(struct iovec *iov, unsigned iov_len);
128
+
129
+ unsigned long t_compare_data_iovec(struct iovec *iov_src, unsigned nr_src,
130
+ struct iovec *iov_dst, unsigned nr_dst);
131
+
123
132
  #ifdef __cplusplus
124
133
  }
125
134
  #endif
@@ -141,18 +141,16 @@ static int __test_io(const char *file, struct io_uring *ring, int tc, int read,
141
141
 
142
142
  if (sqthread)
143
143
  use_fd = 0;
144
+ if (nonvec)
145
+ io_uring_prep_uring_cmd(sqe, NVME_URING_CMD_IO, use_fd);
146
+ else
147
+ io_uring_prep_uring_cmd(sqe, NVME_URING_CMD_IO_VEC, use_fd);
144
148
  if (fixed && (i & 1))
145
149
  do_fixed = 0;
146
150
  if (do_fixed)
147
151
  sqe->buf_index = 0;
148
152
  if (async)
149
153
  sqe->flags |= IOSQE_ASYNC;
150
- if (nonvec)
151
- sqe->cmd_op = NVME_URING_CMD_IO;
152
- else
153
- sqe->cmd_op = NVME_URING_CMD_IO_VEC;
154
- sqe->fd = use_fd;
155
- sqe->opcode = IORING_OP_URING_CMD;
156
154
  if (do_fixed)
157
155
  sqe->uring_cmd_flags |= IORING_URING_CMD_FIXED;
158
156
  sqe->user_data = ((uint64_t)offset << 32) | i;
@@ -328,9 +326,7 @@ static int test_invalid_passthru_submit(const char *file)
328
326
  }
329
327
 
330
328
  sqe = io_uring_get_sqe(&ring);
331
- io_uring_prep_read(sqe, fd, vecs[0].iov_base, vecs[0].iov_len, 0);
332
- sqe->cmd_op = NVME_URING_CMD_IO;
333
- sqe->opcode = IORING_OP_URING_CMD;
329
+ io_uring_prep_uring_cmd(sqe, NVME_URING_CMD_IO, fd);
334
330
  sqe->user_data = 1;
335
331
  cmd = (struct nvme_uring_cmd *)sqe->cmd;
336
332
  memset(cmd, 0, sizeof(struct nvme_uring_cmd));
@@ -401,10 +397,8 @@ static int test_io_uring_submit_enters(const char *file)
401
397
  __u32 nlb;
402
398
 
403
399
  sqe = io_uring_get_sqe(&ring);
404
- io_uring_prep_readv(sqe, fd, &vecs[i], 1, offset);
400
+ io_uring_prep_uring_cmd(sqe, NVME_URING_CMD_IO, fd);
405
401
  sqe->user_data = i;
406
- sqe->opcode = IORING_OP_URING_CMD;
407
- sqe->cmd_op = NVME_URING_CMD_IO;
408
402
  cmd = (struct nvme_uring_cmd *)sqe->cmd;
409
403
  memset(cmd, 0, sizeof(struct nvme_uring_cmd));
410
404