uringmachine 0.20.0 → 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.
@@ -22,7 +22,7 @@ static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec)
22
22
  }
23
23
 
24
24
  static const char *magic = "Hello World!";
25
- static int use_port = 8000;
25
+ static bool no_getsockname = false;
26
26
 
27
27
  enum {
28
28
  SRV_INDEX = 0,
@@ -74,18 +74,82 @@ static int connect_client(struct io_uring *ring, unsigned short peer_port)
74
74
  return T_SETUP_OK;
75
75
  }
76
76
 
77
- static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
77
+ /*
78
+ * getsockname was added to the kernel a few releases after bind/listen.
79
+ * In order to provide a backward-compatible test, fallback to
80
+ * non-io-uring if we are on an older kernel, allowing the test to
81
+ * continue.
82
+ */
83
+ static int do_getsockname(struct io_uring *ring, int direct_socket,
84
+ int peer, struct sockaddr *saddr,
85
+ socklen_t *saddr_len)
86
+ {
87
+ struct io_uring_sqe *sqe;
88
+ struct io_uring_cqe *cqe;
89
+ int res = 0, fd;
90
+
91
+ if (!no_getsockname) {
92
+ /* attempt io_uring. Command might not exist */
93
+ sqe = io_uring_get_sqe(ring);
94
+ io_uring_prep_cmd_getsockname(sqe, direct_socket,
95
+ saddr, saddr_len, peer);
96
+ sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
97
+ io_uring_submit(ring);
98
+ io_uring_wait_cqe(ring, &cqe);
99
+ res = cqe->res;
100
+ io_uring_cqe_seen(ring, cqe);
101
+ }
102
+
103
+ if (no_getsockname || res == -ENOTSUP) {
104
+ /*
105
+ * Older kernel. install the fd and use the getsockname
106
+ * syscall.
107
+ */
108
+ no_getsockname = true;
109
+
110
+ sqe = io_uring_get_sqe(ring);
111
+ io_uring_prep_fixed_fd_install(sqe, direct_socket, 0);
112
+ io_uring_submit(ring);
113
+ io_uring_wait_cqe(ring, &cqe);
114
+ fd = cqe->res;
115
+ io_uring_cqe_seen(ring, cqe);
116
+
117
+ if (fd < 0) {
118
+ fprintf(stderr, "installing direct fd failed. %d\n",
119
+ cqe->res);
120
+ return T_EXIT_FAIL;
121
+ }
122
+ if (peer)
123
+ res = getpeername(fd, saddr, saddr_len);
124
+ else
125
+ res = getsockname(fd, saddr, saddr_len);
126
+
127
+ if (res) {
128
+ fprintf(stderr, "get%sname syscall failed. %d\n",
129
+ peer? "peer":"sock", errno);
130
+ return T_EXIT_FAIL;
131
+ }
132
+ close(fd);
133
+ } else if (res < 0) {
134
+ fprintf(stderr, "getsockname server failed. %d\n", cqe->res);
135
+ return T_EXIT_FAIL;
136
+ }
137
+ return 0;
138
+ }
139
+
140
+ static int setup_srv(struct io_uring *ring)
78
141
  {
142
+ struct sockaddr_in server_addr;
79
143
  struct io_uring_sqe *sqe;
80
144
  struct io_uring_cqe *cqe;
81
145
  struct __kernel_timespec ts;
82
146
  int ret, val, submitted;
83
147
  unsigned head;
84
148
 
85
- memset(server_addr, 0, sizeof(struct sockaddr_in));
86
- server_addr->sin_family = AF_INET;
87
- server_addr->sin_port = htons(use_port++);
88
- server_addr->sin_addr.s_addr = htons(INADDR_ANY);
149
+ memset(&server_addr, 0, sizeof(struct sockaddr_in));
150
+ server_addr.sin_family = AF_INET;
151
+ server_addr.sin_port = htons(0);
152
+ server_addr.sin_addr.s_addr = htons(INADDR_ANY);
89
153
 
90
154
  sqe = io_uring_get_sqe(ring);
91
155
  io_uring_prep_socket_direct(sqe, AF_INET, SOCK_STREAM, 0, SRV_INDEX, 0);
@@ -98,7 +162,7 @@ static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
98
162
  sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
99
163
 
100
164
  sqe = io_uring_get_sqe(ring);
101
- io_uring_prep_bind(sqe, SRV_INDEX, (struct sockaddr *) server_addr,
165
+ io_uring_prep_bind(sqe, SRV_INDEX, (struct sockaddr *) &server_addr,
102
166
  sizeof(struct sockaddr_in));
103
167
  sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
104
168
 
@@ -132,12 +196,13 @@ static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
132
196
 
133
197
  static int test_good_server(unsigned int ring_flags)
134
198
  {
135
- struct sockaddr_in server_addr;
199
+ struct sockaddr_in saddr = {};
200
+ socklen_t saddr_len = sizeof(saddr);
136
201
  struct __kernel_timespec ts;
137
202
  struct io_uring_sqe *sqe;
138
203
  struct io_uring_cqe *cqe;
139
204
  struct io_uring ring;
140
- int ret;
205
+ int ret, port;
141
206
  int fds[3];
142
207
  char buf[1024];
143
208
 
@@ -155,18 +220,22 @@ static int test_good_server(unsigned int ring_flags)
155
220
  return T_SETUP_SKIP;
156
221
  }
157
222
 
158
- ret = setup_srv(&ring, &server_addr);
223
+ ret = setup_srv(&ring);
159
224
  if (ret != T_SETUP_OK) {
160
225
  fprintf(stderr, "srv startup failed.\n");
161
226
  return T_EXIT_FAIL;
162
227
  }
163
228
 
164
- if (connect_client(&ring, server_addr.sin_port) != T_SETUP_OK) {
229
+ if (do_getsockname(&ring, SRV_INDEX, 0, (struct sockaddr*) &saddr,
230
+ &saddr_len))
231
+ return T_EXIT_FAIL;
232
+
233
+ if (connect_client(&ring, saddr.sin_port) != T_SETUP_OK) {
165
234
  fprintf(stderr, "cli startup failed.\n");
166
235
  return T_SETUP_SKIP;
167
236
  }
168
237
 
169
- /* Wait for a request */
238
+ /* Wait for a connection */
170
239
  sqe = io_uring_get_sqe(&ring);
171
240
  io_uring_prep_accept_direct(sqe, SRV_INDEX, NULL, NULL, 0, CONN_INDEX);
172
241
  sqe->flags |= IOSQE_FIXED_FILE;
@@ -179,6 +248,22 @@ static int test_good_server(unsigned int ring_flags)
179
248
  }
180
249
  io_uring_cqe_seen(&ring, cqe);
181
250
 
251
+ /* Test that getsockname on the peer (getpeername) yields a
252
+ * sane result.
253
+ */
254
+ port = saddr.sin_port;
255
+ saddr.sin_port = 0;
256
+ if (do_getsockname(&ring, CLI_INDEX, 1,
257
+ (struct sockaddr*)&saddr, &saddr_len))
258
+ return T_EXIT_FAIL;
259
+
260
+ if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) ||
261
+ saddr.sin_port != port) {
262
+ fprintf(stderr, "getsockname peer got wrong address: %s:%d\n",
263
+ inet_ntoa(saddr.sin_addr), saddr.sin_port);
264
+ return T_EXIT_FAIL;
265
+ }
266
+
182
267
  sqe = io_uring_get_sqe(&ring);
