1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2021 SUSE LLC <mdoucha@suse.cz>
4 */
5
6 #define TST_NO_DEFAULT_MAIN
7 #include "tst_test.h"
8 #include "tst_safe_io_uring.h"
9
safe_io_uring_init(const char * file,const int lineno,unsigned int entries,struct io_uring_params * params,struct tst_io_uring * uring)10 int safe_io_uring_init(const char *file, const int lineno,
11 unsigned int entries, struct io_uring_params *params,
12 struct tst_io_uring *uring)
13 {
14 errno = 0;
15 uring->fd = io_uring_setup(entries, params);
16
17 if (uring->fd == -1) {
18 tst_brk_(file, lineno, TBROK | TERRNO,
19 "io_uring_setup() failed");
20 return uring->fd;
21 } else if (uring->fd < 0) {
22 tst_brk_(file, lineno, TBROK | TERRNO,
23 "io_uring_setup() returned invalid value %d",
24 uring->fd);
25 return uring->fd;
26 }
27
28 uring->sqr_size = params->sq_entries;
29 uring->cqr_size = params->cq_entries;
30 uring->sqr_mapsize = params->sq_off.array +
31 params->sq_entries * sizeof(__u32);
32 uring->cqr_mapsize = params->cq_off.cqes +
33 params->cq_entries * sizeof(struct io_uring_cqe);
34
35 uring->sqr_base = safe_mmap(file, lineno, NULL, uring->sqr_mapsize,
36 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, uring->fd,
37 IORING_OFF_SQ_RING);
38
39 if (uring->sqr_base == MAP_FAILED)
40 return -1;
41
42 uring->sqr_entries = safe_mmap(file, lineno, NULL,
43 params->sq_entries * sizeof(struct io_uring_sqe),
44 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, uring->fd,
45 IORING_OFF_SQES);
46
47 if (uring->sqr_entries == MAP_FAILED)
48 return -1;
49
50 uring->cqr_base = safe_mmap(file, lineno, NULL, uring->cqr_mapsize,
51 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, uring->fd,
52 IORING_OFF_CQ_RING);
53
54 if (uring->cqr_base == MAP_FAILED)
55 return -1;
56
57 uring->sqr_head = uring->sqr_base + params->sq_off.head;
58 uring->sqr_tail = uring->sqr_base + params->sq_off.tail;
59 uring->sqr_mask = uring->sqr_base + params->sq_off.ring_mask;
60 uring->sqr_flags = uring->sqr_base + params->sq_off.flags;
61 uring->sqr_dropped = uring->sqr_base + params->sq_off.dropped;
62 uring->sqr_array = uring->sqr_base + params->sq_off.array;
63
64 uring->cqr_head = uring->cqr_base + params->cq_off.head;
65 uring->cqr_tail = uring->cqr_base + params->cq_off.tail;
66 uring->cqr_mask = uring->cqr_base + params->cq_off.ring_mask;
67 uring->cqr_overflow = uring->cqr_base + params->cq_off.overflow;
68 uring->cqr_entries = uring->cqr_base + params->cq_off.cqes;
69 return uring->fd;
70 }
71
safe_io_uring_close(const char * file,const int lineno,struct tst_io_uring * uring)72 int safe_io_uring_close(const char *file, const int lineno,
73 struct tst_io_uring *uring)
74 {
75 int ret;
76
77 safe_munmap(file, lineno, NULL, uring->cqr_base, uring->cqr_mapsize);
78 safe_munmap(file, lineno, NULL, uring->sqr_entries,
79 uring->sqr_size * sizeof(struct io_uring_sqe));
80 safe_munmap(file, lineno, NULL, uring->sqr_base, uring->sqr_mapsize);
81 ret = safe_close(file, lineno, NULL, uring->fd);
82 uring->fd = -1;
83 return ret;
84 }
85
safe_io_uring_enter(const char * file,const int lineno,int strict,int fd,unsigned int to_submit,unsigned int min_complete,unsigned int flags,sigset_t * sig)86 int safe_io_uring_enter(const char *file, const int lineno, int strict,
87 int fd, unsigned int to_submit, unsigned int min_complete,
88 unsigned int flags, sigset_t *sig)
89 {
90 int ret;
91
92 errno = 0;
93 ret = io_uring_enter(fd, to_submit, min_complete, flags, sig);
94
95 if (ret == -1) {
96 tst_brk_(file, lineno, TBROK | TERRNO,
97 "io_uring_enter() failed");
98 } else if (ret < 0) {
99 tst_brk_(file, lineno, TBROK | TERRNO,
100 "Invalid io_uring_enter() return value %d", ret);
101 } else if (strict && to_submit != (unsigned int)ret) {
102 tst_brk_(file, lineno, TBROK,
103 "io_uring_enter() submitted %d items (expected %d)",
104 ret, to_submit);
105 }
106
107 return ret;
108 }
109