polyphony 1.5 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/CHANGELOG.md +14 -0
  4. data/TODO.md +0 -4
  5. data/ext/polyphony/backend_io_uring.c +34 -1
  6. data/ext/polyphony/backend_io_uring_context.c +24 -18
  7. data/ext/polyphony/backend_io_uring_context.h +4 -2
  8. data/ext/polyphony/backend_libev.c +4 -7
  9. data/ext/polyphony/event.c +21 -0
  10. data/ext/polyphony/extconf.rb +20 -18
  11. data/ext/polyphony/fiber.c +0 -2
  12. data/ext/polyphony/polyphony.c +2 -0
  13. data/ext/polyphony/polyphony.h +5 -0
  14. data/ext/polyphony/ring_buffer.c +1 -0
  15. data/ext/polyphony/runqueue_ring_buffer.c +1 -0
  16. data/ext/polyphony/thread.c +63 -0
  17. data/lib/polyphony/adapters/open3.rb +190 -0
  18. data/lib/polyphony/core/sync.rb +83 -13
  19. data/lib/polyphony/core/timer.rb +7 -25
  20. data/lib/polyphony/extensions/exception.rb +15 -0
  21. data/lib/polyphony/extensions/fiber.rb +14 -13
  22. data/lib/polyphony/extensions/io.rb +56 -14
  23. data/lib/polyphony/extensions/kernel.rb +1 -1
  24. data/lib/polyphony/extensions/object.rb +1 -13
  25. data/lib/polyphony/extensions/process.rb +76 -1
  26. data/lib/polyphony/extensions/thread.rb +19 -27
  27. data/lib/polyphony/version.rb +1 -1
  28. data/lib/polyphony.rb +11 -5
  29. data/test/helper.rb +46 -4
  30. data/test/open3/envutil.rb +380 -0
  31. data/test/open3/find_executable.rb +24 -0
  32. data/test/stress.rb +11 -7
  33. data/test/test_backend.rb +7 -2
  34. data/test/test_event.rb +10 -3
  35. data/test/test_ext.rb +2 -1
  36. data/test/test_fiber.rb +16 -4
  37. data/test/test_global_api.rb +13 -12
  38. data/test/test_io.rb +39 -0
  39. data/test/test_kernel.rb +2 -2
  40. data/test/test_monitor.rb +356 -0
  41. data/test/test_open3.rb +338 -0
  42. data/test/test_signal.rb +5 -1
  43. data/test/test_socket.rb +6 -3
  44. data/test/test_sync.rb +46 -0
  45. data/test/test_thread.rb +10 -1
  46. data/test/test_thread_pool.rb +5 -0
  47. data/test/test_throttler.rb +1 -1
  48. data/test/test_timer.rb +8 -2
  49. data/test/test_trace.rb +2 -0
  50. data/vendor/liburing/.github/workflows/build.yml +8 -0
  51. data/vendor/liburing/.gitignore +1 -0
  52. data/vendor/liburing/CHANGELOG +8 -0
  53. data/vendor/liburing/configure +17 -25
  54. data/vendor/liburing/debian/liburing-dev.manpages +2 -0
  55. data/vendor/liburing/debian/rules +2 -1
  56. data/vendor/liburing/examples/Makefile +2 -1
  57. data/vendor/liburing/examples/io_uring-udp.c +11 -3
  58. data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
  59. data/vendor/liburing/liburing.spec +1 -1
  60. data/vendor/liburing/make-debs.sh +4 -2
  61. data/vendor/liburing/src/Makefile +5 -5
  62. data/vendor/liburing/src/arch/aarch64/lib.h +1 -1
  63. data/vendor/liburing/src/include/liburing/io_uring.h +41 -16
  64. data/vendor/liburing/src/include/liburing.h +86 -11
  65. data/vendor/liburing/src/int_flags.h +1 -0
  66. data/vendor/liburing/src/liburing-ffi.map +12 -0
  67. data/vendor/liburing/src/liburing.map +8 -0
  68. data/vendor/liburing/src/register.c +7 -2
  69. data/vendor/liburing/src/setup.c +373 -81
  70. data/vendor/liburing/test/232c93d07b74.c +3 -3
  71. data/vendor/liburing/test/Makefile +10 -3
  72. data/vendor/liburing/test/accept.c +2 -1
  73. data/vendor/liburing/test/buf-ring.c +35 -75
  74. data/vendor/liburing/test/connect-rep.c +204 -0
  75. data/vendor/liburing/test/coredump.c +59 -0
  76. data/vendor/liburing/test/fallocate.c +9 -0
  77. data/vendor/liburing/test/fd-pass.c +34 -3
  78. data/vendor/liburing/test/file-verify.c +27 -6
  79. data/vendor/liburing/test/helpers.c +3 -1
  80. data/vendor/liburing/test/io_uring_register.c +25 -28
  81. data/vendor/liburing/test/io_uring_setup.c +1 -1
  82. data/vendor/liburing/test/poll-cancel-all.c +29 -5
  83. data/vendor/liburing/test/poll-race-mshot.c +6 -22
  84. data/vendor/liburing/test/read-write.c +53 -0
  85. data/vendor/liburing/test/recv-msgall.c +21 -23
  86. data/vendor/liburing/test/reg-fd-only.c +55 -0
  87. data/vendor/liburing/test/reg-hint.c +56 -0
  88. data/vendor/liburing/test/regbuf-merge.c +91 -0
  89. data/vendor/liburing/test/ringbuf-read.c +2 -10
  90. data/vendor/liburing/test/send_recvmsg.c +5 -16
  91. data/vendor/liburing/test/shutdown.c +2 -1
  92. data/vendor/liburing/test/socket-io-cmd.c +215 -0
  93. data/vendor/liburing/test/socket-rw-eagain.c +2 -1
  94. data/vendor/liburing/test/socket-rw-offset.c +2 -1
  95. data/vendor/liburing/test/socket-rw.c +2 -1
  96. data/vendor/liburing/test/timeout.c +276 -0
  97. data/vendor/liburing/test/xattr.c +38 -25
  98. metadata +14 -3
  99. data/vendor/liburing/test/timeout-overflow.c +0 -204