183
268
  io_uring_prep_recv(sqe, CONN_INDEX, buf, sizeof(buf), 0);
184
269
  sqe->flags |= IOSQE_FIXED_FILE;
@@ -355,6 +440,77 @@ fail:
355
440
  return ret;
356
441
  }
357
442
 
443
+ static int test_bad_sockname(void)
444
+ {
445
+ struct sockaddr_in saddr;
446
+ socklen_t saddr_len;
447
+ struct io_uring_sqe *sqe;
448
+ struct io_uring_cqe *cqe;
449
+ struct io_uring ring;
450
+ int sock = -1, err;
451
+ int ret = T_EXIT_FAIL;
452
+
453
+ memset(&saddr, 0, sizeof(struct sockaddr_in));
454
+ saddr.sin_family = AF_INET;
455
+ saddr.sin_port = htons(8001);
456
+ saddr.sin_addr.s_addr = htons(INADDR_ANY);
457
+
458
+ err = t_create_ring(1, &ring, 0);
459
+ if (err < 0) {
460
+ fprintf(stderr, "queue_init: %d\n", err);
461
+ return T_SETUP_SKIP;
462
+ }
463
+
464
+ sock = socket(AF_INET, SOCK_STREAM, 0);
465
+ if (sock < 0) {
466
+ perror("socket");
467
+ goto fail;
468
+ }
469
+
470
+ err = t_bind_ephemeral_port(sock, &saddr);
471
+ if (err) {
472
+ fprintf(stderr, "bind: %s\n", strerror(-err));
473
+ goto fail;
474
+ }
475
+
476
+ /* getsockname on a !socket fd. with getsockname(2), this would
477
+ * return -ENOTSOCK, but we can't do it in an io_uring_cmd.
478
+ */
479
+ sqe = io_uring_get_sqe(&ring);
480
+ saddr_len = sizeof(saddr);
481
+ io_uring_prep_cmd_getsockname(sqe, 1, (struct sockaddr*)&saddr, &saddr_len, 0);
482
+ err = io_uring_submit(&ring);
483
+ if (err < 0)
484
+ goto fail;
485
+ err = io_uring_wait_cqe(&ring, &cqe);
486
+ if (err)
487
+ goto fail;
488
+ if (cqe->res != -ENOTSUP)
489
+ goto fail;
490
+ io_uring_cqe_seen(&ring, cqe);
491
+
492
+ /* getsockname with weird parameters */
493
+ sqe = io_uring_get_sqe(&ring);
494
+ io_uring_prep_cmd_getsockname(sqe, sock, (struct sockaddr*)&saddr,
495
+ &saddr_len, 3);
496
+ err = io_uring_submit(&ring);
497
+ if (err < 0)
498
+ goto fail;
499
+ err = io_uring_wait_cqe(&ring, &cqe);
500
+ if (err)
501
+ goto fail;
502
+ if (cqe->res != -EINVAL)
503
+ goto fail;
504
+ io_uring_cqe_seen(&ring, cqe);
505
+
506
+ ret = T_EXIT_PASS;
507
+ fail:
508
+ io_uring_queue_exit(&ring);
509
+ if (sock != -1)
510
+ close(sock);
511
+ return ret;
512
+ }
513
+
358
514
  int main(int argc, char *argv[])
