uringmachine 0.3 → 0.5

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 (167) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +23 -0
  4. data/README.md +128 -0
  5. data/TODO.md +14 -0
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_write.rb +56 -0
  8. data/examples/dns_client.rb +12 -0
  9. data/examples/echo_server.rb +18 -40
  10. data/examples/http_server.rb +42 -43
  11. data/examples/inout.rb +19 -0
  12. data/examples/nc.rb +36 -0
  13. data/examples/server_client.rb +64 -0
  14. data/examples/snooze.rb +44 -0
  15. data/examples/write_dev_null.rb +16 -0
  16. data/ext/um/extconf.rb +24 -23
  17. data/ext/um/um.c +524 -278
  18. data/ext/um/um.h +146 -44
  19. data/ext/um/um_buffer.c +49 -0
  20. data/ext/um/um_class.c +217 -106
  21. data/ext/um/um_const.c +213 -0
  22. data/ext/um/um_ext.c +4 -0
  23. data/ext/um/um_mutex_class.c +47 -0
  24. data/ext/um/um_op.c +86 -114
  25. data/ext/um/um_queue_class.c +58 -0
  26. data/ext/um/um_sync.c +273 -0
  27. data/ext/um/um_utils.c +49 -4
  28. data/lib/uringmachine/dns_resolver.rb +84 -0
  29. data/lib/uringmachine/version.rb +1 -1
  30. data/lib/uringmachine.rb +28 -0
  31. data/supressions/ruby.supp +71 -0
  32. data/test/helper.rb +8 -0
  33. data/test/test_um.rb +685 -46
  34. data/vendor/liburing/.github/workflows/build.yml +29 -1
  35. data/vendor/liburing/.gitignore +6 -0
  36. data/vendor/liburing/CHANGELOG +16 -0
  37. data/vendor/liburing/CONTRIBUTING.md +165 -0
  38. data/vendor/liburing/configure +64 -0
  39. data/vendor/liburing/examples/Makefile +9 -1
  40. data/vendor/liburing/examples/kdigest.c +405 -0
  41. data/vendor/liburing/examples/proxy.c +75 -8
  42. data/vendor/liburing/examples/reg-wait.c +159 -0
  43. data/vendor/liburing/liburing.pc.in +1 -1
  44. data/vendor/liburing/liburing.spec +1 -1
  45. data/vendor/liburing/src/Makefile +16 -2
  46. data/vendor/liburing/src/include/liburing/io_uring.h +77 -0
  47. data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
  48. data/vendor/liburing/src/include/liburing.h +59 -6
  49. data/vendor/liburing/src/int_flags.h +10 -3
  50. data/vendor/liburing/src/liburing-ffi.map +16 -0
  51. data/vendor/liburing/src/liburing.map +10 -0
  52. data/vendor/liburing/src/queue.c +28 -16
  53. data/vendor/liburing/src/register.c +106 -1
  54. data/vendor/liburing/src/sanitize.c +176 -0
  55. data/vendor/liburing/src/setup.c +47 -19
  56. data/vendor/liburing/src/setup.h +6 -0
  57. data/vendor/liburing/test/35fa71a030ca.c +7 -0
  58. data/vendor/liburing/test/500f9fbadef8.c +2 -0
  59. data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
  60. data/vendor/liburing/test/917257daa0fe.c +7 -0
  61. data/vendor/liburing/test/Makefile +38 -4
  62. data/vendor/liburing/test/a0908ae19763.c +7 -0
  63. data/vendor/liburing/test/a4c0b3decb33.c +7 -0
  64. data/vendor/liburing/test/accept.c +14 -4
  65. data/vendor/liburing/test/b19062a56726.c +7 -0
  66. data/vendor/liburing/test/bind-listen.c +2 -2
  67. data/vendor/liburing/test/buf-ring-nommap.c +10 -3
  68. data/vendor/liburing/test/buf-ring.c +2 -0
  69. data/vendor/liburing/test/cmd-discard.c +427 -0
  70. data/vendor/liburing/test/coredump.c +7 -0
  71. data/vendor/liburing/test/cq-overflow.c +13 -1
  72. data/vendor/liburing/test/d4ae271dfaae.c +11 -3
  73. data/vendor/liburing/test/defer-taskrun.c +2 -2
  74. data/vendor/liburing/test/defer-tw-timeout.c +4 -1
  75. data/vendor/liburing/test/defer.c +2 -2
  76. data/vendor/liburing/test/double-poll-crash.c +1 -1
  77. data/vendor/liburing/test/eeed8b54e0df.c +2 -0
  78. data/vendor/liburing/test/eventfd.c +0 -1
  79. data/vendor/liburing/test/exit-no-cleanup.c +11 -0
  80. data/vendor/liburing/test/fadvise.c +9 -26
  81. data/vendor/liburing/test/fdinfo.c +9 -1
  82. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  83. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  84. data/vendor/liburing/test/file-register.c +14 -2
  85. data/vendor/liburing/test/file-update.c +1 -1
  86. data/vendor/liburing/test/file-verify.c +27 -16
  87. data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
  88. data/vendor/liburing/test/fixed-buf-iter.c +3 -1
  89. data/vendor/liburing/test/fixed-hugepage.c +12 -1
  90. data/vendor/liburing/test/fsnotify.c +1 -0
  91. data/vendor/liburing/test/futex.c +16 -4
  92. data/vendor/liburing/test/helpers.c +47 -0
  93. data/vendor/liburing/test/helpers.h +6 -0
  94. data/vendor/liburing/test/init-mem.c +5 -3
  95. data/vendor/liburing/test/io-cancel.c +0 -24
  96. data/vendor/liburing/test/io_uring_passthrough.c +4 -0
  97. data/vendor/liburing/test/io_uring_register.c +38 -8
  98. data/vendor/liburing/test/iopoll-leak.c +4 -0
  99. data/vendor/liburing/test/iopoll-overflow.c +1 -1
  100. data/vendor/liburing/test/iopoll.c +3 -3
  101. data/vendor/liburing/test/kallsyms.c +203 -0
  102. data/vendor/liburing/test/link-timeout.c +159 -0
  103. data/vendor/liburing/test/linked-defer-close.c +224 -0
  104. data/vendor/liburing/test/madvise.c +12 -25
  105. data/vendor/liburing/test/min-timeout-wait.c +0 -25
  106. data/vendor/liburing/test/min-timeout.c +0 -25
  107. data/vendor/liburing/test/mkdir.c +6 -0
  108. data/vendor/liburing/test/msg-ring.c +8 -2
  109. data/vendor/liburing/test/napi-test.c +16 -3
  110. data/vendor/liburing/test/no-mmap-inval.c +3 -1
  111. data/vendor/liburing/test/nop.c +44 -0
  112. data/vendor/liburing/test/ooo-file-unreg.c +1 -1
  113. data/vendor/liburing/test/open-close.c +40 -0
  114. data/vendor/liburing/test/openat2.c +37 -14
  115. data/vendor/liburing/test/poll-many.c +13 -7
  116. data/vendor/liburing/test/poll-mshot-update.c +17 -10
  117. data/vendor/liburing/test/poll-v-poll.c +6 -3
  118. data/vendor/liburing/test/pollfree.c +148 -0
  119. data/vendor/liburing/test/read-mshot-empty.c +158 -153
  120. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  121. data/vendor/liburing/test/read-mshot.c +282 -27
  122. data/vendor/liburing/test/read-write.c +78 -13
  123. data/vendor/liburing/test/recv-msgall-stream.c +3 -0
  124. data/vendor/liburing/test/recv-msgall.c +5 -0
  125. data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
  126. data/vendor/liburing/test/recvsend_bundle.c +94 -31
  127. data/vendor/liburing/test/reg-fd-only.c +15 -5
  128. data/vendor/liburing/test/reg-wait.c +251 -0
  129. data/vendor/liburing/test/regbuf-clone.c +645 -0
  130. data/vendor/liburing/test/regbuf-merge.c +7 -0
  131. data/vendor/liburing/test/register-restrictions.c +86 -85
  132. data/vendor/liburing/test/rename.c +59 -1
  133. data/vendor/liburing/test/resize-rings.c +643 -0
  134. data/vendor/liburing/test/ringbuf-read.c +5 -0
  135. data/vendor/liburing/test/ringbuf-status.c +5 -1
  136. data/vendor/liburing/test/rsrc_tags.c +1 -1
  137. data/vendor/liburing/test/runtests.sh +16 -1
  138. data/vendor/liburing/test/send-zerocopy.c +59 -0
  139. data/vendor/liburing/test/short-read.c +1 -0
  140. data/vendor/liburing/test/socket.c +43 -0
  141. data/vendor/liburing/test/splice.c +3 -1
  142. data/vendor/liburing/test/sq-poll-dup.c +1 -1
  143. data/vendor/liburing/test/sq-poll-share.c +2 -0
  144. data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
  145. data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
  146. data/vendor/liburing/test/sqpoll-sleep.c +40 -33
  147. data/vendor/liburing/test/sqwait.c +136 -0
  148. data/vendor/liburing/test/statx.c +89 -0
  149. data/vendor/liburing/test/stdout.c +2 -0
  150. data/vendor/liburing/test/submit-and-wait.c +1 -25
  151. data/vendor/liburing/test/submit-reuse.c +4 -26
  152. data/vendor/liburing/test/symlink.c +12 -1
  153. data/vendor/liburing/test/sync-cancel.c +56 -22
  154. data/vendor/liburing/test/thread-exit.c +5 -0
  155. data/vendor/liburing/test/timeout-new.c +1 -26
  156. data/vendor/liburing/test/timeout.c +25 -34
  157. data/vendor/liburing/test/unlink.c +94 -1
  158. data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
  159. data/vendor/liburing/test/waitid.c +62 -8
  160. data/vendor/liburing/test/wq-aff.c +35 -0
  161. data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
  162. data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
  163. metadata +37 -6
  164. data/examples/event_loop.rb +0 -69
  165. data/examples/fibers.rb +0 -105
  166. data/examples/http_server_multishot.rb +0 -57
  167. data/examples/http_server_simpler.rb +0 -34