@@ -20,11 +20,11 @@ static int pagesize;
20
20
  /* test trying to register classic group when ring group exists */
21
21
  static int test_mixed_reg2(int bgid)
22
22
  {
23
- struct io_uring_buf_reg reg = { };
23
+ struct io_uring_buf_ring *br;
24
24
  struct io_uring_sqe *sqe;
25
25
  struct io_uring_cqe *cqe;
26
26
  struct io_uring ring;
27
- void *ptr, *bufs;
27
+ void *bufs;
28
28
  int ret;
29
29
 
30
30
  ret = t_create_ring(1, &ring, 0);
@@ -33,15 +33,8 @@ static int test_mixed_reg2(int bgid)
33
33
  else if (ret != T_SETUP_OK)
34
34
  return 1;
35
35
 
36
- if (posix_memalign(&ptr, 4096, 32 * sizeof(struct io_uring_buf)))
37
- return 1;
38
-
39
- reg.ring_addr = (unsigned long) ptr;
40
- reg.ring_entries = 32;
41
- reg.bgid = bgid;
42
-
43
- ret = io_uring_register_buf_ring(&ring, &reg, 0);
44
- if (ret) {
36
+ br = io_uring_setup_buf_ring(&ring, 32, bgid, 0, &ret);
37
+ if (!br) {
45
38
  fprintf(stderr, "Buffer ring register failed %d\n", ret);
46
39
  return 1;
47
40
  }
@@ -62,6 +55,7 @@ static int test_mixed_reg2(int bgid)
62
55
  }
63
56
  io_uring_cqe_seen(&ring, cqe);
64
57
 
58
+ io_uring_free_buf_ring(&ring, br, 32, bgid);
65
59
  io_uring_queue_exit(&ring);
66
60
  return 0;
67
61
  }
@@ -69,11 +63,11 @@ static int test_mixed_reg2(int bgid)
69
63
  /* test trying to register ring group when classic group exists */
70
64
  static int test_mixed_reg(int bgid)
71
65
  {
72
- struct io_uring_buf_reg reg = { };
66
+ struct io_uring_buf_ring *br;
73
67
  struct io_uring_sqe *sqe;
74
68
  struct io_uring_cqe *cqe;
75
69
  struct io_uring ring;
76
- void *ptr, *bufs;
70
+ void *bufs;
77
71
  int ret;
78
72
 
79
73
  ret = t_create_ring(1, &ring, 0);
@@ -98,16 +92,9 @@ static int test_mixed_reg(int bgid)
98
92
  }
99
93
  io_uring_cqe_seen(&ring, cqe);
100
94
 