359
515
  {
360
516
  struct io_uring_probe *probe;
@@ -403,6 +559,12 @@ int main(int argc, char *argv[])
403
559
  fprintf(stderr, "bad listen failed\n");
404
560
  return T_EXIT_FAIL;
405
561
  }
406
-
562
+ if (!no_getsockname) {
563
+ ret = test_bad_sockname();
564
+ if (ret) {
565
+ fprintf(stderr, "bad sockname failed\n");
566
+ return T_EXIT_FAIL;
567
+ }
568
+ }
407
569
  return T_EXIT_PASS;
408
570
  }
@@ -462,7 +462,7 @@ static int test_buf_select_short(const char *filename, int nonvec)
462
462
  }
463
463
 
464
464
  exp_len = 0;
465
- for (i = 0; i < BUFFERS; i++) {
465
+ for (i = 0; i < 2 * BUFFERS; i++) {
466
466
  sqe = io_uring_get_sqe(&ring);
467
467
  io_uring_prep_provide_buffers(sqe, vecs[i].iov_base,
468
468
  vecs[i].iov_len / 2, 1, 1, i);
@@ -471,12 +471,12 @@ static int test_buf_select_short(const char *filename, int nonvec)
471
471
  }
472
472
 
473
473
  ret = io_uring_submit(&ring);
474
- if (ret != BUFFERS) {
474
+ if (ret != BUFFERS * 2) {
475
475
  fprintf(stderr, "submit: %d\n", ret);
476
476
  return -1;
477
477
  }
478
478
 
479
- for (i = 0; i < BUFFERS; i++) {
479
+ for (i = 0; i < BUFFERS * 2; i++) {
480
480
  ret = io_uring_wait_cqe(&ring, &cqe);
481
481
  if (cqe->res < 0) {
482
482
  fprintf(stderr, "cqe->res=%d\n", cqe->res);
@@ -935,7 +935,7 @@ int main(int argc, char *argv[])
935
935
 
936
936
  signal(SIGXFSZ, SIG_IGN);
937
937
 
938
- vecs = t_create_buffers(BUFFERS, BS);
938
+ vecs = t_create_buffers(2 * BUFFERS, BS);
939
939
 
940
940
  /* if we don't have nonvec read, skip testing that */
941
941
  nr = has_nonvec_read() ? 64 : 32;
@@ -14,7 +14,7 @@
14
14
  #include "helpers.h"
15
15
 
16
16
  #define BUF_SIZE 4096
17
- #define NR_BUFS 64
17
+ #define NR_BUFS 128
18
18
  #define FSIZE (BUF_SIZE * NR_BUFS)
19
19
 
20
20
  #define BR_MASK (NR_BUFS - 1)
@@ -87,7 +87,7 @@ static int test(const char *filename, int dio, int async)
87
87
  }
88
88
  io_uring_buf_ring_advance(br, NR_BUFS);
89
89
 
90
- for (i = 0; i < NR_BUFS; i++) {
90
+ for (i = 0; i < NR_BUFS / 2; i++) {
91
91
  sqe = io_uring_get_sqe(&ring);
92
92
  io_uring_prep_read(sqe, fd, NULL, BUF_SIZE, i * BUF_SIZE);
93
93
  sqe->buf_group = 1;
@@ -98,12 +98,12 @@ static int test(const char *filename, int dio, int async)
98
98
  }
99
99
 
100
100
  ret = io_uring_submit(&ring);
101
- if (ret != NR_BUFS) {
101
+ if (ret != NR_BUFS / 2) {
102
102
  fprintf(stderr, "submit: %d\n", ret);
103
103
  return 1;
104
104
  }
105
105
 
106
- for (i = 0; i < NR_BUFS; i++) {
106
+ for (i = 0; i < NR_BUFS / 2; i++) {
107
107
  int bid, ud;
108
108
 
109
109
  ret = io_uring_wait_cqe(&ring, &cqe);
@@ -7,6 +7,7 @@
7
7
  #include <stdlib.h>
8
8
  #include <string.h>
9
9
  #include <unistd.h>
10
+ #include <inttypes.h>
10
11
  #include <arpa/inet.h>
11
12
  #include <sys/types.h>
12
13
  #include <sys/socket.h>
@@ -17,7 +18,7 @@
17
18
 
18
19
  #define MAX_MSG 4096
19
20
 
20
- static unsigned long str[MAX_MSG / sizeof(unsigned long)];
21
+ static uint64_t str[MAX_MSG / sizeof(uint64_t)];
21
22
 
22
23
  #define PORT 10202
23
24
  #define HOST "127.0.0.1"
@@ -88,7 +89,7 @@ err:
88
89
  static int do_recv(struct io_uring *ring, struct iovec *iov, int enobufs)
89
90
  {
90
91
  struct io_uring_cqe *cqe;
91
- unsigned long *ptr;
92
+ uint64_t *ptr;
92
93
  int i, ret;
93
94
 
94
95
  ret = io_uring_wait_cqe(ring, &cqe);
@@ -118,10 +119,10 @@ static int do_recv(struct io_uring *ring, struct iovec *iov, int enobufs)
118
119
  }
119
120
 
120
121
  ptr = iov->iov_base;
121
- for (i = 0; i < MAX_MSG / sizeof(unsigned long); i++) {
122
+ for (i = 0; i < MAX_MSG / sizeof(uint64_t); i++) {
122
123
  if (ptr[i] == str[i])
123
124
  continue;
124
- fprintf(stderr, "data mismatch at %d: %lu\n", i, ptr[i]);
125
+ fprintf(stderr, "data mismatch at %d: %llu\n", i, (unsigned long long) ptr[i]);
125
126
  goto err;
126
127
  }
127
128
 
@@ -224,7 +225,7 @@ retry:
224
225
  sqe = io_uring_get_sqe(&ring);
225
226
  if (vec) {
226
227
  size_t total = MAX_MSG;
227
- unsigned long *ptr = str;
228
+ uint64_t *ptr = str;
228
229
  int i, nvecs;
229
230
 
230
231
  if (!big_vec) {
@@ -239,7 +240,7 @@ retry:
239
240
  for (i = 0; i < 32; i++) {
240
241
  vecs[i].iov_base = ptr;
241
242
  vecs[i].iov_len = total;
242
- ptr += total / sizeof(unsigned long);
243
+ ptr += total / sizeof(uint64_t);
243
244
  }
244
245
  nvecs = 32;
245
246
  }
@@ -371,7 +372,7 @@ int main(int argc, char *argv[])
371
372
  if (argc > 1)
372
373
  return T_EXIT_SKIP;
373
374
 
374
- for (i = 0; i < MAX_MSG / sizeof(unsigned long); i++)
375
+ for (i = 0; i < MAX_MSG / sizeof(uint64_t); i++)
375
376
  str[i] = i + 1;
376
377
 
377
378
  ret = test_invalid();
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uringmachine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.0
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
@@ -13,56 +13,56 @@ dependencies:
13
13
  name: rake-compiler
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - '='
16
+ - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 1.2.9
18
+ version: 1.3.0
19
19
  type: :development
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
- - - '='
23
+ - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 1.2.9
25
+ version: 1.3.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: minitest
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - '='
30
+ - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 5.25.4
32
+ version: 5.26.2
33
33
  type: :development
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - '='
37
+ - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 5.25.4
39
+ version: 5.26.2
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: benchmark-ips
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - '='
44
+ - - "~>"
45
45
  - !ruby/object:Gem::Version
46
46
  version: 2.14.0
47
47
  type: :development
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - '='
51
+ - - "~>"
52
52
  - !ruby/object:Gem::Version
53
53
  version: 2.14.0
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: http_parser.rb
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - '='
58
+ - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: 0.8.0
61
61
  type: :development
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - '='
65
+ - - "~>"
66
66
  - !ruby/object:Gem::Version
67
67
  version: 0.8.0
68
68
  email: sharon@noteflakes.com
@@ -690,14 +690,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
690
690
  requirements:
691
691
  - - ">="
692
692
  - !ruby/object:Gem::Version
693
- version: '3.4'
693
+ version: '3.5'
694
694
  required_rubygems_version: !ruby/object:Gem::Requirement
695
695
  requirements:
696
696
  - - ">="
697
697
  - !ruby/object:Gem::Version
698
698
  version: '0'
699
699
  requirements: []
700
- rubygems_version: 4.0.0.dev
700
+ rubygems_version: 4.0.0
701
701
  specification_version: 4
702
702
  summary: A lean, mean io_uring machine
703
703
  test_files: []