@@ -0,0 +1,224 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Test that the final close of a file does indeed get it closed, if the
4
+ * ring is setup with DEFER_TASKRUN and the task is waiting in cqring_wait()
5
+ * during. Also see:
6
+ *
7
+ * https://github.com/axboe/liburing/issues/1235
8
+ *
9
+ * for a bug report, and the zig code on which this test program is based.
10
+ */
11
+ #include <stdio.h>
12
+ #include <stdlib.h>
13
+ #include <string.h>
14
+ #include <unistd.h>
15
+ #include <errno.h>
16
+ #include <arpa/inet.h>
17
+ #include <sys/socket.h>
18
+ #include <signal.h>
19
+ #include <pthread.h>
20
+
21
+ #include "liburing.h"
22
+ #include "helpers.h"
23
+
24
+ enum {
25
+ IS_ACCEPT = 0,
26
+ IS_SEND = 0x100,
27
+ IS_SEND2 = 0x101,
28
+ IS_SEND3 = 0x102,
29
+ IS_CLOSE = 0x200,
30
+ };
31
+
32
+ struct thread_data {
33
+ int parent_pid;
34
+ };
35
+
36
+ static void *thread_fn(void *__data)
37
+ {
38
+ struct thread_data *data = __data;
39
+ struct sockaddr_in saddr;
40
+ int sockfd, ret;
41
+ char msg[64];
42
+
43
+ memset(&saddr, 0, sizeof(saddr));
44
+ saddr.sin_family = AF_INET;
45
+ saddr.sin_port = htons(9999);
46
+ inet_pton(AF_INET, "127.0.0.1", &saddr.sin_addr);
47
+
48
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
49
+ if (sockfd < 0) {
50
+ perror("socket");
51
+ goto done;
52
+ }
53
+
54
+ ret = connect(sockfd, (struct sockaddr *) &saddr, sizeof(saddr));
55
+ if (ret < 0) {
56
+ perror("connect");
57
+ close(sockfd);
58
+ goto done;
59
+ }
60
+
61
+ do {
62
+ memset(msg, 0, sizeof(msg));
63
+ ret = recv(sockfd, msg, sizeof(msg), 0);
64
+ } while (ret > 0);
65
+
66
+ close(sockfd);
67
+ done:
68
+ kill(data->parent_pid, SIGUSR1);
69
+ return NULL;
70
+ }
71
+
72
+ /* we got SIGUSR1, exit normally */
73
+ static void sig_usr1(int sig)
74
+ {
75
+ exit(T_EXIT_PASS);
76
+ }
77
+
78
+ /* timed out, failure */
79
+ static void sig_timeout(int sig)
80
+ {
81
+ exit(T_EXIT_FAIL);
82
+ }
83
+
84
+ int main(int argc, char *argv[])
85
+ {
86
+ struct io_uring ring;
87
+ struct io_uring_sqe *sqe;
88
+ struct io_uring_cqe *cqe;
89
+ struct sockaddr_in saddr;
90
+ char *msg1 = "message number 1\n";
91
+ char *msg2 = "message number 2\n";
92
+ char *msg3 = "message number 3\n";
93
+ int val, send_fd, ret, sockfd;
94
+ struct sigaction act[2] = { };
95
+ struct thread_data td;
96
+ pthread_t thread;
97
+
98
+ if (argc > 1)
99
+ return T_EXIT_SKIP;
100
+
101
+ memset(&saddr, 0, sizeof(saddr));
102
+ saddr.sin_family = AF_INET;
103
+ saddr.sin_addr.s_addr = htonl(INADDR_ANY);
104
+ saddr.sin_port = htons(9999);
105
+
106
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
107
+ if (sockfd < 0) {
108
+ perror("socket");
109
+ return T_EXIT_FAIL;
110
+ }
111
+
112
+ val = 1;
113
+ setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
114
+ setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
115
+
116
+ ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
117
+ if (ret < 0) {
118
+ perror("bind");
119
+ close(sockfd);
120
+ return T_EXIT_FAIL;
121
+ }
122
+
123
+ ret = listen(sockfd, 1);
124
+ if (ret < 0) {
125
+ perror("listen");
126
+ close(sockfd);
127
+ return T_EXIT_FAIL;
128
+ }
129
+
130
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER |
131
+ IORING_SETUP_DEFER_TASKRUN);
132
+ if (ret == -EINVAL) {
133
+ close(sockfd);
134
+ return T_EXIT_SKIP;
135
+ }
136
+
137
+ sqe = io_uring_get_sqe(&ring);
138
+ io_uring_prep_multishot_accept(sqe, sockfd, NULL, NULL, 0);
139
+ sqe->user_data = IS_ACCEPT;
140
+ io_uring_submit(&ring);
141
+
142
+ /* check for no multishot accept */
143
+ ret = io_uring_peek_cqe(&ring, &cqe);
144
+ if (!ret && cqe->res == -EINVAL) {
145
+ close(sockfd);
146
+ return T_EXIT_SKIP;
147
+ }
148
+
149
+ /* expected exit */
150
+ act[0].sa_handler = sig_usr1;
151
+ sigaction(SIGUSR1, &act[0], NULL);
152
+
153
+ /* if this hits, we have failed */
154
+ act[1].sa_handler = sig_timeout;
155
+ sigaction(SIGALRM, &act[1], NULL);
156
+ alarm(5);
157
+
158
+ /* start receiver */
159
+ td.parent_pid = getpid();
160
+ pthread_create(&thread, NULL, thread_fn, &td);
161
+
162
+ do {
163
+ ret = io_uring_submit_and_wait(&ring, 1);
164
+ if (ret < 0) {
165
+ fprintf(stderr, "submit: %d\n", ret);
166
+ return T_EXIT_FAIL;
167
+ }
168
+ ret = io_uring_peek_cqe(&ring, &cqe);
169
+ if (ret) {
170
+ fprintf(stderr, "peek: %d\n", ret);
171
+ return T_EXIT_FAIL;
172
+ }
173
+
174
+ switch (cqe->user_data) {
175
+ case IS_ACCEPT:
176
+ send_fd = cqe->res;
177
+ io_uring_cqe_seen(&ring, cqe);
178
+
179
+ /*
180
+ * prep two sends, with the 2nd linked to a close
181
+ * operation. Once the close has been completed, that
182
+ * will terminate the receiving thread and that will
183
+ * in turn send this task a SIGUSR1 signal. If the
184
+ * kernel is buggy, then we never get SIGUSR1 and we
185
+ * will sit forever waiting and be timed out.
186
+ */
187
+ sqe = io_uring_get_sqe(&ring);
188
+ io_uring_prep_send(sqe, send_fd, msg1, strlen(msg1), 0);
189
+ sqe->user_data = IS_SEND;
190
+ sqe->flags = IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_LINK;
191
+
192
+ sqe = io_uring_get_sqe(&ring);
193
+ io_uring_prep_send(sqe, send_fd, msg2, strlen(msg2), 0);
194
+ sqe->user_data = IS_SEND2;
195
+ sqe->flags = IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_LINK;
196
+
197
+ sqe = io_uring_get_sqe(&ring);
198
+ io_uring_prep_send(sqe, send_fd, msg3, strlen(msg3), 0);
199
+ sqe->user_data = IS_SEND3;
200
+ sqe->flags = IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_LINK;
201
+
202
+ sqe = io_uring_get_sqe(&ring);
203
+ io_uring_prep_close(sqe, send_fd);
204
+ sqe->user_data = IS_CLOSE;
205
+ sqe->flags = IOSQE_CQE_SKIP_SUCCESS;
206
+ break;
207
+ case IS_SEND:
208
+ case IS_SEND2:
209
+ fprintf(stderr, "Should not see send response\n");
210
+ io_uring_cqe_seen(&ring, cqe);
211
+ return T_EXIT_FAIL;
212
+ case IS_CLOSE:
213
+ fprintf(stderr, "Should not see close response\n");
214
+ io_uring_cqe_seen(&ring, cqe);
215
+ return T_EXIT_FAIL;
216
+ default:
217
+ fprintf(stderr, "got unknown cqe\n");
218
+ return T_EXIT_FAIL;
219
+ }
220
+ } while (1);
221
+
222
+ /* will never get here */
223
+ return T_EXIT_FAIL;
224
+ }
@@ -20,30 +20,6 @@
20
20
  #define LOOPS 100
