File: io-wq-exit.c

package info (click to toggle)
liburing 2.14-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,448 kB
  • sloc: ansic: 59,512; sh: 816; makefile: 603; cpp: 32
file content (131 lines) | stat: -rw-r--r-- 2,779 bytes parent folder | download
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
/* SPDX-License-Identifier: MIT */
/*
 * Description: Test that created thread that sets up a ring and causes io-wq
 *		worker creation doesn't need to wait for io-wq idle worker
 *		timeout to exit.
 *
 */
#include <fcntl.h>
#include <pthread.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

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

#define BUF_LEN		20

static void *test(void *data)
{
	int fd_src = -1, fd_dst = -1, pipe_fds[2] = { -1, -1 };
	uint8_t buffer_write[BUF_LEN], buffer_read[BUF_LEN];
	char dst_fname[PATH_MAX], src_fname[PATH_MAX];
	struct io_uring_sqe *sqe;
	struct io_uring_cqe *cqe;
	struct io_uring ring;
	int ret;

	ret = io_uring_queue_init(4, &ring, 0);
	if (ret < 0) {
		fprintf(stderr, "io_uring_queue_init failed: %d\n", ret);
		return NULL;
	}

	sprintf(src_fname, ".splice.%d.src", getpid());
	fd_src = open(src_fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd_src < 0) {
		perror("open source");
		goto cleanup;
	}

	sprintf(dst_fname, ".splice.%d.dst", getpid());
	fd_dst = open(dst_fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
	if (fd_dst < 0) {
		perror("open destination");
		goto cleanup;
	}

	memset(buffer_write, 97, BUF_LEN);
	memset(buffer_read, 98, BUF_LEN);
	ret = pwrite(fd_src, buffer_write, BUF_LEN, 0);
	if (ret < 0) {
		perror("pwrite src");
		goto cleanup;
	}

	if (pipe(pipe_fds) < 0) {
		perror("pipe");
		goto cleanup;
	}

	sqe = io_uring_get_sqe(&ring);
	io_uring_prep_splice(sqe, fd_src, 0, pipe_fds[1], -1, 20, 0);
	sqe->user_data = 1;

	sqe = io_uring_get_sqe(&ring);
	io_uring_prep_splice(sqe, pipe_fds[0], -1, fd_dst, 10, 20, 0);
	sqe->user_data = 2;

	io_uring_submit(&ring);

	ret = io_uring_wait_cqe(&ring, &cqe);
	if (ret) {
		fprintf(stderr, "wait cqe %d\n", ret);
		goto cleanup;
	}
	io_uring_cqe_seen(&ring, cqe);

	ret = io_uring_wait_cqe(&ring, &cqe);
	if (ret) {
		fprintf(stderr, "wait cqe %d\n", ret);
		goto cleanup;
	}
	io_uring_cqe_seen(&ring, cqe);
cleanup:
	if (pipe_fds[0] != -1)
		close(pipe_fds[0]);
	if (pipe_fds[1] != -1)
		close(pipe_fds[1]);
	if (fd_src != -1)
		close(fd_src);
	if (fd_src != -1)
		close(fd_dst);
	io_uring_queue_exit(&ring);
	unlink(src_fname);
	unlink(dst_fname);
	return NULL;
}

static long get_time_ns(void)
{
	struct timespec ts;

	clock_gettime(CLOCK_MONOTONIC, &ts);
	return ts.tv_sec * 1000000000L + ts.tv_nsec;
}

int main(int argc, char *argv[])
{
	pthread_t thread;
	long start, end;

	if (argc > 1)
		return T_EXIT_SKIP;

	start = get_time_ns();
	pthread_create(&thread, NULL, test, NULL);
	pthread_join(thread, NULL);
	end = get_time_ns();
	end -= start;
	end /= 1000000;
	if (end >= 500) {
		fprintf(stderr, "Test took too long: %lu msec\n", end);
		return T_EXIT_FAIL;
	}

	return T_EXIT_PASS;
}