Skip to content

Commit 5305e15

Browse files
committed
Add test cases for IORING_CQE_F_POLLED
Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 9a0461d commit 5305e15

4 files changed

Lines changed: 488 additions & 0 deletions

File tree

src/include/liburing/io_uring.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,12 +457,18 @@ struct io_uring_cqe {
457457
* other provided buffer type, all completions with a
458458
* buffer passed back is automatically returned to the
459459
* application.
460+
* IORING_CQE_F_POLLED If set, the operation was completed after being through
461+
* the poll machinery. For a write/send, this meant the
462+
* socket was full when the operation was attempted. For
463+
* a read operation, the socket/fd was empty when it was
464+
* initially attempted.
460465
*/
461466
#define IORING_CQE_F_BUFFER (1U << 0)
462467
#define IORING_CQE_F_MORE (1U << 1)
463468
#define IORING_CQE_F_SOCK_NONEMPTY (1U << 2)
464469
#define IORING_CQE_F_NOTIF (1U << 3)
465470
#define IORING_CQE_F_BUF_MORE (1U << 4)
471+
#define IORING_CQE_F_POLLED (1U << 5)
466472

467473
#define IORING_CQE_BUFFER_SHIFT 16
468474

test/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ test_srcs := \
155155
personality.c \
156156
pipe-bug.c \
157157
pipe-eof.c \
158+
pipe-full.c \
158159
pipe-reuse.c \
159160
poll.c \
160161
poll-cancel.c \
@@ -200,6 +201,7 @@ test_srcs := \
200201
self.c \
201202
recvsend_bundle.c \
202203
recvsend_bundle-inc.c \
204+
send_full.c \
203205
send_recv.c \
204206
send_recvmsg.c \
205207
send-zerocopy.c \

test/pipe-full.c

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Description: Test flagging of IORING_CQE_F_POLLED on both read and write
4+
* side of a pipe.
5+
*/
6+
#include <errno.h>
7+
#include <stdio.h>
8+
#include <string.h>
9+
#include <unistd.h>
10+
#include <string.h>
11+
12+
#include "liburing.h"
13+
#include "helpers.h"
14+
15+
static bool set_nonblock(int fd)
16+
{
17+
int fl;
18+
19+
fl = fcntl(fd, F_GETFL, 0);
20+
if (fl < 0) {
21+
perror("fcntl get");
22+
return false;
23+
}
24+
fl |= O_NONBLOCK;
25+
if (fcntl(fd, F_SETFL, fl) < 0) {
26+
perror("fcntl set");
27+
return false;
28+
}
29+
30+
return true;
31+
}
32+
33+
static int test_write(struct io_uring *ring, int *fds)
34+
{
35+
struct io_uring_sqe *sqe;
36+
struct io_uring_cqe *cqe;
37+
unsigned fl1, fl2;
38+
char buf[32];
39+
int ret;
40+
41+
if (!set_nonblock(fds[0]) || !set_nonblock(fds[1]))
42+
return T_EXIT_FAIL;
43+
44+
memset(buf, 0x5a, sizeof(buf));
45+
do {
46+
ret = write(fds[1], buf, sizeof(buf));
47+
if (ret < 0) {
48+
if (errno == EAGAIN)
49+
break;
50+
perror("write pipe");
51+
return T_EXIT_FAIL;
52+
}
53+
} while (1);
54+
55+
sqe = io_uring_get_sqe(ring);
56+
io_uring_prep_write(sqe, fds[1], buf, sizeof(buf), 0);
57+
io_uring_submit(ring);
58+
59+
/* drain read side so our write can complete */
60+
do {
61+
ret = read(fds[0], buf, sizeof(buf));
62+
if (ret < 0) {
63+
if (errno == EAGAIN)
64+
break;
65+
perror("read pipe");
66+
return T_EXIT_FAIL;
67+
} else if (!ret) {
68+
break;
69+
}
70+
} while (1);
71+
72+
ret = io_uring_wait_cqe(ring, &cqe);
73+
if (ret) {
74+
fprintf(stderr, "wait_cqe: %d\n", ret);
75+
return T_EXIT_FAIL;
76+
}
77+
fl1 = cqe->flags;
78+
io_uring_cqe_seen(ring, cqe);
79+
80+
sqe = io_uring_get_sqe(ring);
81+
io_uring_prep_write(sqe, fds[1], buf, sizeof(buf), 0);
82+
io_uring_submit(ring);
83+
84+
ret = io_uring_wait_cqe(ring, &cqe);
85+
if (ret) {
86+
fprintf(stderr, "wait_cqe: %d\n", ret);
87+
return T_EXIT_FAIL;
88+
}
89+
fl2 = cqe->flags;
90+
io_uring_cqe_seen(ring, cqe);
91+
92+
if (!(fl1 & IORING_CQE_F_POLLED) && (fl2 & IORING_CQE_F_POLLED)) {
93+
fprintf(stderr, "write test odd POLLED flags\n");
94+
return T_EXIT_FAIL;
95+
}
96+
if (fl1 & IORING_CQE_F_POLLED)
97+
fprintf(stdout, "Pipe write side sets IORING_CQE_F_POLLED\n");
98+
return 0;
99+
}
100+
101+
static int test_read(struct io_uring *ring, int *fds)
102+
{
103+
struct io_uring_sqe *sqe;
104+
struct io_uring_cqe *cqe;
105+
unsigned int fl1, fl2;
106+
char buf[32];
107+
int ret;
108+
109+
sqe = io_uring_get_sqe(ring);
110+
io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
111+
io_uring_submit(ring);
112+
113+
ret = write(fds[1], "foo", 3);
114+
if (ret < 0) {
115+
perror("write pipe");
116+
return T_EXIT_FAIL;
117+
}
118+
119+
ret = io_uring_wait_cqe(ring, &cqe);
120+
if (ret) {
121+
fprintf(stderr, "wait_cqe: %d\n", ret);
122+
return T_EXIT_FAIL;
123+
}
124+
fl1 = cqe->flags;
125+
io_uring_cqe_seen(ring, cqe);
126+
127+
ret = write(fds[1], "foo", 3);
128+
if (ret < 0) {
129+
perror("write pipe");
130+
return T_EXIT_FAIL;
131+
}
132+
133+
sqe = io_uring_get_sqe(ring);
134+
io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
135+
io_uring_submit(ring);
136+
137+
ret = io_uring_wait_cqe(ring, &cqe);
138+
if (ret) {
139+
fprintf(stderr, "wait_cqe: %d\n", ret);
140+
return T_EXIT_FAIL;
141+
}
142+
fl2 = cqe->flags;
143+
io_uring_cqe_seen(ring, cqe);
144+
145+
if (!(fl1 & IORING_CQE_F_POLLED) && (fl2 & IORING_CQE_F_POLLED)) {
146+
fprintf(stderr, "read test odd POLLED flags\n");
147+
return T_EXIT_FAIL;
148+
}
149+
if (fl1 & IORING_CQE_F_POLLED)
150+
fprintf(stdout, "Pipe read side sets IORING_CQE_F_POLLED\n");
151+
return 0;
152+
}
153+
154+
int main(int argc, char *argv[])
155+
{
156+
struct io_uring ring;
157+
int ret, fds[2];
158+
159+
if (argc > 1)
160+
return T_EXIT_SKIP;
161+
162+
if (pipe(fds) < 0) {
163+
perror("pipe");
164+
return T_EXIT_FAIL;
165+
}
166+
167+
io_uring_queue_init(4, &ring, 0);
168+
169+
ret = test_read(&ring, fds);
170+
if (ret)
171+
return ret;
172+
173+
ret = test_write(&ring, fds);
174+
if (ret)
175+
return ret;
176+
177+
close(fds[0]);
178+
close(fds[1]);
179+
io_uring_queue_exit(&ring);
180+
return 0;
181+
}

0 commit comments

Comments
 (0)