aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/liburing/test/sqwait.c
blob: 135b50be3a8fccfedffe7b55f3cdcf258d4ec31e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "../config-host.h"
/* SPDX-License-Identifier: MIT */
/*
 * Description: test that the app can always get a new sqe after having
 *		called io_uring_sqring_wait().
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "liburing.h"
#include "helpers.h"

#define NR_IOS	10000
#define INFLIGHT	256
#define FILE_SIZE	(256 * 1024 * 1024)

static int inflight;

static int reap(struct io_uring *ring)
{
	struct io_uring_cqe *cqe;
	int ret;

	while (inflight >= INFLIGHT / 2) {
		ret = io_uring_wait_cqe(ring, &cqe);
		if (ret < 0) {
			fprintf(stderr, "wait=%d\n", ret);
			return 1;
		}
		if (cqe->res < 0) {
			printf("cqe res %d\n", cqe->res);
			return 1;
		}
		io_uring_cqe_seen(ring, cqe);
		inflight--;
	}

	return 0;
}

int main(int argc, char *argv[])
{
	struct io_uring_sqe *sqe;
	struct io_uring ring;
	int fd = -1, i, iov_off, ret, fret;
	struct iovec iovs[INFLIGHT];
	const char *fname;
	char buf[256];
	loff_t off;

	if (argc > 1) {
		fname = argv[1];
	} else {
		srand((unsigned)time(NULL));
		snprintf(buf, sizeof(buf), ".sqwait-%u-%u", (unsigned)rand(),
			 (unsigned)getpid());
		fname = buf;
		t_create_file(fname, FILE_SIZE);
	}

	fret = T_EXIT_SKIP;
	ret = io_uring_queue_init(8, &ring, IORING_SETUP_SQPOLL);
	if (ret < 0) {
		if (errno == EINVAL || errno == EPERM)
			goto err;
		fprintf(stderr, "queue init %d\n", ret);
		fret = T_EXIT_FAIL;
		goto err;
	}

	fd = open(fname, O_RDONLY | O_DIRECT);
	if (fd < 0) {
		if (errno == EACCES || errno == EPERM || errno == EINVAL)
			return T_EXIT_SKIP;
		perror("open");
		fret = T_EXIT_FAIL;
		goto err;
	}

	for (i = 0; i < INFLIGHT; i++) {
		if (posix_memalign(&iovs[i].iov_base, 4096, 4096))
			goto err;
		iovs[i].iov_len = 4096;
	}

	iov_off = off = 0;
	for (i = 0; i < NR_IOS; i++) {
		struct iovec *iov = &iovs[iov_off];

		sqe = io_uring_get_sqe(&ring);
		if (!sqe) {
			ret = io_uring_sqring_wait(&ring);
			if (ret < 0) {
				if (ret == -EINVAL)
					return T_EXIT_SKIP;
				fprintf(stderr, "sqwait=%d\n", ret);
				fret = T_EXIT_FAIL;
				goto err;
			}
			sqe = io_uring_get_sqe(&ring);
			if (!sqe) {
				fprintf(stderr, "No sqe post wait\n");
				fret = T_EXIT_FAIL;
				goto err;
			}
		}
		io_uring_prep_read(sqe, fd, iov->iov_base, iov->iov_len, 0);
		io_uring_submit(&ring);
		inflight++;

		iov_off++;
		if (iov_off == INFLIGHT)
			iov_off = 0;
		off += 8192;
		if (off > FILE_SIZE - 8192)
			off = 0;
		if (reap(&ring)) {
			fret = T_EXIT_FAIL;
			goto err;
		}
	}

	if (fd != -1)
		close(fd);
	if (fname != argv[1])
		unlink(fname);
	io_uring_queue_exit(&ring);
	return T_EXIT_PASS;
err:
	if (fd != -1)
		close(fd);
	if (fname != argv[1])
		unlink(fname);
	return fret;
}