21
21
  #define MIN_LOOPS 10
22
22
 
23
- static unsigned long long utime_since(const struct timeval *s,
24
- const struct timeval *e)
25
- {
26
- long long sec, usec;
27
-
28
- sec = e->tv_sec - s->tv_sec;
29
- usec = (e->tv_usec - s->tv_usec);
30
- if (sec > 0 && usec < 0) {
31
- sec--;
32
- usec += 1000000;
33
- }
34
-
35
- sec *= 1000000;
36
- return sec + usec;
37
- }
38
-
39
- static unsigned long long utime_since_now(struct timeval *tv)
40
- {
41
- struct timeval end;
42
-
43
- gettimeofday(&end, NULL);
44
- return utime_since(tv, &end);
45
- }
46
-
47
23
  static int do_madvise(struct io_uring *ring, void *addr, off_t len, int advice)
48
24
  {
49
25
  struct io_uring_sqe *sqe;
@@ -100,6 +76,8 @@ static int test_madvise(struct io_uring *ring, const char *filename)
100
76
 
101
77
  fd = open(filename, O_RDONLY);
102
78
  if (fd < 0) {
79
+ if (errno == EACCES || errno == EPERM)
80
+ return T_EXIT_SKIP;
103
81
  perror("open");
104
82
  return 1;
105
83
  }
@@ -143,9 +121,12 @@ static int test_madvise(struct io_uring *ring, const char *filename)
143
121
  return 1;
144
122
 
145
123
  if (cached_read < uncached_read &&
146
- cached_read2 < uncached_read)
124
+ cached_read2 < uncached_read) {
125
+ free(buf);
147
126
  return 0;
127
+ }
148
128
 
