92 static const auto probeResult = [] {
95 int ret = io_uring_queue_init(1 , &ring, 0 );
97 io_uring_queue_exit(&ring);
98 return std::pair<bool, std::string>(
true,
"");
100 std::string msg = std::strerror(-ret);
102 msg +=
": the running kernel does not support io_uring (CONFIG_IO_URING is not set)";
103 else if (ret == -EPERM)
104 msg +=
": the io_uring_setup system call is blocked, e.g. by a seccomp profile";
105 return std::pair<bool, std::string>(
false, msg);
108 *errMsg = probeResult.second;
109 return probeResult.first;
129 unsigned int batch = 0;
130 unsigned int batchSize =
fDepth;
131 unsigned int readPos = 0;
133 while (readPos < nReads) {
134 if (readPos + batchSize > nReads) {
135 batchSize = nReads - readPos;
138 struct io_uring_sqe *sqe;
139 for (std::size_t i = readPos; i < readPos + batchSize; ++i) {
140 sqe = io_uring_get_sqe(&
fRing);
142 throw std::runtime_error(
"batch " + std::to_string(batch) +
": "
143 +
"get SQE failed for read request '" + std::to_string(i)
144 +
"', error: " + std::string(strerror(errno)));
146 if (readEvents[i].fFileDes == -1) {
147 throw std::runtime_error(
"batch " + std::to_string(batch) +
": "
148 +
"bad fd (-1) for read request '" + std::to_string(i) +
"'");
150 if (readEvents[i].
fBuffer ==
nullptr) {
151 throw std::runtime_error(
"batch " + std::to_string(batch) +
": "
152 +
"null read buffer for read request '" + std::to_string(i) +
"'");
154 io_uring_prep_read(sqe,
155 readEvents[i].fFileDes,
158 readEvents[i].fOffset
160 sqe->flags |= IOSQE_ASYNC;
165 int submitted = io_uring_submit_and_wait(&
fRing, batchSize);
166 if (submitted <= 0) {
167 throw std::runtime_error(
"batch " + std::to_string(batch) +
": "
168 "ring submit failed, error: " + std::string(strerror(errno)));
170 if (submitted !=
static_cast<int>(batchSize)) {
171 throw std::runtime_error(
"ring submitted " + std::to_string(submitted) +
172 " events but requested " + std::to_string(batchSize));
175 struct io_uring_cqe *cqe;
177 for (
int i = 0; i < submitted; ++i) {
178 ret = io_uring_wait_cqe(&
fRing, &cqe);
180 throw std::runtime_error(
"wait cqe failed, error: " + std::string(std::strerror(-ret)));
182 auto index =
reinterpret_cast<std::size_t
>(io_uring_cqe_get_data(cqe));
183 if (
index >= nReads) {
184 throw std::runtime_error(
"bad cqe user data: " + std::to_string(
index));
187 throw std::runtime_error(
"batch " + std::to_string(batch) +
": "
188 +
"read failed for ReadEvent[" + std::to_string(
index) +
"], "
189 "error: " + std::string(std::strerror(-cqe->res)));
192 io_uring_cqe_seen(&
fRing, cqe);
194 readPos += batchSize;