• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: link <open file><read from file><close file> with an existing
4  * file present in the opened slot, verifying that we get the new file
5  * rather than the old one.
6  *
7  */
8 #include <errno.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <fcntl.h>
14 
15 #include "liburing.h"
16 #include "helpers.h"
17 
18 #define MAX_FILES	8
19 #define FNAME1		".slot.reuse.1"
20 #define FNAME2		".slot.reuse.2"
21 #define PAT1		0xaa
22 #define PAT2		0x55
23 #define BSIZE		4096
24 
test(struct io_uring * ring)25 static int test(struct io_uring *ring)
26 {
27 	struct io_uring_cqe *cqe;
28 	struct io_uring_sqe *sqe;
29 	char buf[BSIZE];
30 	int ret, i;
31 
32 	/* open FNAME1 in slot 0 */
33 	sqe = io_uring_get_sqe(ring);
34 	io_uring_prep_openat_direct(sqe, AT_FDCWD, FNAME1, O_RDONLY, 0, 0);
35 	sqe->user_data = 1;
36 
37 	ret = io_uring_submit(ring);
38 	if (ret != 1) {
39 		fprintf(stderr, "sqe submit failed: %d\n", ret);
40 		goto err;
41 	}
42 
43 	ret = io_uring_wait_cqe(ring, &cqe);
44 	if (ret < 0) {
45 		fprintf(stderr, "wait completion %d\n", ret);
46 		goto err;
47 	}
48 	if (cqe->res != 0) {
49 		fprintf(stderr, "open res %d\n", ret);
50 		goto err;
51 	}
52 	io_uring_cqe_seen(ring, cqe);
53 
54 	/*
55 	 * Now open FNAME2 in that same slot, verifying we get data from
56 	 * FNAME2 and not FNAME1.
57 	 */
58 	sqe = io_uring_get_sqe(ring);
59 	io_uring_prep_openat_direct(sqe, AT_FDCWD, FNAME2, O_RDONLY, 0, 0);
60 	sqe->flags |= IOSQE_IO_LINK;
61 	sqe->user_data = 2;
62 
63 	sqe = io_uring_get_sqe(ring);
64 	io_uring_prep_read(sqe, 0, buf, sizeof(buf), 0);
65 	sqe->flags |= IOSQE_FIXED_FILE;
66 	sqe->flags |= IOSQE_IO_LINK;
67 	sqe->user_data = 3;
68 
69 	sqe = io_uring_get_sqe(ring);
70 	io_uring_prep_close_direct(sqe, 0);
71 	sqe->user_data = 4;
72 
73 	ret = io_uring_submit(ring);
74 	if (ret != 3) {
75 		fprintf(stderr, "sqe submit failed: %d\n", ret);
76 		goto err;
77 	}
78 
79 	for (i = 0; i < 3; i++) {
80 		ret = io_uring_wait_cqe(ring, &cqe);
81 		if (ret < 0) {
82 			fprintf(stderr, "wait completion %d\n", ret);
83 			goto err;
84 		}
85 		switch (cqe->user_data) {
86 		case 2:
87 			if (cqe->res) {
88 				fprintf(stderr, "bad open %d\n", cqe->res);
89 				goto err;
90 			}
91 			break;
92 		case 3:
93 			if (cqe->res != sizeof(buf)) {
94 				fprintf(stderr, "bad read %d\n", cqe->res);
95 				goto err;
96 			}
97 			break;
98 		case 4:
99 			if (cqe->res) {
100 				fprintf(stderr, "bad close %d\n", cqe->res);
101 				goto err;
102 			}
103 			break;
104 		}
105 		io_uring_cqe_seen(ring, cqe);
106 	}
107 
108 	for (i = 0; i < sizeof(buf); i++) {
109 		if (buf[i] == PAT2)
110 			continue;
111 		fprintf(stderr, "Bad pattern %x at %d\n", buf[i], i);
112 		goto err;
113 	}
114 
115 	return 0;
116 err:
117 	return 1;
118 }
119 
main(int argc,char * argv[])120 int main(int argc, char *argv[])
121 {
122 	struct io_uring ring;
123 	struct io_uring_params p = { };
124 	int ret, files[MAX_FILES];
125 
126 	if (argc > 1)
127 		return 0;
128 
129 	ret = io_uring_queue_init_params(8, &ring, &p);
130 	if (ret) {
131 		fprintf(stderr, "ring setup failed: %d\n", ret);
132 		return 1;
133 	}
134 	if (!(p.features & IORING_FEAT_CQE_SKIP))
135 		return 0;
136 
137 	memset(files, -1, sizeof(files));
138 	ret = io_uring_register_files(&ring, files, ARRAY_SIZE(files));
139 	if (ret) {
140 		fprintf(stderr, "Failed registering files\n");
141 		return 1;
142 	}
143 
144 	t_create_file_pattern(FNAME1, 4096, PAT1);
145 	t_create_file_pattern(FNAME2, 4096, PAT2);
146 
147 	ret = test(&ring);
148 	if (ret) {
149 		fprintf(stderr, "test failed\n");
150 		goto err;
151 	}
152 
153 	unlink(FNAME1);
154 	unlink(FNAME2);
155 	return 0;
156 err:
157 	unlink(FNAME1);
158 	unlink(FNAME2);
159 	return 1;
160 }
161