129
+ free(buf);
149
130
  return 2;
150
131
  }
151
132
 
@@ -170,6 +151,8 @@ int main(int argc, char *argv[])
170
151
  good = bad = 0;
171
152
  for (i = 0; i < LOOPS; i++) {
172
153
  ret = test_madvise(&ring, fname);
154
+ if (ret == T_EXIT_SKIP)
155
+ goto skip;
173
156
  if (ret == 1) {
174
157
  fprintf(stderr, "test_madvise failed\n");
175
158
  goto err;
@@ -192,4 +175,8 @@ err:
192
175
  if (fname != argv[1])
193
176
  unlink(fname);
194
177
  return T_EXIT_FAIL;
178
+ skip:
179
+ if (fname != argv[1])
180
+ unlink(fname);
181
+ return T_EXIT_SKIP;
195
182
  }
@@ -22,31 +22,6 @@ struct data {
22
22
  int nr_fds;
23
23
  };
24
24
 
25
- static unsigned long long mtime_since(const struct timeval *s,
26
- const struct timeval *e)
27
- {
28
- long long sec, usec;
29
-
30
- sec = e->tv_sec - s->tv_sec;
31
- usec = (e->tv_usec - s->tv_usec);
32
- if (sec > 0 && usec < 0) {
33
- sec--;
34
- usec += 1000000;
35
- }
36
-
37
- sec *= 1000;
38
- usec /= 1000;
39
- return sec + usec;
40
- }
41
-
42
- static unsigned long long mtime_since_now(struct timeval *tv)
43
- {
44
- struct timeval end;
45
-
46
- gettimeofday(&end, NULL);
47
- return mtime_since(tv, &end);
48
- }
49
-
50
25
  static int time_pass(struct timeval *start, unsigned long min_t,
51
26
  unsigned long max_t, const char *name)
52
27
  {
@@ -61,31 +61,6 @@ static int within_range(unsigned int target, unsigned int msec)
61
61
  return (msec >= low && msec <= high);
62
62
  }
63
63
 
64
- static unsigned long long mtime_since(const struct timeval *s,
65
- const struct timeval *e)
66
- {
67
- long long sec, usec;
68
-
69
- sec = e->tv_sec - s->tv_sec;
70
- usec = (e->tv_usec - s->tv_usec);
71
- if (sec > 0 && usec < 0) {
72
- sec--;
73
- usec += 1000000;
74
- }
75
-
76
- sec *= 1000;
77
- usec /= 1000;
78
- return sec + usec;
79
- }
80
-
81
- static unsigned long long mtime_since_now(struct timeval *tv)
82
- {
83
- struct timeval end;
84
-
85
- gettimeofday(&end, NULL);
86
- return mtime_since(tv, &end);
87
- }
88
-
89
64
  static int test(int flags, int expected_ctx, int min_wait, int write_delay,
90
65
  int nr_cqes, int msec_target)
91
66
  {
@@ -97,6 +97,12 @@ int main(int argc, char *argv[])
97
97
  goto err1;
98
98
  }
99
99
 
100
+ ret = do_mkdirat(&ring, (const char *) (uintptr_t) 0x1234);
101
+ if (ret != -EFAULT) {
102
+ fprintf(stderr, "do_mkdirat bad address: %d\n", ret);
103
+ goto err1;
104
+ }
105
+
100
106
  unlinkat(AT_FDCWD, fn, AT_REMOVEDIR);
101
107
  io_uring_queue_exit(&ring);
102
108
  return T_EXIT_PASS;
@@ -309,6 +309,8 @@ static int test_disabled_ring(struct io_uring *ring, int flags)
309
309
  flags |= IORING_SETUP_R_DISABLED;
310
310
  ret = io_uring_queue_init(8, &disabled_ring, flags);
311
311
  if (ret) {
312
+ if (ret == -EINVAL)
313
+ return T_EXIT_SKIP;
312
314
  fprintf(stderr, "ring setup failed: %d\n", ret);
313
315
  return 1;
314
316
  }
@@ -349,6 +351,8 @@ static int test(int ring_flags)
349
351
 
350
352
  ret = io_uring_queue_init(8, &ring, ring_flags);
351
353
  if (ret) {
354
+ if (ret == -EINVAL)
355
+ return T_EXIT_SKIP;
352
356
  fprintf(stderr, "ring setup failed: %d\n", ret);
353
357
  return T_EXIT_FAIL;
354
358
  }
@@ -452,13 +456,15 @@ int main(int argc, char *argv[])
452
456
  return T_EXIT_SKIP;
453
457
 
454
458
  ret = test(0);
455
- if (ret != T_EXIT_PASS) {
459
+ if (ret == T_EXIT_FAIL) {
456
460
  fprintf(stderr, "ring flags 0 failed\n");
457
461
  return ret;
462
+ } else if (ret == T_EXIT_SKIP) {
463
+ return T_EXIT_SKIP;
458
464
  }
459
465
 
460
466
  ret = test(IORING_SETUP_SINGLE_ISSUER|IORING_SETUP_DEFER_TASKRUN);
461
- if (ret != T_EXIT_PASS) {
467
+ if (ret == T_EXIT_FAIL) {
462
468
  fprintf(stderr, "ring flags defer failed\n");
463
469
  return ret;
464
470
  }
@@ -37,12 +37,23 @@ static void do_setsockopt(int fd, int level, int optname, int val)
37
37
  assert(ret == 0);
38
38
  }
39
39
 
40
- static int sender(void)
40
+ static int sender(int queue_flags)
41
41
  {
42
42
  unsigned long long written = 0;
43
43
  struct sockaddr_in addr;
44
+ struct io_uring ring;
44
45
  int i, ret, fd;
45
46
 
47
+ /*
48
+ * Sender doesn't use the ring, but try and set one up with the same
49
+ * flags that the receiver will use. If that fails, we know the
50
+ * receiver will have failed too - just skip the test in that case.
51
+ */
52
+ ret = io_uring_queue_init(1, &ring, queue_flags);
53
+ if (ret)
54
+ return T_EXIT_SKIP;
55
+ io_uring_queue_exit(&ring);
56
+
46
57
  memset(&addr, 0, sizeof(addr));
47
58
  addr.sin_family = AF_INET;
48
59
  addr.sin_port = htons(port);
@@ -100,6 +111,8 @@ static int receiver(int queue_flags)
100
111
 
101
112
  ret = io_uring_queue_init(8, &ring, queue_flags);
102
113
  if (ret < 0) {
114
+ if (ret == -EINVAL)
115
+ return T_EXIT_SKIP;
103
116
  fprintf(stderr, "queue_init: %s\n", strerror(-ret));
104
117
  return 1;
105
118
  }
@@ -134,7 +147,7 @@ static int receiver(int queue_flags)
134
147
  io_uring_prep_recv(sqe, fd, buffer, BUF_SIZE, 0);
135
148
 
136
149
  ret = io_uring_submit(&ring);
137
- if (ret != 1) {
150
+ if (ret < 0) {
138
151
  fprintf(stderr, "io_uring_submit: %i\n", ret);
139
152
  return 1;
140
153
  }
@@ -211,5 +224,5 @@ int main(int argc, char **argv)
211
224
  if (is_rx)
212
225
  return receiver(queue_flags);
213
226
 
214
- return sender();
227
+ return sender(queue_flags);
215
228
  }
@@ -30,13 +30,15 @@ int main(int argc, char *argv[])
30
30
  p.cq_off.user_addr = (unsigned long long) (uintptr_t) addr;
31
31
 
32
32
  ret = io_uring_queue_init_params(2, &ring, &p);
33
- if (ret == -EINVAL) {
33
+ if (ret == -EINVAL || ret == -ENOENT) {
34
34
  /* kernel doesn't support SETUP_NO_MMAP */
35
+ free(addr);
35
36
  return T_EXIT_SKIP;
36
37
  } else if (ret && (ret != -EFAULT && ret != -ENOMEM)) {
37
38
  fprintf(stderr, "Got %d, wanted -EFAULT\n", ret);
38
39
  return T_EXIT_FAIL;
39
40
  }
40
41
 
42
+ free(addr);
41
43
  return T_EXIT_PASS;
42
44
  }
@@ -15,6 +15,45 @@
15
15
 
16
16
  static int seq;
17
17
 
18
+ static int test_nop_inject(struct io_uring *ring, unsigned req_flags)
19
+ {
20
+ struct io_uring_cqe *cqe;
21
+ struct io_uring_sqe *sqe;
22
+ int ret;
23
+
24
+ sqe = io_uring_get_sqe(ring);
25
+ if (!sqe) {
26
+ fprintf(stderr, "get sqe failed\n");
27
+ goto err;
28
+ }
29
+
30
+ io_uring_prep_nop(sqe);
31
+ sqe->user_data = ++seq;
32
+ sqe->nop_flags = IORING_NOP_INJECT_RESULT;
33
+ sqe->flags |= req_flags;
34
+ sqe->len = -EFAULT;
35
+
36
+ ret = io_uring_submit(ring);
37
+ if (ret <= 0) {
38
+ fprintf(stderr, "sqe submit failed: %d\n", ret);
39
+ goto err;
40
+ }
41
+
42
+ ret = io_uring_wait_cqe(ring, &cqe);
43
+ if (ret < 0) {
44
+ fprintf(stderr, "wait completion %d\n", ret);
45
+ goto err;
46
+ }
47
+ if (cqe->res != -EINVAL && cqe->res != -EFAULT) {
48
+ fprintf(stderr, "expected injected result, got %d\n", cqe->res);
49
+ goto err;
50
+ }
51
+ io_uring_cqe_seen(ring, cqe);
52
+ return 0;
53
+ err:
54
+ return 1;
55
+ }
56
+
18
57
  static int test_single_nop(struct io_uring *ring, unsigned req_flags)
19
58
  {
20
59
  struct io_uring_cqe *cqe;
@@ -151,6 +190,11 @@ static int test_ring(unsigned flags)
151
190
  fprintf(stderr, "test_barrier_nop failed\n");
152
191
  goto err;
153
192
  }
193
+ ret = test_nop_inject(&ring, req_flags);
194
+ if (ret) {
195
+ fprintf(stderr, "test_nop_inject failed\n");
196
+ goto err;
197
+ }
154
198
  }
155
199
  err:
156
200
  io_uring_queue_exit(&ring);
@@ -9,7 +9,7 @@
9
9
  #include <sys/socket.h>
10
10
  #include <unistd.h>
11
11
  #include <stdlib.h>
12
- #include <sys/poll.h>
12
+ #include <poll.h>
13
13
 
14
14
  #include "liburing.h"
15
15
  #include "helpers.h"
@@ -35,6 +35,36 @@ static int submit_wait(struct io_uring *ring)
35
35
  return ret;
36
36
  }
37
37
 
38
+ static int test_close_flush(void)
39
+ {
40
+ struct io_uring ring;
41
+ struct io_uring_sqe *sqe;
42
+ char buf[128];
43
+ int ret, fd;
44
+
45
+ sprintf(buf, "/sys/kernel/debug/tracing/per_cpu/cpu0/trace_pipe_raw");
46
+ fd = open(buf, O_RDONLY);
47
+ if (fd < 0)
48
+ return 0;
49
+
50
+ ret = io_uring_queue_init(8, &ring, 0);
51
+ if (ret) {
52
+ fprintf(stderr, "ring setup failed\n");
53
+ return -1;
54
+ }
55
+
56
+ sqe = io_uring_get_sqe(&ring);
57
+ io_uring_prep_close(sqe, fd);
58
+ ret = submit_wait(&ring);
59
+ if (ret) {
60
+ fprintf(stderr, "closefailed %i\n", ret);
61
+ return -1;
62
+ }
63
+
64
+ io_uring_queue_exit(&ring);
65
+ return 0;
66
+ }
67
+
38
68
  static inline int try_close(struct io_uring *ring, int fd, int slot)
39
69
  {
40
70
  struct io_uring_sqe *sqe;
@@ -220,12 +250,16 @@ int main(int argc, char *argv[])
220
250
  fprintf(stdout, "Open not supported, skipping\n");
221
251
  goto done;
222
252
  }
253
+ if (ret == -EPERM || ret == -EACCES)
254
+ return T_EXIT_SKIP;
223
255
  fprintf(stderr, "test_openat absolute failed: %d\n", ret);
224
256
  goto err;
225
257
  }
226
258
 
227
259
  ret = test_openat(&ring, path_rel, AT_FDCWD);
228
260
  if (ret < 0) {
261
+ if (ret == -EPERM || ret == -EACCES)
262
+ return T_EXIT_SKIP;
229
263
  fprintf(stderr, "test_openat relative failed: %d\n", ret);
230
264
  goto err;
231
265
  }
@@ -248,6 +282,12 @@ int main(int argc, char *argv[])
248
282
  goto err;
249
283
  }
250
284
 
285
+ ret = test_close_flush();
286
+ if (ret) {
287
+ fprintf(stderr, "test_close_flush failed\n");
288
+ goto err;
289
+ }
290
+
251
291
  done:
252
292
  unlink(path);
253
293
  if (do_unlink)