101
- if (posix_memalign(&ptr, 4096, 32 * sizeof(struct io_uring_buf)))
102
- return 1;
103
-
104
- reg.ring_addr = (unsigned long) ptr;
105
- reg.ring_entries = 32;
106
- reg.bgid = bgid;
107
-
108
- ret = io_uring_register_buf_ring(&ring, &reg, 0);
109
- if (ret != -EEXIST) {
110
- fprintf(stderr, "Buffer ring register failed %d\n", ret);
95
+ br = io_uring_setup_buf_ring(&ring, 32, bgid, 0, &ret);
96
+ if (br) {
97
+ fprintf(stderr, "Buffer ring setup succeeded unexpectedly %d\n", ret);
111
98
  return 1;
112
99
  }
113
100
 
@@ -118,8 +105,8 @@ static int test_mixed_reg(int bgid)
118
105
  static int test_double_reg_unreg(int bgid)
119
106
  {
120
107
  struct io_uring_buf_reg reg = { };
108
+ struct io_uring_buf_ring *br;
121
109
  struct io_uring ring;
122
- void *ptr;
123
110
  int ret;
124
111
 
125
112
  ret = t_create_ring(1, &ring, 0);
@@ -128,21 +115,14 @@ static int test_double_reg_unreg(int bgid)
128
115
  else if (ret != T_SETUP_OK)
129
116
  return 1;
130
117
 
131
- if (posix_memalign(&ptr, 4096, 32 * sizeof(struct io_uring_buf)))
132
- return 1;
133
-
134
- reg.ring_addr = (unsigned long) ptr;
135
- reg.ring_entries = 32;
136
- reg.bgid = bgid;
137
-
138
- ret = io_uring_register_buf_ring(&ring, &reg, 0);
139
- if (ret) {
118
+ br = io_uring_setup_buf_ring(&ring, 32, bgid, 0, &ret);
119
+ if (!br) {
140
120
  fprintf(stderr, "Buffer ring register failed %d\n", ret);
141
121
  return 1;
142
122
  }
143
123
 
144
124
  /* check that 2nd register with same bgid fails */
145
- reg.ring_addr = (unsigned long) ptr;
125
+ reg.ring_addr = (unsigned long) br;
146
126
  reg.ring_entries = 32;
147
127
  reg.bgid = bgid;
148
128
 
@@ -152,7 +132,7 @@ static int test_double_reg_unreg(int bgid)
152
132
  return 1;
153
133
  }
154
134
 
155
- ret = io_uring_unregister_buf_ring(&ring, bgid);
135
+ ret = io_uring_free_buf_ring(&ring, br, 32, bgid);
156
136
  if (ret) {
157
137
  fprintf(stderr, "Buffer ring register failed %d\n", ret);
158
138
  return 1;
@@ -170,9 +150,8 @@ static int test_double_reg_unreg(int bgid)
170
150
 
171
151
  static int test_reg_unreg(int bgid)
172
152
  {
173
- struct io_uring_buf_reg reg = { };
153
+ struct io_uring_buf_ring *br;
174
154
  struct io_uring ring;
175
- void *ptr;
176
155
  int ret;
177
156
 
178
157
  ret = t_create_ring(1, &ring, 0);
@@ -181,15 +160,8 @@ static int test_reg_unreg(int bgid)
181
160
  else if (ret != T_SETUP_OK)
182
161
  return 1;
183
162
 
184
- if (posix_memalign(&ptr, 4096, 32 * sizeof(struct io_uring_buf)))
185
- return 1;
186
-
187
- reg.ring_addr = (unsigned long) ptr;
188
- reg.ring_entries = 32;
189
- reg.bgid = bgid;
190
-
191
- ret = io_uring_register_buf_ring(&ring, &reg, 0);
192
- if (ret) {
163
+ br = io_uring_setup_buf_ring(&ring, 32, bgid, 0, &ret);
164
+ if (!br) {
193
165
  if (ret == -EINVAL) {
194
166
  no_buf_ring = 1;
195
167
  return 0;
@@ -198,9 +170,9 @@ static int test_reg_unreg(int bgid)
198
170
  return 1;
199
171
  }
200
172
 
201
- ret = io_uring_unregister_buf_ring(&ring, bgid);
173
+ ret = io_uring_free_buf_ring(&ring, br, 32, bgid);
202
174
  if (ret) {
203
- fprintf(stderr, "Buffer ring register failed %d\n", ret);
175
+ fprintf(stderr, "Buffer ring unregister failed %d\n", ret);
204
176
  return 1;
205
177
  }
206
178
 
@@ -234,6 +206,9 @@ static int test_bad_reg(int bgid)
234
206
 
235
207
  static int test_full_page_reg(int bgid)
236
208
  {
209
+ #if defined(__hppa__)
210
+ return T_EXIT_SKIP;
211
+ #else
237
212
  struct io_uring ring;
238
213
  int ret;
239
214
  void *ptr;
@@ -243,7 +218,7 @@ static int test_full_page_reg(int bgid)
243
218
  ret = io_uring_queue_init(1, &ring, 0);
244
219
  if (ret) {
245
220
  fprintf(stderr, "queue init failed %d\n", ret);
246
- return 1;
221
+ return T_EXIT_FAIL;
247
222
  }
248
223
 
249
224
  ret = posix_memalign(&ptr, pagesize, pagesize * 2);
@@ -273,7 +248,8 @@ err1:
273
248
  free(ptr);
274
249
  err:
275
250
  io_uring_queue_exit(&ring);
276
- return ret;
251
+ return ret ? T_EXIT_FAIL : T_EXIT_PASS;
252
+ #endif
277
253
  }
278
254
 
279
255
  static int test_one_read(int fd, int bgid, struct io_uring *ring)
@@ -318,18 +294,12 @@ static int test_one_read(int fd, int bgid, struct io_uring *ring)
318
294
 
319
295
  static int test_running(int bgid, int entries, int loops)
320
296
  {
321
- struct io_uring_buf_reg reg = { };
297
+ int ring_mask = io_uring_buf_ring_mask(entries);
298
+ struct io_uring_buf_ring *br;
299
+ int ret, loop, idx, read_fd;
322
300
  struct io_uring ring;
323
- void *ptr;
324
301
  char buffer[8];
325
- int ret;
326
- int ring_size = (entries * sizeof(struct io_uring_buf) + 4095) & (~4095);
327
- int ring_mask = io_uring_buf_ring_mask(entries);
328
-
329
- int loop, idx;
330
302
  bool *buffers;
331
- struct io_uring_buf_ring *br;
332
- int read_fd;
333
303
 
334
304
  ret = t_create_ring(1, &ring, 0);
335
305
  if (ret == T_SETUP_SKIP)
@@ -337,11 +307,12 @@ static int test_running(int bgid, int entries, int loops)
337
307
  else if (ret != T_SETUP_OK)
338
308
  return 1;
339
309
 
340
- if (posix_memalign(&ptr, 4096, ring_size))
310
+ br = io_uring_setup_buf_ring(&ring, entries, bgid, 0, &ret);
311
+ if (!br) {
312
+ /* by now should have checked if this is supported or not */
313
+ fprintf(stderr, "Buffer ring register failed %d\n", ret);
341
314
  return 1;
342
-
343
- br = (struct io_uring_buf_ring *)ptr;
344
- io_uring_buf_ring_init(br);
315
+ }
345
316
 
346
317
  buffers = malloc(sizeof(bool) * entries);
347
318
  if (!buffers)
@@ -351,17 +322,6 @@ static int test_running(int bgid, int entries, int loops)
351
322
  if (read_fd < 0)
352
323
  return 1;
353
324
 
354
- reg.ring_addr = (unsigned long) ptr;
355
- reg.ring_entries = entries;
356
- reg.bgid = bgid;
357
-
358
- ret = io_uring_register_buf_ring(&ring, &reg, 0);
359
- if (ret) {
360
- /* by now should have checked if this is supported or not */
361
- fprintf(stderr, "Buffer ring register failed %d\n", ret);
362
- return 1;
363
- }
364
-
365
325
  for (loop = 0; loop < loops; loop++) {
366
326
  memset(buffers, 0, sizeof(bool) * entries);
367
327
  for (idx = 0; idx < entries; idx++)
@@ -456,7 +416,7 @@ int main(int argc, char *argv[])
456
416
  }
457
417
 
458
418
  ret = test_full_page_reg(bgids[i]);
459
- if (ret) {
419
+ if (ret == T_EXIT_FAIL) {
460
420
  fprintf(stderr, "test_full_page_reg failed\n");
461
421
  return T_EXIT_FAIL;
462
422
  }
@@ -0,0 +1,204 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Check that repeated IORING_OP_CONNECT to a socket without a listener keeps
4
+ * yielding -ECONNREFUSED rather than -ECONNABORTED. Based on a reproducer
5
+ * from:
6
+ *
7
+ * https://github.com/axboe/liburing/issues/828
8
+ *
9
+ * and adopted to our usual test cases. Other changes made like looping,
10
+ * using different ring types, adding a memset() for reuse, etc.
11
+ *
12
+ */
13
+ #include <stdio.h>
14
+ #include <netinet/in.h>
15
+ #include <string.h>
16
+ #include <unistd.h>
17
+ #include <stdlib.h>
18
+ #include <arpa/inet.h>
19
+
20
+ #include "liburing.h"
21
+ #include "helpers.h"
22
+
23
+ static unsigned long ud;
24
+
25
+ static int init_test_server(struct sockaddr_in *serv_addr)
26
+ {
27
+ socklen_t servaddr_len = sizeof(struct sockaddr_in);
28
+ int fd;
29
+
30
+ /* Init server socket. Bind but don't listen */
31
+ fd = socket(AF_INET, SOCK_STREAM, 0);
32
+ if (fd < 0) {
33
+ perror("socket");
34
+ return -1;
35
+ }
36
+
37
+ serv_addr->sin_family = AF_INET;
38
+ serv_addr->sin_addr.s_addr = inet_addr("127.0.0.1");
39
+
40
+ if (bind(fd, (struct sockaddr *) serv_addr, servaddr_len) < 0) {
41
+ perror("bind");
42
+ return -1;
43
+ }
44
+
45
+ /*
46
+ * Get the addresses the socket is bound to because the port is chosen
47
+ * by the network stack.
48
+ */
49
+ if (getsockname(fd, (struct sockaddr *)serv_addr, &servaddr_len) < 0) {
50
+ perror("getsockname");
51
+ return -1;
52
+ }
53
+
54
+ return fd;
55
+ }
56
+
57
+ static int init_test_client(void)
58
+ {
59
+ socklen_t addr_len = sizeof(struct sockaddr_in);
60
+ struct sockaddr_in client_addr = {};
61
+ int clientfd;
62
+
63
+ clientfd = socket(AF_INET, SOCK_STREAM, 0);
64
+ if (clientfd < 0) {
65
+ perror("socket");
66
+ return -1;
67
+ }
68
+
69
+ client_addr.sin_family = AF_INET;
70
+ client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
71
+
72
+ if (bind(clientfd, (struct sockaddr *)&client_addr, addr_len) < 0) {
73
+ perror("bind");
74
+ close(clientfd);
75
+ return -1;
76
+ }
77
+
78
+ /*
79
+ * Get the addresses the socket is bound to because the port is chosen
80
+ * by the network stack.
81
+ */
82
+ if (getsockname(clientfd, (struct sockaddr *)&client_addr, &addr_len) < 0) {
83
+ perror("getsockname");
84
+ close(clientfd);
85
+ return -1;
86
+ }
87
+
88
+ return clientfd;
89
+ }
90
+
91
+ static int get_completion_and_print(struct io_uring *ring)
92
+ {
93
+ struct io_uring_cqe *cqe;
94
+ int ret, res;
95
+
96
+ ret = io_uring_wait_cqe(ring, &cqe);
97
+ if (ret < 0) {
98
+ fprintf(stderr, "wait_cqe=%d\n", ret);
99
+ return -1;
100
+ }
101
+
102
+ /* Mark this completion as seen */
103
+ res = cqe->res;
104
+ io_uring_cqe_seen(ring, cqe);
105
+ return res;
106
+ }
107
+
108
+ static int test_connect(struct io_uring *ring,
109
+ int clientfd, struct sockaddr_in *serv_addr)
110
+ {
111
+ struct sockaddr_in local_sa;
112
+ struct io_uring_sqe *sqe;
113
+ int ret;
114
+
115
+ sqe = io_uring_get_sqe(ring);
116
+ io_uring_prep_connect(sqe, clientfd, (const struct sockaddr *)serv_addr,
117
+ sizeof(struct sockaddr_in));
118
+ sqe->user_data = ++ud;
119
+
120
+ memcpy(&local_sa, serv_addr, sizeof(local_sa));
121
+
122
+ ret = io_uring_submit_and_wait(ring, 1);
123
+ if (ret != 1) {
124
+ fprintf(stderr, "submit=%d\n", ret);
125
+ return T_EXIT_FAIL;
126
+ }
127
+
128
+ /* check for reuse at the same time */
129
+ memset(&local_sa, 0xff, sizeof(local_sa));
130
+
131
+ ret = get_completion_and_print(ring);
132
+ if (ret != -ECONNREFUSED) {
133
+ fprintf(stderr, "Connect got %d\n", ret);
134
+ return T_EXIT_FAIL;
135
+ }
136
+ return T_EXIT_PASS;
137
+ }
138
+
139
+ static int test(int flags)
140
+ {
141
+ struct io_uring_params params = { .flags = flags, };
142
+ struct sockaddr_in serv_addr = {};
143
+ struct io_uring ring;
144
+ int ret, clientfd, s_fd, i;
145
+
146
+ if (flags & IORING_SETUP_SQPOLL)
147
+ params.sq_thread_idle = 50;
148
+
149
+ ret = io_uring_queue_init_params(8, &ring, &params);
150
+ if (ret < 0) {
151
+ fprintf(stderr, "Queue init: %d\n", ret);
152
+ return T_EXIT_FAIL;
153
+ }
154
+
155
+ s_fd = init_test_server(&serv_addr);
156
+ if (s_fd < 0)
157
+ return T_EXIT_FAIL;
158
+
159
+ clientfd = init_test_client();
160
+ if (clientfd < 0) {
161
+ close(s_fd);
162
+ return T_EXIT_FAIL;
163
+ }
164
+
165
+ /* make sure SQPOLL thread is sleeping */
166
+ if (flags & IORING_SETUP_SQPOLL)
167
+ usleep(100000);
168
+
169
+ for (i = 0; i < 32; i++) {
170
+ ret = test_connect(&ring, clientfd, &serv_addr);
171
+ if (ret == T_EXIT_SKIP)
172
+ return T_EXIT_SKIP;
173
+ else if (ret == T_EXIT_PASS)
174
+ continue;
175
+
176
+ return T_EXIT_FAIL;
177
+ }
178
+
179
+ close(s_fd);
180
+ close(clientfd);
181
+ return T_EXIT_PASS;
182
+ }
183
+
184
+ int main(int argc, char *argv[])
185
+ {
186
+ int ret;
187
+
188
+ if (argc > 1)
189
+ return T_EXIT_SKIP;
190
+
191
+ ret = test(0);
192
+ if (ret == T_EXIT_FAIL) {
193
+ fprintf(stderr, "test(0) failed\n");
194
+ return T_EXIT_FAIL;
195
+ }
196
+
197
+ ret = test(IORING_SETUP_SQPOLL);
198
+ if (ret == T_EXIT_FAIL) {
199
+ fprintf(stderr, "test(SQPOLL) failed\n");
200
+ return T_EXIT_FAIL;
201
+ }
202
+
203
+ return 0;
204
+ }
@@ -0,0 +1,59 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Description: trigger segfault. A recent 6.4-rc kernel introduced a bug
4
+ * via vhost where segfaults for applications using io_uring
5
+ * would hang in D state forever upon trying to generate the
6
+ * core file. Perform a trivial test where a child process
7
+ * generates a NULL pointer dereference and ensure that we don't
8
+ * hang.
9
+ *
10
+ */
11
+ #include <stdio.h>
12
+ #include <stdlib.h>
13
+ #include <unistd.h>
14
+ #include <sys/wait.h>
15
+
16
+ #include "liburing.h"
17
+ #include "helpers.h"
18
+
19
+ static void test(void)
20
+ {
21
+ struct io_uring_sqe *sqe;
22
+ struct io_uring ring;
23
+ int *ptr = NULL;
24
+ int fds[2];
25
+ char r1;
26
+
27
+ if (pipe(fds) < 0) {
28
+ perror("pipe");
29
+ exit(0);
30
+ }
31
+
32
+ io_uring_queue_init(8, &ring, 0);
33
+
34
+ sqe = io_uring_get_sqe(&ring);
35
+ io_uring_prep_read(sqe, fds[0], &r1, sizeof(r1), 0);
36
+ sqe->flags = IOSQE_ASYNC;
37
+ sqe->user_data = 1;
38
+
39
+ io_uring_submit(&ring);
40
+ *ptr = 0;
41
+ exit(0);
42
+ }
43
+
44
+ int main(int argc, char *argv[])
45
+ {
46
+ pid_t pid;
47
+ int wstat;
48
+
49
+ pid = fork();
50
+ if (pid < 0) {
51
+ perror("fork");
52
+ return T_EXIT_SKIP;
53
+ } else if (!pid) {
54
+ test();
55
+ }
56
+
57
+ wait(&wstat);
58
+ return T_EXIT_PASS;
59
+ }
@@ -12,6 +12,7 @@
12
12
  #include <stdlib.h>
13
13
  #include <string.h>
14
14
  #include <fcntl.h>
15
+ #include <signal.h>
15
16
 
16
17
  #include "liburing.h"
17
18
  #include "helpers.h"
@@ -216,14 +217,22 @@ err:
216
217
  return 1;
217
218
  }
218
219
 
220
+ static void sig_xfsz(int sig)
221
+ {
222
+ }
223
+
219
224
  int main(int argc, char *argv[])
220
225
  {
226
+ struct sigaction act = { };
221
227
  struct io_uring ring;
222
228
  int ret;
223
229
 
224
230
  if (argc > 1)
225
231
  return T_EXIT_SKIP;
226
232
 
233
+ act.sa_handler = sig_xfsz;
234
+ sigaction(SIGXFSZ, &act, NULL);
235
+
227
236
  ret = io_uring_queue_init(8, &ring, 0);
228
237
  if (ret) {
229
238
  fprintf(stderr, "ring setup failed\n");
@@ -80,6 +80,14 @@ static int test(const char *filename, int source_fd, int target_fd)
80
80
  fprintf(stderr, "register files failed %d\n", ret);
81
81
  return T_EXIT_FAIL;
82
82
  }
83
+ if (target_fd == IORING_FILE_INDEX_ALLOC) {
84
+ /* we want to test installing into a non-zero slot */
85
+ ret = io_uring_register_file_alloc_range(&dring, 1, 1);
86
+ if (ret) {
87
+ fprintf(stderr, "io_uring_register_file_alloc_range %d\n", ret);
88
+ return T_EXIT_FAIL;
89
+ }
90
+ }
83
91
 
84
92
  /* open direct descriptor */
85
93
  sqe = io_uring_get_sqe(&sring);
@@ -102,8 +110,14 @@ static int test(const char *filename, int source_fd, int target_fd)
102
110
 
103
111
  /* send direct descriptor to destination ring */
104
112
  sqe = io_uring_get_sqe(&sring);
105
- io_uring_prep_msg_ring_fd(sqe, dring.ring_fd, source_fd, target_fd,
106
- USER_DATA, 0);
113
+ if (target_fd == IORING_FILE_INDEX_ALLOC) {
114
+ io_uring_prep_msg_ring_fd_alloc(sqe, dring.ring_fd, source_fd,
115
+ USER_DATA, 0);
116
+ } else {
117
+
118
+ io_uring_prep_msg_ring_fd(sqe, dring.ring_fd, source_fd,
119
+ target_fd, USER_DATA, 0);
120
+ }
107
121
  io_uring_submit(&sring);
108
122
 
109
123
  ret = io_uring_wait_cqe(&sring, &cqe);
@@ -111,7 +125,7 @@ static int test(const char *filename, int source_fd, int target_fd)
111
125
  fprintf(stderr, "wait cqe failed %d\n", ret);
112
126
  return T_EXIT_FAIL;
113
127
  }
114
- if (cqe->res) {
128
+ if (cqe->res < 0) {
115
129
  if (cqe->res == -EINVAL && !no_fd_pass) {
116
130
  no_fd_pass = 1;
117
131
  return T_EXIT_SKIP;
@@ -131,6 +145,17 @@ static int test(const char *filename, int source_fd, int target_fd)
131
145
  fprintf(stderr, "bad user_data %ld\n", (long) cqe->res);
132
146
  return T_EXIT_FAIL;
133
147
  }
148
+ if (cqe->res < 0) {
149
+ fprintf(stderr, "bad result %i\n", cqe->res);
150
+ return T_EXIT_FAIL;
151
+ }
152
+ if (target_fd == IORING_FILE_INDEX_ALLOC) {
153
+ if (cqe->res != 1) {
154
+ fprintf(stderr, "invalid allocated index %i\n", cqe->res);
155
+ return T_EXIT_FAIL;
156
+ }
157
+ target_fd = cqe->res;
158
+ }
134
159
  io_uring_cqe_seen(&dring, cqe);
135
160
 
136
161
  /* now verify we can read the sane data from the destination ring */
@@ -201,6 +226,12 @@ int main(int argc, char *argv[])
201
226
  ret = T_EXIT_FAIL;
202
227
  }
203
228
 
229
+ ret = test(fname, 1, IORING_FILE_INDEX_ALLOC);
230
+ if (ret == T_EXIT_FAIL) {
231
+ fprintf(stderr, "test failed 1 ALLOC\n");
232
+ ret = T_EXIT_FAIL;
233
+ }
234
+
204
235
  unlink(fname);
205
236
  return ret;
206
237
  }
@@ -32,15 +32,32 @@
32
32
  */
33
33
  #define READ_BATCH 16
34
34
 
35
+ static void verify_buf_sync(void *buf, size_t size, bool registered)
36
+ {
37
+ #if defined(__hppa__)
38
+ if (registered) {
39
+ unsigned long off = (unsigned long) buf & 4095;
40
+ unsigned long p = (unsigned long) buf & ~4095;
41
+ int i;
42
+
43
+ size += off;
44
+ for (i = 0; i < size; i += 32)
45
+ asm volatile("fdc 0(%0)" : : "r" (p + i));
46
+ }
47
+ #endif
48
+ }
49
+
35
50
  /*
36
51
  * Each offset in the file has the offset / sizeof(int) stored for every
37
52
  * sizeof(int) address.
38
53
  */
39
- static int verify_buf(void *buf, size_t size, off_t off)
54
+ static int verify_buf(void *buf, size_t size, off_t off, bool registered)
40
55
  {
41
56
  int i, u_in_buf = size / sizeof(unsigned int);
42
57
  unsigned int *ptr;
43
58
 
59
+ verify_buf_sync(buf, size, registered);
60
+
44
61
  off /= sizeof(unsigned int);
45
62
  ptr = buf;
46
63
  for (i = 0; i < u_in_buf; i++) {
@@ -197,7 +214,7 @@ again:
197
214
  goto err;
198
215
  }
199
216
 
200
- if (verify_buf(buf, CHUNK_SIZE / 2, 0))
217
+ if (verify_buf(buf, CHUNK_SIZE / 2, 0, false))
201
218
  goto err;
202
219
 
203
220
  /*
@@ -364,9 +381,12 @@ static int test(struct io_uring *ring, const char *fname, int buffered,
364
381
  v[i].iov_base = buf[i];
365
382
  v[i].iov_len = CHUNK_SIZE;
366
383
  }
367
- ret = io_uring_register_buffers(ring, v, READ_BATCH);
384
+ ret = t_register_buffers(ring, v, READ_BATCH);
368
385
  if (ret) {
369
- fprintf(stderr, "Error buffer reg %d\n", ret);
386
+ if (ret == T_SETUP_SKIP) {
387
+ ret = 0;
388
+ goto free_bufs;
389
+ }
370
390
  goto err;
371
391
  }
372
392
  }
@@ -445,12 +465,12 @@ static int test(struct io_uring *ring, const char *fname, int buffered,
445
465
  void *buf = vecs[index][j].iov_base;
446
466
  size_t len = vecs[index][j].iov_len;
447
467
 
448
- if (verify_buf(buf, len, voff))
468
+ if (verify_buf(buf, len, voff, registered))
449
469
  goto err;
450
470
  voff += len;
451
471
  }
452
472
  } else {
453
- if (verify_buf(buf[index], CHUNK_SIZE, voff))
473
+ if (verify_buf(buf[index], CHUNK_SIZE, voff, registered))
454
474
  goto err;
455
475
  }
456
476
  }
@@ -460,6 +480,7 @@ static int test(struct io_uring *ring, const char *fname, int buffered,
460
480
  done:
461
481
  if (registered)
462
482
  io_uring_unregister_buffers(ring);
483
+ free_bufs:
463
484
  if (vectored) {
464
485
  for (j = 0; j < READ_BATCH; j++)
465
486
  for (i = 0; i < nr_vecs; i++)
@@ -36,13 +36,15 @@ void *t_malloc(size_t size)
36
36
  int t_bind_ephemeral_port(int fd, struct sockaddr_in *addr)
37
37
  {
38
38
  socklen_t addrlen;
39
+ int ret;
39
40
 
40
41
  addr->sin_port = 0;
41
42
  if (bind(fd, (struct sockaddr *)addr, sizeof(*addr)))
42
43
  return -errno;
43
44
 
44
45
  addrlen = sizeof(*addr);
45
- assert(!getsockname(fd, (struct sockaddr *)addr, &addrlen));
46
+ ret = getsockname(fd, (struct sockaddr *)addr, &addrlen);
47
+ assert(!ret);
46
48
  assert(addr->sin_port != 0);
47
49
  return 0;
48
50
  }