The unpac monorepo manager self-hosting as a monorepo using unpac
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge commit 'c1934854af69536419f8224a0845c5021cd82781' into liburing-2.3

+7587 -1330
+10 -6
vendor/liburing/.github/workflows/build.yml
··· 7 7 8 8 jobs: 9 9 build: 10 - runs-on: ubuntu-latest 10 + runs-on: ubuntu-22.04 11 11 12 12 strategy: 13 13 fail-fast: false ··· 26 26 cxx_pkg: clang 27 27 cc: clang 28 28 cxx: clang++ 29 + extra_flags: -Wshorten-64-to-32 29 30 30 31 # x86 (32-bit) gcc 31 32 - arch: i686 ··· 84 85 cxx: mips-linux-gnu-g++ 85 86 86 87 env: 87 - FLAGS: -g -O2 -Wall -Wextra -Werror 88 + FLAGS: -g -O3 -Wall -Wextra -Werror 89 + 90 + # Flags for building sources in src/ dir only. 91 + LIBURING_CFLAGS: ${{matrix.extra_flags}} 88 92 89 93 steps: 90 94 - name: Checkout source ··· 94 98 run: | 95 99 if [[ "${{matrix.cc_pkg}}" == "clang" ]]; then \ 96 100 wget https://apt.llvm.org/llvm.sh -O /tmp/llvm.sh; \ 97 - sudo bash /tmp/llvm.sh 15; \ 98 - sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-15 400; \ 99 - sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-15 400; \ 101 + sudo bash /tmp/llvm.sh 16; \ 102 + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-16 400; \ 103 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-16 400; \ 100 104 else \ 101 105 sudo apt-get update -y; \ 102 106 sudo apt-get install -y ${{matrix.cc_pkg}} ${{matrix.cxx_pkg}}; \ ··· 114 118 115 119 - name: Build nolibc 116 120 run: | 117 - if [[ "${{matrix.arch}}" == "x86_64" || "${{matrix.arch}}" == "i686" ]]; then \ 121 + if [[ "${{matrix.arch}}" == "x86_64" || "${{matrix.arch}}" == "i686" || "${{matrix.arch}}" == "aarch64" ]]; then \ 118 122 make clean; \ 119 123 ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} --nolibc; \ 120 124 make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS"; \
+1 -1
vendor/liburing/.github/workflows/shellcheck.yml
··· 7 7 8 8 jobs: 9 9 test: 10 - runs-on: ubuntu-latest 10 + runs-on: ubuntu-22.04 11 11 12 12 steps: 13 13 - name: Checkout source
+3
vendor/liburing/.gitignore
··· 13 13 14 14 /examples/io_uring-cp 15 15 /examples/io_uring-test 16 + /examples/io_uring-udp 16 17 /examples/link-cp 17 18 /examples/ucontext-cp 19 + /examples/poll-bench 20 + /examples/send-zerocopy 18 21 19 22 /test/*.t 20 23 /test/*.dmesg
+18 -1
vendor/liburing/CHANGELOG
··· 1 + liburing-2.3 release 2 + 3 + - Support non-libc build for aarch64. 4 + - Add io_uring_{enter,enter2,register,setup} syscall functions. 5 + - Add sync cancel interface, io_uring_register_sync_cancel(). 6 + - Fix return value of io_uring_submit_and_wait_timeout() to match the 7 + man page. 8 + - Improvements to the regression tests 9 + - Add support and test case for passthrough IO 10 + - Add recv and recvmsg multishot helpers and support 11 + - Add documentation and support for IORING_SETUP_DEFER_TASKRUN 12 + - Fix potential missing kernel entry with IORING_SETUP_IOPOLL 13 + - Add support and documentation for zero-copy network transmit 14 + - Various optimizations 15 + - Many cleanups 16 + - Many man page additions and updates 17 + 1 18 liburing-2.2 release 2 19 3 20 - Support non-libc builds. ··· 6 23 - Add support for multishot accept. 7 24 - io_uring_register_files() will set RLIMIT_NOFILE if necessary. 8 25 - Add support for registered ring fds, io_uring_register_ring_fd(), 9 - reducingthe overhead of an io_uring_enter() system call. 26 + reducing the overhead of an io_uring_enter() system call. 10 27 - Add support for the message ring opcode. 11 28 - Add support for newer request cancelation features. 12 29 - Add support for IORING_SETUP_COOP_TASKRUN, which can help reduce the
+12 -12
vendor/liburing/configure
··· 368 368 print_config "has_ucontext" "$has_ucontext" 369 369 370 370 ########################################## 371 - # check for memfd_create(2) 372 - has_memfd_create="no" 371 + # Check NVME_URING_CMD support 372 + nvme_uring_cmd="no" 373 373 cat > $TMPC << EOF 374 - #include <sys/mman.h> 375 - int main(int argc, char **argv) 374 + #include <linux/nvme_ioctl.h> 375 + int main(void) 376 376 { 377 - int memfd = memfd_create("test", 0); 378 - return 0; 377 + struct nvme_uring_cmd *cmd; 378 + 379 + return sizeof(struct nvme_uring_cmd); 379 380 } 380 381 EOF 381 - if compile_prog "-Werror=implicit-function-declaration" "" "has_memfd_create"; then 382 - has_memfd_create="yes" 382 + if compile_prog "" "" "nvme uring cmd"; then 383 + nvme_uring_cmd="yes" 383 384 fi 384 - print_config "has_memfd_create" "$has_memfd_create" 385 - 385 + print_config "NVMe uring command support" "$nvme_uring_cmd" 386 386 387 387 ############################################################################# 388 388 if test "$liburing_nolibc" = "yes"; then ··· 419 419 if test "$array_bounds" = "yes"; then 420 420 output_sym "CONFIG_HAVE_ARRAY_BOUNDS" 421 421 fi 422 - if test "$has_memfd_create" = "yes"; then 423 - output_sym "CONFIG_HAVE_MEMFD_CREATE" 422 + if test "$nvme_uring_cmd" = "yes"; then 423 + output_sym "CONFIG_HAVE_NVME_URING" 424 424 fi 425 425 426 426 echo "CC=$cc" >> $config_host_mak
+4 -1
vendor/liburing/examples/Makefile
··· 13 13 example_srcs := \ 14 14 io_uring-cp.c \ 15 15 io_uring-test.c \ 16 - link-cp.c 16 + io_uring-udp.c \ 17 + link-cp.c \ 18 + poll-bench.c \ 19 + send-zerocopy.c 17 20 18 21 all_targets := 19 22
+395
vendor/liburing/examples/io_uring-udp.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + 3 + #include <stdio.h> 4 + #include <unistd.h> 5 + #include <errno.h> 6 + #include <sys/mman.h> 7 + #include <stdlib.h> 8 + #include <string.h> 9 + #include <netinet/udp.h> 10 + #include <arpa/inet.h> 11 + 12 + #include "liburing.h" 13 + 14 + #define QD 64 15 + #define BUF_SHIFT 12 /* 4k */ 16 + #define CQES (QD * 16) 17 + #define BUFFERS CQES 18 + #define CONTROLLEN 0 19 + 20 + struct sendmsg_ctx { 21 + struct msghdr msg; 22 + struct iovec iov; 23 + }; 24 + 25 + struct ctx { 26 + struct io_uring ring; 27 + struct io_uring_buf_ring *buf_ring; 28 + unsigned char *buffer_base; 29 + struct msghdr msg; 30 + int buf_shift; 31 + int af; 32 + bool verbose; 33 + struct sendmsg_ctx send[BUFFERS]; 34 + size_t buf_ring_size; 35 + }; 36 + 37 + static size_t buffer_size(struct ctx *ctx) 38 + { 39 + return 1U << ctx->buf_shift; 40 + } 41 + 42 + static unsigned char *get_buffer(struct ctx *ctx, int idx) 43 + { 44 + return ctx->buffer_base + (idx << ctx->buf_shift); 45 + } 46 + 47 + static int setup_buffer_pool(struct ctx *ctx) 48 + { 49 + int ret, i; 50 + void *mapped; 51 + struct io_uring_buf_reg reg = { .ring_addr = 0, 52 + .ring_entries = BUFFERS, 53 + .bgid = 0 }; 54 + 55 + ctx->buf_ring_size = (sizeof(struct io_uring_buf) + buffer_size(ctx)) * BUFFERS; 56 + mapped = mmap(NULL, ctx->buf_ring_size, PROT_READ | PROT_WRITE, 57 + MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 58 + if (mapped == MAP_FAILED) { 59 + fprintf(stderr, "buf_ring mmap: %s\n", strerror(errno)); 60 + return -1; 61 + } 62 + ctx->buf_ring = (struct io_uring_buf_ring *)mapped; 63 + 64 + io_uring_buf_ring_init(ctx->buf_ring); 65 + 66 + reg = (struct io_uring_buf_reg) { 67 + .ring_addr = (unsigned long)ctx->buf_ring, 68 + .ring_entries = BUFFERS, 69 + .bgid = 0 70 + }; 71 + ctx->buffer_base = (unsigned char *)ctx->buf_ring + 72 + sizeof(struct io_uring_buf) * BUFFERS; 73 + 74 + ret = io_uring_register_buf_ring(&ctx->ring, &reg, 0); 75 + if (ret) { 76 + fprintf(stderr, "buf_ring init failed: %s\n" 77 + "NB This requires a kernel version >= 6.0\n", 78 + strerror(-ret)); 79 + return ret; 80 + } 81 + 82 + for (i = 0; i < BUFFERS; i++) { 83 + io_uring_buf_ring_add(ctx->buf_ring, get_buffer(ctx, i), buffer_size(ctx), i, 84 + io_uring_buf_ring_mask(BUFFERS), i); 85 + } 86 + io_uring_buf_ring_advance(ctx->buf_ring, BUFFERS); 87 + 88 + return 0; 89 + } 90 + 91 + static int setup_context(struct ctx *ctx) 92 + { 93 + struct io_uring_params params; 94 + int ret; 95 + 96 + memset(&params, 0, sizeof(params)); 97 + params.cq_entries = QD * 8; 98 + params.flags = IORING_SETUP_SUBMIT_ALL | IORING_SETUP_COOP_TASKRUN | 99 + IORING_SETUP_CQSIZE; 100 + 101 + ret = io_uring_queue_init_params(QD, &ctx->ring, &params); 102 + if (ret < 0) { 103 + fprintf(stderr, "queue_init failed: %s\n" 104 + "NB: This requires a kernel version >= 6.0\n", 105 + strerror(-ret)); 106 + return ret; 107 + } 108 + 109 + ret = setup_buffer_pool(ctx); 110 + if (ret) 111 + io_uring_queue_exit(&ctx->ring); 112 + 113 + memset(&ctx->msg, 0, sizeof(ctx->msg)); 114 + ctx->msg.msg_namelen = sizeof(struct sockaddr_storage); 115 + ctx->msg.msg_controllen = CONTROLLEN; 116 + return ret; 117 + } 118 + 119 + static int setup_sock(int af, int port) 120 + { 121 + int ret; 122 + int fd; 123 + uint16_t nport = port <= 0 ? 0 : htons(port); 124 + 125 + fd = socket(af, SOCK_DGRAM, 0); 126 + if (fd < 0) { 127 + fprintf(stderr, "sock_init: %s\n", strerror(errno)); 128 + return -1; 129 + } 130 + 131 + if (af == AF_INET6) { 132 + struct sockaddr_in6 addr6 = { 133 + .sin6_family = af, 134 + .sin6_port = nport, 135 + .sin6_addr = IN6ADDR_ANY_INIT 136 + }; 137 + 138 + ret = bind(fd, (struct sockaddr *) &addr6, sizeof(addr6)); 139 + } else { 140 + struct sockaddr_in addr = { 141 + .sin_family = af, 142 + .sin_port = nport, 143 + .sin_addr = { INADDR_ANY } 144 + }; 145 + 146 + ret = bind(fd, (struct sockaddr *) &addr, sizeof(addr)); 147 + } 148 + 149 + if (ret) { 150 + fprintf(stderr, "sock_bind: %s\n", strerror(errno)); 151 + close(fd); 152 + return -1; 153 + } 154 + 155 + if (port <= 0) { 156 + int port; 157 + struct sockaddr_storage s; 158 + socklen_t sz = sizeof(s); 159 + 160 + if (getsockname(fd, (struct sockaddr *)&s, &sz)) { 161 + fprintf(stderr, "getsockname failed\n"); 162 + close(fd); 163 + return -1; 164 + } 165 + 166 + port = ntohs(((struct sockaddr_in *)&s)->sin_port); 167 + fprintf(stderr, "port bound to %d\n", port); 168 + } 169 + 170 + return fd; 171 + } 172 + 173 + static void cleanup_context(struct ctx *ctx) 174 + { 175 + munmap(ctx->buf_ring, ctx->buf_ring_size); 176 + io_uring_queue_exit(&ctx->ring); 177 + } 178 + 179 + static bool get_sqe(struct ctx *ctx, struct io_uring_sqe **sqe) 180 + { 181 + *sqe = io_uring_get_sqe(&ctx->ring); 182 + 183 + if (!*sqe) { 184 + io_uring_submit(&ctx->ring); 185 + *sqe = io_uring_get_sqe(&ctx->ring); 186 + } 187 + if (!*sqe) { 188 + fprintf(stderr, "cannot get sqe\n"); 189 + return true; 190 + } 191 + return false; 192 + } 193 + 194 + static int add_recv(struct ctx *ctx, int idx) 195 + { 196 + struct io_uring_sqe *sqe; 197 + 198 + if (get_sqe(ctx, &sqe)) 199 + return -1; 200 + 201 + io_uring_prep_recvmsg_multishot(sqe, idx, &ctx->msg, MSG_TRUNC); 202 + sqe->flags |= IOSQE_FIXED_FILE; 203 + 204 + sqe->flags |= IOSQE_BUFFER_SELECT; 205 + sqe->buf_group = 0; 206 + io_uring_sqe_set_data64(sqe, BUFFERS + 1); 207 + return 0; 208 + } 209 + 210 + static void recycle_buffer(struct ctx *ctx, int idx) 211 + { 212 + io_uring_buf_ring_add(ctx->buf_ring, get_buffer(ctx, idx), buffer_size(ctx), idx, 213 + io_uring_buf_ring_mask(BUFFERS), 0); 214 + io_uring_buf_ring_advance(ctx->buf_ring, 1); 215 + } 216 + 217 + static int process_cqe_send(struct ctx *ctx, struct io_uring_cqe *cqe) 218 + { 219 + int idx = cqe->user_data; 220 + 221 + if (cqe->res < 0) 222 + fprintf(stderr, "bad send %s\n", strerror(-cqe->res)); 223 + recycle_buffer(ctx, idx); 224 + return 0; 225 + } 226 + 227 + static int process_cqe_recv(struct ctx *ctx, struct io_uring_cqe *cqe, 228 + int fdidx) 229 + { 230 + int ret, idx; 231 + struct io_uring_recvmsg_out *o; 232 + struct io_uring_sqe *sqe; 233 + 234 + if (!(cqe->flags & IORING_CQE_F_MORE)) { 235 + ret = add_recv(ctx, fdidx); 236 + if (ret) 237 + return ret; 238 + } 239 + 240 + if (cqe->res == -ENOBUFS) 241 + return 0; 242 + 243 + if (!(cqe->flags & IORING_CQE_F_BUFFER) || cqe->res < 0) { 244 + fprintf(stderr, "recv cqe bad res %d\n", cqe->res); 245 + if (cqe->res == -EFAULT || cqe->res == -EINVAL) 246 + fprintf(stderr, 247 + "NB: This requires a kernel version >= 6.0\n"); 248 + return -1; 249 + } 250 + idx = cqe->flags >> 16; 251 + 252 + o = io_uring_recvmsg_validate(get_buffer(ctx, cqe->flags >> 16), 253 + cqe->res, &ctx->msg); 254 + if (!o) { 255 + fprintf(stderr, "bad recvmsg\n"); 256 + return -1; 257 + } 258 + if (o->namelen > ctx->msg.msg_namelen) { 259 + fprintf(stderr, "truncated name\n"); 260 + recycle_buffer(ctx, idx); 261 + return 0; 262 + } 263 + if (o->flags & MSG_TRUNC) { 264 + unsigned int r; 265 + 266 + r = io_uring_recvmsg_payload_length(o, cqe->res, &ctx->msg); 267 + fprintf(stderr, "truncated msg need %u received %u\n", 268 + o->payloadlen, r); 269 + recycle_buffer(ctx, idx); 270 + return 0; 271 + } 272 + 273 + if (ctx->verbose) { 274 + char buff[INET6_ADDRSTRLEN + 1]; 275 + const char *name; 276 + struct sockaddr_in *addr = io_uring_recvmsg_name(o); 277 + 278 + name = inet_ntop(ctx->af, addr, buff, sizeof(buff)); 279 + if (!name) 280 + name = "<INVALID>"; 281 + fprintf(stderr, "received %u bytes %d from %s:%d\n", 282 + io_uring_recvmsg_payload_length(o, cqe->res, &ctx->msg), 283 + o->namelen, name, (int)ntohs(addr->sin_port)); 284 + } 285 + 286 + if (get_sqe(ctx, &sqe)) 287 + return -1; 288 + 289 + ctx->send[idx].iov = (struct iovec) { 290 + .iov_base = io_uring_recvmsg_payload(o, &ctx->msg), 291 + .iov_len = 292 + io_uring_recvmsg_payload_length(o, cqe->res, &ctx->msg) 293 + }; 294 + ctx->send[idx].msg = (struct msghdr) { 295 + .msg_namelen = o->namelen, 296 + .msg_name = io_uring_recvmsg_name(o), 297 + .msg_control = NULL, 298 + .msg_controllen = 0, 299 + .msg_iov = &ctx->send[idx].iov, 300 + .msg_iovlen = 1 301 + }; 302 + 303 + io_uring_prep_sendmsg(sqe, fdidx, &ctx->send[idx].msg, 0); 304 + io_uring_sqe_set_data64(sqe, idx); 305 + sqe->flags |= IOSQE_FIXED_FILE; 306 + 307 + return 0; 308 + } 309 + static int process_cqe(struct ctx *ctx, struct io_uring_cqe *cqe, int fdidx) 310 + { 311 + if (cqe->user_data < BUFFERS) 312 + return process_cqe_send(ctx, cqe); 313 + else 314 + return process_cqe_recv(ctx, cqe, fdidx); 315 + } 316 + 317 + int main(int argc, char *argv[]) 318 + { 319 + struct ctx ctx; 320 + int ret; 321 + int port = -1; 322 + int sockfd; 323 + int opt; 324 + struct io_uring_cqe *cqes[CQES]; 325 + unsigned int count, i; 326 + 327 + memset(&ctx, 0, sizeof(ctx)); 328 + ctx.verbose = false; 329 + ctx.af = AF_INET; 330 + ctx.buf_shift = BUF_SHIFT; 331 + 332 + while ((opt = getopt(argc, argv, "6vp:b:")) != -1) { 333 + switch (opt) { 334 + case '6': 335 + ctx.af = AF_INET6; 336 + break; 337 + case 'p': 338 + port = atoi(optarg); 339 + break; 340 + case 'b': 341 + ctx.buf_shift = atoi(optarg); 342 + break; 343 + case 'v': 344 + ctx.verbose = true; 345 + break; 346 + default: 347 + fprintf(stderr, "Usage: %s [-p port] " 348 + "[-b log2(BufferSize)] [-6] [-v]\n", 349 + argv[0]); 350 + exit(-1); 351 + } 352 + } 353 + 354 + sockfd = setup_sock(ctx.af, port); 355 + if (sockfd < 0) 356 + return 1; 357 + 358 + if (setup_context(&ctx)) { 359 + close(sockfd); 360 + return 1; 361 + } 362 + 363 + ret = io_uring_register_files(&ctx.ring, &sockfd, 1); 364 + if (ret) { 365 + fprintf(stderr, "register files: %s\n", strerror(-ret)); 366 + return -1; 367 + } 368 + 369 + ret = add_recv(&ctx, 0); 370 + if (ret) 371 + return 1; 372 + 373 + while (true) { 374 + ret = io_uring_submit_and_wait(&ctx.ring, 1); 375 + if (ret == -EINTR) 376 + continue; 377 + if (ret < 0) { 378 + fprintf(stderr, "submit and wait failed %d\n", ret); 379 + break; 380 + } 381 + 382 + count = io_uring_peek_batch_cqe(&ctx.ring, &cqes[0], CQES); 383 + for (i = 0; i < count; i++) { 384 + ret = process_cqe(&ctx, cqes[i], 0); 385 + if (ret) 386 + goto cleanup; 387 + } 388 + io_uring_cq_advance(&ctx.ring, count); 389 + } 390 + 391 + cleanup: 392 + cleanup_context(&ctx); 393 + close(sockfd); 394 + return ret; 395 + }
+101
vendor/liburing/examples/poll-bench.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + #include <errno.h> 3 + #include <stdio.h> 4 + #include <unistd.h> 5 + #include <stdlib.h> 6 + #include <string.h> 7 + #include <signal.h> 8 + #include <poll.h> 9 + #include <sys/time.h> 10 + #include <sys/wait.h> 11 + 12 + #include "liburing.h" 13 + 14 + static char buf[4096]; 15 + static unsigned long runtime_ms = 10000; 16 + 17 + static unsigned long gettimeofday_ms(void) 18 + { 19 + struct timeval tv; 20 + 21 + gettimeofday(&tv, NULL); 22 + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); 23 + } 24 + 25 + int main(void) 26 + { 27 + unsigned long tstop; 28 + unsigned long nr_reqs = 0; 29 + struct io_uring_cqe *cqe; 30 + struct io_uring_sqe *sqe; 31 + struct io_uring ring; 32 + int pipe1[2]; 33 + int ret, i, qd = 32; 34 + 35 + if (pipe(pipe1) != 0) { 36 + perror("pipe"); 37 + return 1; 38 + } 39 + 40 + ret = io_uring_queue_init(1024, &ring, IORING_SETUP_SINGLE_ISSUER); 41 + if (ret == -EINVAL) { 42 + fprintf(stderr, "can't single\n"); 43 + ret = io_uring_queue_init(1024, &ring, 0); 44 + } 45 + if (ret) { 46 + fprintf(stderr, "child: ring setup failed: %d\n", ret); 47 + return 1; 48 + } 49 + 50 + ret = io_uring_register_files(&ring, pipe1, 2); 51 + if (ret < 0) { 52 + fprintf(stderr, "io_uring_register_files failed\n"); 53 + return 1; 54 + } 55 + 56 + ret = io_uring_register_ring_fd(&ring); 57 + if (ret < 0) { 58 + fprintf(stderr, "io_uring_register_ring_fd failed\n"); 59 + return 1; 60 + } 61 + 62 + tstop = gettimeofday_ms() + runtime_ms; 63 + do { 64 + for (i = 0; i < qd; i++) { 65 + sqe = io_uring_get_sqe(&ring); 66 + io_uring_prep_poll_add(sqe, 0, POLLIN); 67 + sqe->flags |= IOSQE_FIXED_FILE; 68 + sqe->user_data = 1; 69 + } 70 + 71 + ret = io_uring_submit(&ring); 72 + if (ret != qd) { 73 + fprintf(stderr, "child: sqe submit failed: %d\n", ret); 74 + return 1; 75 + } 76 + 77 + ret = write(pipe1[1], buf, 1); 78 + if (ret != 1) { 79 + fprintf(stderr, "write failed %i\n", errno); 80 + return 1; 81 + } 82 + ret = read(pipe1[0], buf, 1); 83 + if (ret != 1) { 84 + fprintf(stderr, "read failed %i\n", errno); 85 + return 1; 86 + } 87 + 88 + for (i = 0; i < qd; i++) { 89 + ret = io_uring_wait_cqe(&ring, &cqe); 90 + if (ret < 0) { 91 + fprintf(stderr, "child: wait completion %d\n", ret); 92 + break; 93 + } 94 + io_uring_cqe_seen(&ring, cqe); 95 + nr_reqs++; 96 + } 97 + } while (gettimeofday_ms() < tstop); 98 + 99 + fprintf(stderr, "requests/s: %lu\n", nr_reqs * 1000UL / runtime_ms); 100 + return 0; 101 + }
+339
vendor/liburing/examples/send-zerocopy.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* based on linux-kernel/tools/testing/selftests/net/msg_zerocopy.c */ 3 + #include <stdio.h> 4 + #include <stdlib.h> 5 + #include <stdint.h> 6 + #include <assert.h> 7 + #include <errno.h> 8 + #include <error.h> 9 + #include <limits.h> 10 + #include <fcntl.h> 11 + #include <unistd.h> 12 + #include <stdbool.h> 13 + #include <string.h> 14 + 15 + #include <arpa/inet.h> 16 + #include <linux/errqueue.h> 17 + #include <linux/if_packet.h> 18 + #include <linux/ipv6.h> 19 + #include <linux/socket.h> 20 + #include <linux/sockios.h> 21 + #include <net/ethernet.h> 22 + #include <net/if.h> 23 + #include <netinet/ip.h> 24 + #include <netinet/in.h> 25 + #include <netinet/ip6.h> 26 + #include <netinet/tcp.h> 27 + #include <netinet/udp.h> 28 + #include <sys/socket.h> 29 + #include <sys/time.h> 30 + #include <sys/resource.h> 31 + #include <sys/un.h> 32 + #include <sys/ioctl.h> 33 + #include <sys/socket.h> 34 + #include <sys/stat.h> 35 + #include <sys/time.h> 36 + #include <sys/types.h> 37 + #include <sys/wait.h> 38 + 39 + #include "liburing.h" 40 + 41 + #define ZC_TAG 0xfffffffULL 42 + #define MAX_SUBMIT_NR 512 43 + 44 + static bool cfg_reg_ringfd = true; 45 + static bool cfg_fixed_files = 1; 46 + static bool cfg_zc = 1; 47 + static int cfg_nr_reqs = 8; 48 + static bool cfg_fixed_buf = 1; 49 + 50 + static int cfg_family = PF_UNSPEC; 51 + static int cfg_payload_len; 52 + static int cfg_port = 8000; 53 + static int cfg_runtime_ms = 4200; 54 + 55 + static socklen_t cfg_alen; 56 + static struct sockaddr_storage cfg_dst_addr; 57 + 58 + static char payload[IP_MAXPACKET] __attribute__((aligned(4096))); 59 + 60 + static unsigned long gettimeofday_ms(void) 61 + { 62 + struct timeval tv; 63 + 64 + gettimeofday(&tv, NULL); 65 + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); 66 + } 67 + 68 + static void do_setsockopt(int fd, int level, int optname, int val) 69 + { 70 + if (setsockopt(fd, level, optname, &val, sizeof(val))) 71 + error(1, errno, "setsockopt %d.%d: %d", level, optname, val); 72 + } 73 + 74 + static void setup_sockaddr(int domain, const char *str_addr, 75 + struct sockaddr_storage *sockaddr) 76 + { 77 + struct sockaddr_in6 *addr6 = (void *) sockaddr; 78 + struct sockaddr_in *addr4 = (void *) sockaddr; 79 + 80 + switch (domain) { 81 + case PF_INET: 82 + memset(addr4, 0, sizeof(*addr4)); 83 + addr4->sin_family = AF_INET; 84 + addr4->sin_port = htons(cfg_port); 85 + if (str_addr && 86 + inet_pton(AF_INET, str_addr, &(addr4->sin_addr)) != 1) 87 + error(1, 0, "ipv4 parse error: %s", str_addr); 88 + break; 89 + case PF_INET6: 90 + memset(addr6, 0, sizeof(*addr6)); 91 + addr6->sin6_family = AF_INET6; 92 + addr6->sin6_port = htons(cfg_port); 93 + if (str_addr && 94 + inet_pton(AF_INET6, str_addr, &(addr6->sin6_addr)) != 1) 95 + error(1, 0, "ipv6 parse error: %s", str_addr); 96 + break; 97 + default: 98 + error(1, 0, "illegal domain"); 99 + } 100 + } 101 + 102 + static int do_setup_tx(int domain, int type, int protocol) 103 + { 104 + int fd; 105 + 106 + fd = socket(domain, type, protocol); 107 + if (fd == -1) 108 + error(1, errno, "socket t"); 109 + 110 + do_setsockopt(fd, SOL_SOCKET, SO_SNDBUF, 1 << 21); 111 + 112 + if (connect(fd, (void *) &cfg_dst_addr, cfg_alen)) 113 + error(1, errno, "connect"); 114 + return fd; 115 + } 116 + 117 + static inline struct io_uring_cqe *wait_cqe_fast(struct io_uring *ring) 118 + { 119 + struct io_uring_cqe *cqe; 120 + unsigned head; 121 + int ret; 122 + 123 + io_uring_for_each_cqe(ring, head, cqe) 124 + return cqe; 125 + 126 + ret = io_uring_wait_cqe(ring, &cqe); 127 + if (ret) 128 + error(1, ret, "wait cqe"); 129 + return cqe; 130 + } 131 + 132 + static void do_tx(int domain, int type, int protocol) 133 + { 134 + unsigned long packets = 0; 135 + unsigned long bytes = 0; 136 + struct io_uring ring; 137 + struct iovec iov; 138 + uint64_t tstop; 139 + int i, fd, ret; 140 + int compl_cqes = 0; 141 + 142 + fd = do_setup_tx(domain, type, protocol); 143 + 144 + ret = io_uring_queue_init(512, &ring, IORING_SETUP_COOP_TASKRUN); 145 + if (ret) 146 + error(1, ret, "io_uring: queue init"); 147 + 148 + if (cfg_fixed_files) { 149 + ret = io_uring_register_files(&ring, &fd, 1); 150 + if (ret < 0) 151 + error(1, ret, "io_uring: files registration"); 152 + } 153 + if (cfg_reg_ringfd) { 154 + ret = io_uring_register_ring_fd(&ring); 155 + if (ret < 0) 156 + error(1, ret, "io_uring: io_uring_register_ring_fd"); 157 + } 158 + 159 + iov.iov_base = payload; 160 + iov.iov_len = cfg_payload_len; 161 + 162 + ret = io_uring_register_buffers(&ring, &iov, 1); 163 + if (ret) 164 + error(1, ret, "io_uring: buffer registration"); 165 + 166 + tstop = gettimeofday_ms() + cfg_runtime_ms; 167 + do { 168 + struct io_uring_sqe *sqe; 169 + struct io_uring_cqe *cqe; 170 + unsigned buf_idx = 0; 171 + unsigned msg_flags = MSG_WAITALL; 172 + 173 + for (i = 0; i < cfg_nr_reqs; i++) { 174 + sqe = io_uring_get_sqe(&ring); 175 + 176 + if (!cfg_zc) 177 + io_uring_prep_send(sqe, fd, payload, 178 + cfg_payload_len, 0); 179 + else { 180 + io_uring_prep_send_zc(sqe, fd, payload, 181 + cfg_payload_len, msg_flags, 0); 182 + if (cfg_fixed_buf) { 183 + sqe->ioprio |= IORING_RECVSEND_FIXED_BUF; 184 + sqe->buf_index = buf_idx; 185 + } 186 + } 187 + sqe->user_data = 1; 188 + if (cfg_fixed_files) { 189 + sqe->fd = 0; 190 + sqe->flags |= IOSQE_FIXED_FILE; 191 + } 192 + } 193 + 194 + ret = io_uring_submit(&ring); 195 + if (ret != cfg_nr_reqs) 196 + error(1, ret, "submit"); 197 + 198 + for (i = 0; i < cfg_nr_reqs; i++) { 199 + cqe = wait_cqe_fast(&ring); 200 + 201 + if (cqe->flags & IORING_CQE_F_NOTIF) { 202 + if (cqe->flags & IORING_CQE_F_MORE) 203 + error(1, -EINVAL, "F_MORE notif"); 204 + compl_cqes--; 205 + i--; 206 + io_uring_cqe_seen(&ring, cqe); 207 + continue; 208 + } 209 + if (cqe->flags & IORING_CQE_F_MORE) 210 + compl_cqes++; 211 + 212 + if (cqe->res >= 0) { 213 + packets++; 214 + bytes += cqe->res; 215 + } else if (cqe->res == -ECONNREFUSED || cqe->res == -EPIPE || 216 + cqe->res == -ECONNRESET) { 217 + fprintf(stderr, "Connection failure"); 218 + goto out_fail; 219 + } else if (cqe->res != -EAGAIN) { 220 + error(1, cqe->res, "send failed"); 221 + } 222 + io_uring_cqe_seen(&ring, cqe); 223 + } 224 + } while (gettimeofday_ms() < tstop); 225 + 226 + out_fail: 227 + shutdown(fd, SHUT_RDWR); 228 + if (close(fd)) 229 + error(1, errno, "close"); 230 + 231 + fprintf(stderr, "tx=%lu (MB=%lu), tx/s=%lu (MB/s=%lu)\n", 232 + packets, bytes >> 20, 233 + packets / (cfg_runtime_ms / 1000), 234 + (bytes >> 20) / (cfg_runtime_ms / 1000)); 235 + 236 + while (compl_cqes) { 237 + struct io_uring_cqe *cqe = wait_cqe_fast(&ring); 238 + 239 + io_uring_cqe_seen(&ring, cqe); 240 + compl_cqes--; 241 + } 242 + io_uring_queue_exit(&ring); 243 + } 244 + 245 + static void do_test(int domain, int type, int protocol) 246 + { 247 + int i; 248 + 249 + for (i = 0; i < IP_MAXPACKET; i++) 250 + payload[i] = 'a' + (i % 26); 251 + 252 + do_tx(domain, type, protocol); 253 + } 254 + 255 + static void usage(const char *filepath) 256 + { 257 + error(1, 0, "Usage: %s [-n<N>] [-z<val>] [-s<payload size>] " 258 + "(-4|-6) [-t<time s>] -D<dst_ip> udp", filepath); 259 + } 260 + 261 + static void parse_opts(int argc, char **argv) 262 + { 263 + const int max_payload_len = sizeof(payload) - 264 + sizeof(struct ipv6hdr) - 265 + sizeof(struct tcphdr) - 266 + 40 /* max tcp options */; 267 + int c; 268 + char *daddr = NULL; 269 + 270 + if (argc <= 1) 271 + usage(argv[0]); 272 + 273 + cfg_payload_len = max_payload_len; 274 + 275 + while ((c = getopt(argc, argv, "46D:p:s:t:n:z:b:k")) != -1) { 276 + switch (c) { 277 + case '4': 278 + if (cfg_family != PF_UNSPEC) 279 + error(1, 0, "Pass one of -4 or -6"); 280 + cfg_family = PF_INET; 281 + cfg_alen = sizeof(struct sockaddr_in); 282 + break; 283 + case '6': 284 + if (cfg_family != PF_UNSPEC) 285 + error(1, 0, "Pass one of -4 or -6"); 286 + cfg_family = PF_INET6; 287 + cfg_alen = sizeof(struct sockaddr_in6); 288 + break; 289 + case 'D': 290 + daddr = optarg; 291 + break; 292 + case 'p': 293 + cfg_port = strtoul(optarg, NULL, 0); 294 + break; 295 + case 's': 296 + cfg_payload_len = strtoul(optarg, NULL, 0); 297 + break; 298 + case 't': 299 + cfg_runtime_ms = 200 + strtoul(optarg, NULL, 10) * 1000; 300 + break; 301 + case 'n': 302 + cfg_nr_reqs = strtoul(optarg, NULL, 0); 303 + break; 304 + case 'z': 305 + cfg_zc = strtoul(optarg, NULL, 0); 306 + break; 307 + case 'b': 308 + cfg_fixed_buf = strtoul(optarg, NULL, 0); 309 + break; 310 + } 311 + } 312 + 313 + if (cfg_nr_reqs > MAX_SUBMIT_NR) 314 + error(1, 0, "-n: submit batch nr exceeds max (%d)", MAX_SUBMIT_NR); 315 + if (cfg_payload_len > max_payload_len) 316 + error(1, 0, "-s: payload exceeds max (%d)", max_payload_len); 317 + 318 + setup_sockaddr(cfg_family, daddr, &cfg_dst_addr); 319 + 320 + if (optind != argc - 1) 321 + usage(argv[0]); 322 + } 323 + 324 + int main(int argc, char **argv) 325 + { 326 + const char *cfg_test; 327 + 328 + parse_opts(argc, argv); 329 + 330 + cfg_test = argv[argc - 1]; 331 + if (!strcmp(cfg_test, "tcp")) 332 + do_test(cfg_family, SOCK_STREAM, 0); 333 + else if (!strcmp(cfg_test, "udp")) 334 + do_test(cfg_family, SOCK_DGRAM, 0); 335 + else 336 + error(1, 0, "unknown cfg_test %s", cfg_test); 337 + 338 + return 0; 339 + }
+1 -1
vendor/liburing/liburing.spec
··· 1 1 Name: liburing 2 - Version: 2.2 2 + Version: 2.3 3 3 Release: 1%{?dist} 4 4 Summary: Linux-native io_uring I/O access library 5 5 License: (GPLv2 with exceptions and LGPLv2+) or MIT
+29 -3
vendor/liburing/man/io_uring.7
··· 2 2 .\" SPDX-License-Identifier: LGPL-2.0-or-later 3 3 .\" 4 4 5 - .TH IO_URING 7 2020-07-26 "Linux" "Linux Programmer's Manual" 5 + .TH io_uring 7 2020-07-26 "Linux" "Linux Programmer's Manual" 6 6 .SH NAME 7 7 io_uring \- Asynchronous I/O facility 8 8 .SH SYNOPSIS ··· 405 405 is the result from the system call that was performed as part of the 406 406 submission; 407 407 its return value. 408 + 408 409 The 409 410 .I flags 410 - field could carry request-specific metadata in the future, 411 - but is currently unused. 411 + field carries request-specific information. As of the 6.0 kernel, the following 412 + flags are defined: 413 + 414 + .TP 415 + .B IORING_CQE_F_BUFFER 416 + If set, the upper 16 bits of the flags field carries the buffer ID that was 417 + chosen for this request. The request must have been issued with 418 + .B IOSQE_BUFFER_SELECT 419 + set, and used with a request type that supports buffer selection. Additionally, 420 + buffers must have been provided upfront either via the 421 + .B IORING_OP_PROVIDE_BUFFERS 422 + or the 423 + .B IORING_REGISTER_PBUF_RING 424 + methods. 425 + .TP 426 + .B IORING_CQE_F_MORE 427 + If set, the application should expect more completions from the request. This 428 + is used for requests that can generate multiple completions, such as multi-shot 429 + requests, receive, or accept. 430 + .TP 431 + .B IORING_CQE_F_SOCK_NONEMPTY 432 + If set, upon receiving the data from the socket in the current request, the 433 + socket still had data left on completion of this request. 434 + .TP 435 + .B IORING_CQE_F_NOTIF 436 + Set for notification CQEs, as seen with the zero-copy networking send and 437 + receive support. 412 438 .PP 413 439 The general sequence to read completion events off the completion queue is 414 440 as follows:
+2 -2
vendor/liburing/man/io_uring_buf_ring_advance.3
··· 9 9 .nf 10 10 .B #include <liburing.h> 11 11 .PP 12 - .BI "int io_uring_buf_ring_advance(struct io_uring_buf_ring *" br ", 13 - .BI " int " count ");" 12 + .BI "void io_uring_buf_ring_advance(struct io_uring_buf_ring *" br ", 13 + .BI " int " count ");" 14 14 .fi 15 15 .SH DESCRIPTION 16 16 .PP
+3 -3
vendor/liburing/man/io_uring_buf_ring_cq_advance.3
··· 9 9 .nf 10 10 .B #include <liburing.h> 11 11 .PP 12 - .BI "int io_uring_buf_ring_cq_advance(struct io_uring *" ring ", 13 - .BI " struct io_uring_buf_ring *" br ", 14 - .BI " int " count ");" 12 + .BI "void io_uring_buf_ring_cq_advance(struct io_uring *" ring ", 13 + .BI " struct io_uring_buf_ring *" br ", 14 + .BI " int " count ");" 15 15 .fi 16 16 .SH DESCRIPTION 17 17 .PP
+25
vendor/liburing/man/io_uring_cq_has_overflow.3
··· 1 + .\" Copyright (C) 2022 Dylan Yudaken <dylany@fb.com> 2 + .\" 3 + .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 + .\" 5 + .TH io_uring_cq_has_overflow 3 "September 5, 2022" "liburing-2.3" "liburing Manual" 6 + .SH NAME 7 + io_uring_cq_has_overflow \- returns if there are overflow entries waiting to move to the CQ ring 8 + .SH SYNOPSIS 9 + .nf 10 + .B #include <liburing.h> 11 + .PP 12 + .BI "bool io_uring_cq_has_overflow(const struct io_uring *" ring ");" 13 + .fi 14 + .SH DESCRIPTION 15 + .PP 16 + The 17 + .BR io_uring_cq_has_overflow (3) 18 + function informs the application if CQ entries have overflowed and are waiting to be flushed to 19 + the CQ ring. For example using 20 + .BR io_uring_get_events (3) 21 + . 22 + .SH RETURN VALUE 23 + True if there are CQ entries waiting to be flushed to the CQ ring. 24 + .SH SEE ALSO 25 + .BR io_uring_get_events (3)
+2 -2
vendor/liburing/man/io_uring_cq_ready.3
··· 2 2 .\" 3 3 .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 4 .\" 5 - .TH io_uring_cq_ready "January 25, 2022" "liburing-2.1" "liburing Manual" 5 + .TH io_uring_cq_ready 3 "January 25, 2022" "liburing-2.1" "liburing Manual" 6 6 .SH NAME 7 7 io_uring_cq_ready \- returns number of unconsumed ready entries in the CQ ring 8 8 .SH SYNOPSIS ··· 15 15 .PP 16 16 The 17 17 .BR io_uring_cq_ready (3) 18 - function retuns the number of unconsumed entries that are ready belonging to the 18 + function returns the number of unconsumed entries that are ready belonging to the 19 19 .I ring 20 20 param. 21 21
+231 -23
vendor/liburing/man/io_uring_enter.2
··· 3 3 .\" 4 4 .\" SPDX-License-Identifier: LGPL-2.0-or-later 5 5 .\" 6 - .TH IO_URING_ENTER 2 2019-01-22 "Linux" "Linux Programmer's Manual" 6 + .TH io_uring_enter 2 2019-01-22 "Linux" "Linux Programmer's Manual" 7 7 .SH NAME 8 8 io_uring_enter \- initiate and/or complete asynchronous I/O 9 9 .SH SYNOPSIS 10 10 .nf 11 - .BR "#include <linux/io_uring.h>" 11 + .BR "#include <liburing.h>" 12 12 .PP 13 13 .BI "int io_uring_enter(unsigned int " fd ", unsigned int " to_submit , 14 14 .BI " unsigned int " min_complete ", unsigned int " flags , 15 15 .BI " sigset_t *" sig ); 16 + .PP 17 + .BI "int io_uring_enter2(unsigned int " fd ", unsigned int " to_submit , 18 + .BI " unsigned int " min_complete ", unsigned int " flags , 19 + .BI " sigset_t *" sig ", size_t " sz ); 16 20 .fi 17 21 .PP 18 22 .SH DESCRIPTION 19 23 .PP 20 - .BR io_uring_enter () 24 + .BR io_uring_enter (2) 21 25 is used to initiate and complete I/O using the shared submission and 22 26 completion queues setup by a call to 23 27 .BR io_uring_setup (2). 24 28 A single call can both submit new I/O and wait for completions of I/O 25 29 initiated by this call or previous calls to 26 - .BR io_uring_enter (). 30 + .BR io_uring_enter (2). 27 31 28 32 .I fd 29 33 is the file descriptor returned by ··· 34 38 is a bitmask of the following values: 35 39 .TP 36 40 .B IORING_ENTER_GETEVENTS 37 - If this flag is set, then the system call will wait for the specificied 41 + If this flag is set, then the system call will wait for the specified 38 42 number of events in 39 43 .I min_complete 40 44 before returning. This flag can be set along with ··· 61 65 the following: 62 66 63 67 .nf 64 - .BI "int io_uring_enter(unsigned int " fd ", unsigned int " to_submit , 65 - .BI " unsigned int " min_complete ", unsigned int " flags , 66 - .BI " const void *" arg ", size_t " argsz ); 68 + .BI "int io_uring_enter2(unsigned int " fd ", unsigned int " to_submit , 69 + .BI " unsigned int " min_complete ", unsigned int " flags , 70 + .BI " const void *" arg ", size_t " argsz ); 67 71 .fi 68 72 69 - which is behaves just like the original definition by default. However, if 73 + which behaves just like the original definition by default. However, if 70 74 .B IORING_ENTER_EXT_ARG 71 75 is set, then instead of a 72 76 .I sigset_t ··· 137 141 if 138 142 .I sig 139 143 is not NULL, 140 - .BR io_uring_enter () 144 + .BR io_uring_enter (2) 141 145 first replaces the current signal mask by the one pointed to by 142 146 .IR sig , 143 147 then waits for events to become available in the completion queue, and 144 148 then restores the original signal mask. The following 145 - .BR io_uring_enter () 149 + .BR io_uring_enter (2) 146 150 call: 147 151 .PP 148 152 .in +4n ··· 249 253 .BR pwritev2 (2). 250 254 If the file is not seekable, 251 255 .I off 252 - must be set to zero. 256 + must be set to zero or -1. 253 257 254 258 .TP 255 259 .B IORING_OP_READ_FIXED ··· 390 394 .BR sendmsg (2) 391 395 for the general description of the related system call. Available since 5.3. 392 396 397 + This command also supports the following modifiers in 398 + .I ioprio: 399 + 400 + .PP 401 + .in +12 402 + .B IORING_RECVSEND_POLL_FIRST 403 + If set, io_uring will assume the socket is currently full and attempting to 404 + send data will be unsuccessful. For this case, io_uring will arm internal 405 + poll and trigger a send of the data when there is enough space available. 406 + This initial send attempt can be wasteful for the case where the socket 407 + is expected to be full, setting this flag will bypass the initial send 408 + attempt and go straight to arming poll. If poll does indicate that data can 409 + be sent, the operation will proceed. 410 + .EE 411 + .in 412 + .PP 413 + 393 414 .TP 394 415 .B IORING_OP_RECVMSG 395 416 Works just like IORING_OP_SENDMSG, except for 396 417 .BR recvmsg(2) 397 418 instead. See the description of IORING_OP_SENDMSG. Available since 5.3. 398 419 420 + This command also supports the following modifiers in 421 + .I ioprio: 422 + 423 + .PP 424 + .in +12 425 + .B IORING_RECVSEND_POLL_FIRST 426 + If set, io_uring will assume the socket is currently empty and attempting to 427 + receive data will be unsuccessful. For this case, io_uring will arm internal 428 + poll and trigger a receive of the data when the socket has data to be read. 429 + This initial receive attempt can be wasteful for the case where the socket 430 + is expected to be empty, setting this flag will bypass the initial receive 431 + attempt and go straight to arming poll. If poll does indicate that data is 432 + ready to be received, the operation will proceed. 433 + .EE 434 + .in 435 + .PP 436 + 399 437 .TP 400 438 .B IORING_OP_SEND 401 439 Issue the equivalent of a ··· 412 450 .BR send(2) 413 451 for the general description of the related system call. Available since 5.6. 414 452 453 + This command also supports the following modifiers in 454 + .I ioprio: 455 + 456 + .PP 457 + .in +12 458 + .B IORING_RECVSEND_POLL_FIRST 459 + If set, io_uring will assume the socket is currently full and attempting to 460 + send data will be unsuccessful. For this case, io_uring will arm internal 461 + poll and trigger a send of the data when there is enough space available. 462 + This initial send attempt can be wasteful for the case where the socket 463 + is expected to be full, setting this flag will bypass the initial send 464 + attempt and go straight to arming poll. If poll does indicate that data can 465 + be sent, the operation will proceed. 466 + .EE 467 + .in 468 + .PP 469 + 415 470 .TP 416 471 .B IORING_OP_RECV 417 472 Works just like IORING_OP_SEND, except for 418 473 .BR recv(2) 419 474 instead. See the description of IORING_OP_SEND. Available since 5.6. 475 + 476 + This command also supports the following modifiers in 477 + .I ioprio: 478 + 479 + .PP 480 + .in +12 481 + .B IORING_RECVSEND_POLL_FIRST 482 + If set, io_uring will assume the socket is currently empty and attempting to 483 + receive data will be unsuccessful. For this case, io_uring will arm internal 484 + poll and trigger a receive of the data when the socket has data to be read. 485 + This initial receive attempt can be wasteful for the case where the socket 486 + is expected to be empty, setting this flag will bypass the initial receive 487 + attempt and go straight to arming poll. If poll does indicate that data is 488 + ready to be received, the operation will proceed. 489 + .EE 490 + .in 491 + .PP 420 492 421 493 .TP 422 494 .B IORING_OP_TIMEOUT ··· 460 532 461 533 .B IORING_TIMEOUT_REALTIME 462 534 If set, then the clocksource used is 463 - .I CLOCK_BOOTTIME 535 + .I CLOCK_REALTIME 464 536 instead of 465 537 .I CLOCK_MONOTONIC. 466 538 .EE ··· 785 857 .I fd 786 858 does not refer to a seekable file, 787 859 .I off 788 - must be set to zero. If 860 + must be set to zero or -1. If 789 861 .I offs 790 862 is set to 791 863 .B -1 ··· 1052 1124 field matching the 1053 1125 .I off 1054 1126 value being passed in. This request type can be used to either just wake or 1055 - interrupt anyone waiting for completions on the target ring, ot it can be used 1127 + interrupt anyone waiting for completions on the target ring, or it can be used 1056 1128 to pass messages via the two fields. Available since 5.18. 1057 1129 1130 + .TP 1131 + .B IORING_OP_SOCKET 1132 + Issue the equivalent of a 1133 + .BR socket(2) 1134 + system call. 1135 + .I fd 1136 + must contain the communication domain, 1137 + .I off 1138 + must contain the communication type, 1139 + .I len 1140 + must contain the protocol, and 1141 + .I rw_flags 1142 + is currently unused and must be set to zero. See also 1143 + .BR socket(2) 1144 + for the general description of the related system call. Available since 5.19. 1145 + 1146 + If the 1147 + .I file_index 1148 + field is set to a positive number, the file won't be installed into the 1149 + normal file table as usual but will be placed into the fixed file table at index 1150 + .I file_index - 1. 1151 + In this case, instead of returning a file descriptor, the result will contain 1152 + either 0 on success or an error. If the index points to a valid empty slot, the 1153 + installation is guaranteed to not fail. If there is already a file in the slot, 1154 + it will be replaced, similar to 1155 + .B IORING_OP_FILES_UPDATE. 1156 + Please note that only io_uring has access to such files and no other syscall 1157 + can use them. See 1158 + .B IOSQE_FIXED_FILE 1159 + and 1160 + .B IORING_REGISTER_FILES. 1161 + 1162 + Available since 5.19. 1163 + 1164 + .TP 1165 + .B IORING_OP_SEND_ZC 1166 + Issue the zerocopy equivalent of a 1167 + .BR send(2) 1168 + system call. Similar to IORING_OP_SEND, but tries to avoid making intermediate 1169 + copies of data. Zerocopy execution is not guaranteed and may fall back to 1170 + copying. The request may also fail with 1171 + .B -EOPNOTSUPP , 1172 + when a protocol doesn't support zerocopy, in which case users are recommended 1173 + to use copying sends instead. 1174 + 1175 + The 1176 + .I flags 1177 + field of the first 1178 + .I "struct io_uring_cqe" 1179 + may likely contain 1180 + .B IORING_CQE_F_MORE , 1181 + which means that there will be a second completion event / notification for 1182 + the request, with the 1183 + .I user_data 1184 + field set to the same value. The user must not modify the data buffer until the 1185 + notification is posted. The first cqe follows the usual rules and so its 1186 + .I res 1187 + field will contain the number of bytes sent or a negative error code. The 1188 + notification's 1189 + .I res 1190 + field will be set to zero and the 1191 + .I flags 1192 + field will contain 1193 + .B IORING_CQE_F_NOTIF . 1194 + The two step model is needed because the kernel may hold on to buffers for a 1195 + long time, e.g. waiting for a TCP ACK, and having a separate cqe for request 1196 + completions allows userspace to push more data without extra delays. Note, 1197 + notifications are only responsible for controlling the lifetime of the buffers, 1198 + and as such don't mean anything about whether the data has atually been sent 1199 + out or received by the other end. Even errored requests may generate a 1200 + notification, and the user must check for 1201 + .B IORING_CQE_F_MORE 1202 + rather than relying on the result. 1203 + 1204 + .I fd 1205 + must be set to the socket file descriptor, 1206 + .I addr 1207 + must contain a pointer to the buffer, 1208 + .I len 1209 + denotes the length of the buffer to send, and 1210 + .I msg_flags 1211 + holds the flags associated with the system call. When 1212 + .I addr2 1213 + is non-zero it points to the address of the target with 1214 + .I addr_len 1215 + specifying its size, turning the request into a 1216 + .BR sendto(2) 1217 + system call equivalent. 1218 + 1219 + Available since 6.0. 1220 + 1221 + This command also supports the following modifiers in 1222 + .I ioprio: 1223 + 1224 + .PP 1225 + .in +12 1226 + .B IORING_RECVSEND_POLL_FIRST 1227 + If set, io_uring will assume the socket is currently full and attempting to 1228 + send data will be unsuccessful. For this case, io_uring will arm internal 1229 + poll and trigger a send of the data when there is enough space available. 1230 + This initial send attempt can be wasteful for the case where the socket 1231 + is expected to be full, setting this flag will bypass the initial send 1232 + attempt and go straight to arming poll. If poll does indicate that data can 1233 + be sent, the operation will proceed. 1234 + 1235 + .B IORING_RECVSEND_FIXED_BUF 1236 + If set, instructs io_uring to use a pre-mapped buffer. The 1237 + .I buf_index 1238 + field should contain an index into an array of fixed buffers. See 1239 + .BR io_uring_register (2) 1240 + for details on how to setup a context for fixed buffer I/O. 1241 + .EE 1242 + .in 1243 + .PP 1244 + 1058 1245 .PP 1059 1246 The 1060 1247 .I flags ··· 1143 1330 1144 1331 The semantics are chosen to accommodate several use cases. First, when all but 1145 1332 the last request of a normal link without linked timeouts are marked with the 1146 - flag, only one CQE per lin is posted. Additionally, it enables supression of 1333 + flag, only one CQE per lin is posted. Additionally, it enables suppression of 1147 1334 CQEs in cases where the side effects of a successfully executed operation is 1148 1335 enough for userspace to know the state of the system. One such example would 1149 1336 be writing to a synchronisation file. ··· 1282 1469 io_uring-specific opcodes. 1283 1470 .PP 1284 1471 .SH RETURN VALUE 1285 - .BR io_uring_enter () 1472 + .BR io_uring_enter (2) 1286 1473 returns the number of I/Os successfully consumed. This can be zero 1287 1474 if 1288 1475 .I to_submit ··· 1299 1486 rather than through the system call itself. 1300 1487 1301 1488 Errors that occur not on behalf of a submission queue entry are returned via the 1302 - system call directly. On such an error, 1303 - .B -1 1304 - is returned and 1489 + system call directly. On such an error, a negative error code is returned. The 1490 + caller should not rely on 1305 1491 .I errno 1306 - is set appropriately. 1492 + variable. 1307 1493 .PP 1308 1494 .SH ERRORS 1309 1495 These are the errors returned by 1310 - .BR io_uring_enter () 1496 + .BR io_uring_enter (2) 1311 1497 system call. 1312 1498 .TP 1313 1499 .B EAGAIN ··· 1326 1512 .BR io_uring_register (2) 1327 1513 for details on how to enable the ring. 1328 1514 .TP 1515 + .B EBADR 1516 + At least one CQE was dropped even with the 1517 + .B IORING_FEAT_NODROP 1518 + feature, and there are no otherwise available CQEs. This clears the error state 1519 + and so with no other changes the next call to 1520 + .BR io_uring_setup (2) 1521 + will not have this error. This error should be extremely rare and indicates the 1522 + machine is running critically low on memory and. It may be reasonable for the 1523 + application to terminate running unless it is able to safely handle any CQE 1524 + being lost. 1525 + .TP 1329 1526 .B EBUSY 1330 - The application is attempting to overcommit the number of requests it can have 1527 + If the 1528 + .B IORING_FEAT_NODROP 1529 + feature flag is set, then 1530 + .B EBUSY 1531 + will be returned if there were overflow entries, 1532 + .B IORING_ENTER_GETEVENTS 1533 + flag is set and not all of the overflow entries were able to be flushed to 1534 + the CQ ring. 1535 + 1536 + Without 1537 + .B IORING_FEAT_NODROP 1538 + the application is attempting to overcommit the number of requests it can have 1331 1539 pending. The application should wait for some completions and try again. May 1332 1540 occur if the application tries to queue more requests than we have room for in 1333 1541 the CQ ring, or if the application attempts to wait for more events without
+1
vendor/liburing/man/io_uring_enter2.2
··· 1 + io_uring_enter.2
+1 -1
vendor/liburing/man/io_uring_free_probe.3
··· 2 2 .\" 3 3 .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 4 .\" 5 - .TH io_uring_free_probe "January 25, 2022" "liburing-2.1" "liburing Manual" 5 + .TH io_uring_free_probe 3 "January 25, 2022" "liburing-2.1" "liburing Manual" 6 6 .SH NAME 7 7 io_uring_free_probe \- free probe instance 8 8 .SH SYNOPSIS
+33
vendor/liburing/man/io_uring_get_events.3
··· 1 + .\" Copyright (C) 2022 Dylan Yudaken 2 + .\" 3 + .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 + .\" 5 + .TH io_uring_get_events 3 "September 5, 2022" "liburing-2.3" "liburing Manual" 6 + .SH NAME 7 + io_uring_get_events \- Flush outstanding requests to CQE ring 8 + .SH SYNOPSIS 9 + .nf 10 + .B #include <liburing.h> 11 + .PP 12 + .BI "int io_uring_get_events(struct io_uring *" ring ");" 13 + .fi 14 + .SH DESCRIPTION 15 + .PP 16 + The 17 + .BR io_uring_get_events (3) 18 + function runs outstanding work and flushes completion events to the CQE ring. 19 + 20 + There can be events needing to be flushed if the ring was full and had overflowed. 21 + Alternatively if the ring was setup with the 22 + .BR IORING_SETUP_DEFER_TASKRUN 23 + flag then this will process outstanding tasks, possibly resulting in more CQEs. 24 + 25 + .SH RETURN VALUE 26 + On success 27 + .BR io_uring_get_events (3) 28 + returns 0. On failure it returns 29 + .BR -errno . 30 + .SH SEE ALSO 31 + .BR io_uring_get_sqe (3), 32 + .BR io_uring_submit_and_get_events (3), 33 + .BR io_uring_cq_has_overflow (3)
+1 -1
vendor/liburing/man/io_uring_get_probe.3
··· 2 2 .\" 3 3 .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 4 .\" 5 - .TH io_uring_get_probe "January 25, 2022" "liburing-2.1" "liburing Manual" 5 + .TH io_uring_get_probe 3 "January 25, 2022" "liburing-2.1" "liburing Manual" 6 6 .SH NAME 7 7 io_uring_get_probe \- get probe instance 8 8 .SH SYNOPSIS
+17 -1
vendor/liburing/man/io_uring_get_sqe.3
··· 32 32 and submitted via 33 33 .BR io_uring_submit (3). 34 34 35 + Note that neither 36 + .BR io_uring_get_sqe 37 + nor the prep functions set (or clear) the 38 + .B user_data 39 + field of the SQE. If the caller expects 40 + .BR io_uring_cqe_get_data (3) 41 + or 42 + .BR io_uring_cqe_get_data64 (3) 43 + to return valid data when reaping IO completions, either 44 + .BR io_uring_sqe_set_data (3) 45 + or 46 + .BR io_uring_sqe_set_data64 (3) 47 + .B MUST 48 + have been called before submitting the request. 49 + 35 50 .SH RETURN VALUE 36 51 .BR io_uring_get_sqe (3) 37 52 returns a pointer to the next submission queue event on success and NULL on 38 53 failure. If NULL is returned, the SQ ring is currently full and entries must 39 54 be submitted for processing before new ones can get allocated. 40 55 .SH SEE ALSO 41 - .BR io_uring_submit (3) 56 + .BR io_uring_submit (3), 57 + .BR io_uring_sqe_set_data (3)
+1 -1
vendor/liburing/man/io_uring_opcode_supported.3
··· 2 2 .\" 3 3 .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 4 .\" 5 - .TH io_uring_opcode_supported "January 25, 2022" "liburing-2.1" "liburing Manual" 5 + .TH io_uring_opcode_supported 3 "January 25, 2022" "liburing-2.1" "liburing Manual" 6 6 .SH NAME 7 7 io_uring_opcode_supported \- is op code supported? 8 8 .SH SYNOPSIS
+89 -51
vendor/liburing/man/io_uring_prep_accept.3
··· 39 39 .PP 40 40 The 41 41 .BR io_uring_prep_accept (3) 42 - function prepares an accept request. The submission queue entry 42 + function and its three variants prepare an accept request similar to 43 + .BR accept4 (2). 44 + The submission queue entry 43 45 .I sqe 44 46 is setup to use the file descriptor 45 47 .I sockfd ··· 50 52 and using modifier flags in 51 53 .IR flags . 52 54 53 - For a direct descriptor accept request, the offset is specified by the 54 - .I file_index 55 - argument. Direct descriptors are io_uring private file descriptors. They 55 + The three variants allow combining the direct file table and multishot features. 56 + 57 + Direct descriptors are io_uring private file descriptors. They 56 58 avoid some of the overhead associated with thread shared file tables and 57 - can be used in any io_uring request that takes a file descriptor. To do so, 59 + can be used in any io_uring request that takes a file descriptor. 60 + The two direct variants here create such direct descriptors. 61 + Subsequent to their creation, they can be used by setting 58 62 .B IOSQE_FIXED_FILE 59 - must be set in the SQE 63 + in the SQE 60 64 .I flags 61 - member, and the SQE 65 + member, and setting the SQE 62 66 .I fd 63 - field should use the direct descriptor value rather than the regular file 67 + field to the direct descriptor value rather than the regular file 64 68 descriptor. Direct descriptors are managed like registered files. 65 69 66 - If the direct variant is used, the application must first have registered 67 - a file table using 70 + To use an accept direct variant, the application must first have registered 71 + a file table of a desired size using 68 72 .BR io_uring_register_files (3) 69 - of the appropriate size. Once registered, a direct accept request may use any 70 - entry in that table, as long as it is within the size of the registered table. 71 - If a specified entry already contains a file, the file will first be removed 72 - from the table and closed. It's consistent with the behavior of updating an 73 + or 74 + .BR io_uring_register_files_sparse (3). 75 + Once registered, 76 + .BR io_uring_prep_accept_direct (3) 77 + allows an entry in that table to be specifically selected through the 78 + .I file_index 79 + argument. 80 + If the specified entry already contains a file, the file will first be removed 81 + from the table and closed, consistent with the behavior of updating an 73 82 existing file with 74 83 .BR io_uring_register_files_update (3). 84 + .I file_index 85 + can also be set to 86 + .B IORING_FILE_INDEX_ALLOC 87 + for this variant and 88 + an unused table index will be dynamically chosen and returned. 89 + Likewise, 90 + .B io_uring_prep_multishot_accept_direct 91 + will have an unused table index dynamically chosen and returned for each connection accepted. 92 + If both forms of direct selection will be employed, specific and dynamic, see 93 + .BR io_uring_register_file_alloc_range (3) 94 + for setting up the table so dynamically chosen entries are made against 95 + a different range than that targetted by specific requests. 96 + 75 97 Note that old kernels don't check the SQE 76 98 .I file_index 77 - field, which is not a problem for liburing helpers, but users of the raw 78 - io_uring interface need to zero SQEs to avoid unexpected behavior. This also 79 - means that applications should check for availability of 80 - .B IORING_OP_ACCEPT_DIRECT 81 - before using it, they cannot rely on a 99 + field meaning 100 + applications cannot rely on a 82 101 .B -EINVAL 83 102 CQE 84 103 .I res 85 - return. 104 + being returned when the kernel is too old because older kernels 105 + may not recognize they are being asked to use a direct table slot. 86 106 87 - For a direct descriptor accept request, the 88 - .I file_index 89 - argument can be set to 90 - .BR IORING_FILE_INDEX_ALLOC , 91 - In this case a free entry in io_uring file table will 92 - be used automatically and the file index will be returned as CQE 93 - .IR res . 107 + When a direct descriptor accept request asks for a table slot to be 108 + dynamically chosen but there are no free entries, 94 109 .B -ENFILE 95 - is otherwise returned if there is no free entries in the io_uring file table. 110 + is returned as the CQE 111 + .IR res . 96 112 97 - The multishot version accept and accept_direct allow an application to issue 113 + The multishot variants allow an application to issue 98 114 a single accept request, which will repeatedly trigger a CQE when a connection 99 115 request comes in. Like other multishot type requests, the application should 100 116 look at the CQE ··· 102 118 and see if 103 119 .B IORING_CQE_F_MORE 104 120 is set on completion as an indication of whether or not the accept request 105 - will generate further CQEs. The multishot variants are available since 5.19. 121 + will generate further CQEs. Note that for the multishot variants, setting 122 + .B addr 123 + and 124 + .B addrlen 125 + may not make a lot of sense, as the same value would be used for every 126 + accepted connection. This means that the data written to 127 + .B addr 128 + may be overwritten by a new connection before the application has had time 129 + to process a past connection. If the application knows that a new connection 130 + cannot come in before a previous one has been processed, it may be used as 131 + expected. The multishot variants are available since 5.19. 106 132 107 - For multishot with direct descriptors, 108 - .B IORING_FILE_INDEX_ALLOC 109 - must be used as the file descriptor. This tells io_uring to allocate a free 110 - direct descriptor from our table, rather than the application passing one in. 111 - Failure to do so will result in the accept request being terminated with 112 - .BR -EINVAL . 113 - The allocated descriptor will be returned in the CQE 114 - .I res 115 - field, like a non-direct accept request. 116 - 117 - These functions prepare an async 133 + See the man page 118 134 .BR accept4 (2) 119 - request. See that man page for details. 135 + for details of the accept function itself. 120 136 121 137 .SH RETURN VALUE 122 138 None 123 139 .SH ERRORS 124 140 The CQE 125 141 .I res 126 - field will contain the result of the operation. For singleshot accept, the 127 - non-direct accept returns the installed file descriptor as its value, the 128 - direct accept returns 142 + field will contain the result of the operation. 143 + 144 + .BR io_uring_prep_accept (3) 145 + generates the installed file descriptor as its result. 146 + 147 + .BR io_uring_prep_accept_direct (3) 148 + and 149 + .I file_index 150 + set to a specific direct descriptor 151 + generates 129 152 .B 0 130 - on success. The caller must know which direct descriptor was picked for this 131 - request. For multishot accept, the non-direct accept returns the installed 132 - file descriptor as its value, the direct accept returns the file index used on 133 - success. See the related man page for details on possible values for the 134 - non-direct accept. Note that where synchronous system calls will return 153 + on success. 154 + The caller must remember which direct descriptor was picked for this request. 155 + 156 + .BR io_uring_prep_accept_direct (3) 157 + and 158 + .I file_index 159 + set to 160 + .B IORING_FILE_INDEX_ALLOC 161 + generates the dynamically chosen direct descriptor. 162 + 163 + .BR io_uring_prep_multishot_accept (3) 164 + generates the installed file descriptor in each result. 165 + 166 + .BR io_uring_prep_multishot_accept_direct (3), 167 + generates the dynamically chosen direct descriptor in each result. 168 + 169 + Note that where synchronous system calls will return 135 170 .B -1 136 171 on failure and set 137 172 .I errno 138 173 to the actual error value, io_uring never uses 139 174 .IR errno . 140 - Instead it returns the negated 175 + Instead it generates the negated 141 176 .I errno 142 177 directly in the CQE 143 178 .I res ··· 155 190 .SH SEE ALSO 156 191 .BR io_uring_get_sqe (3), 157 192 .BR io_uring_submit (3), 193 + .BR io_uring_register_files (3), 194 + .BR io_uring_register_files_sparse (3), 195 + .BR io_uring_register_file_alloc_range (3), 158 196 .BR io_uring_register (2), 159 197 .BR accept4 (2)
+28
vendor/liburing/man/io_uring_prep_nop.3
··· 1 + .\" Copyright (C) 2022 Samuel Williams 2 + .\" 3 + .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 + .\" 5 + .TH io_uring_prep_nop 3 "October 20, 2022" "liburing-2.2" "liburing Manual" 6 + .SH NAME 7 + io_uring_prep_nop \- prepare a nop request 8 + .SH SYNOPSIS 9 + .nf 10 + .B #include <liburing.h> 11 + .PP 12 + .BI "void io_uring_prep_nop(struct io_uring_sqe *" sqe ");" 13 + .fi 14 + .SH DESCRIPTION 15 + .PP 16 + The 17 + .BR io_uring_prep_nop (3) 18 + function prepares nop (no operation) request. The submission queue entry 19 + .I sqe 20 + does not require any additional setup. 21 + 22 + .SH RETURN VALUE 23 + None 24 + .SH ERRORS 25 + None 26 + .SH SEE ALSO 27 + .BR io_uring_get_sqe (3), 28 + .BR io_uring_submit (3),
+1 -1
vendor/liburing/man/io_uring_prep_read.3
··· 40 40 to the file is serialized. It is not encouraged to use this feature, if it's 41 41 possible to provide the desired IO offset from the application or library. 42 42 43 - On files that are not capable of seeking, the offset is ignored. 43 + On files that are not capable of seeking, the offset must be 0 or -1. 44 44 45 45 After the read has been prepared it can be submitted with one of the submit 46 46 functions.
+1 -1
vendor/liburing/man/io_uring_prep_read_fixed.3
··· 42 42 .I buf 43 43 and 44 44 .I nbytes 45 - arguments must fall within a region specificed by 45 + arguments must fall within a region specified by 46 46 .I buf_index 47 47 in the previously registered buffer. The buffer need not be aligned with 48 48 the start of the registered buffer.
+1 -1
vendor/liburing/man/io_uring_prep_readv.3
··· 41 41 to the file is serialized. It is not encouraged to use this feature, if it's 42 42 possible to provide the desired IO offset from the application or library. 43 43 44 - On files that are not capable of seeking, the offset is ignored. 44 + On files that are not capable of seeking, the offset must be 0 or -1. 45 45 46 46 After the write has been prepared it can be submitted with one of the submit 47 47 functions.
+1 -1
vendor/liburing/man/io_uring_prep_readv2.3
··· 67 67 to the file is serialized. It is not encouraged to use this feature, if it's 68 68 possible to provide the desired IO offset from the application or library. 69 69 70 - On files that are not capable of seeking, the offset is ignored. 70 + On files that are not capable of seeking, the offset must be 0 or -1. 71 71 72 72 After the write has been prepared, it can be submitted with one of the submit 73 73 functions.
+23 -1
vendor/liburing/man/io_uring_prep_recv.3
··· 14 14 .BI " void *" buf "," 15 15 .BI " size_t " len "," 16 16 .BI " int " flags ");" 17 + .PP 18 + .BI "void io_uring_prep_recv_multishot(struct io_uring_sqe *" sqe "," 19 + .BI " int " sockfd "," 20 + .BI " void *" buf "," 21 + .BI " size_t " len "," 22 + .BI " int " flags ");" 17 23 .fi 18 24 .SH DESCRIPTION 19 25 .PP ··· 36 42 request. See that man page for details on the arguments specified to this 37 43 prep helper. 38 44 45 + The multishot version allows the application to issue a single receive request, 46 + which repeatedly posts a CQE when data is available. It requires length to be 0 47 + , the 48 + .B IOSQE_BUFFER_SELECT 49 + flag to be set and no 50 + .B MSG_WAITALL 51 + flag to be set. 52 + Therefore each CQE will take a buffer out of a provided buffer pool for receiving. 53 + The application should check the flags of each CQE, regardless of it's result. 54 + If a posted CQE does not have the 55 + .B IORING_CQE_F_MORE 56 + flag set then the multishot receive will be done and the application should issue a 57 + new request. 58 + Multishot variants are available since kernel 6.0. 59 + 60 + 39 61 After calling this function, additional io_uring internal modifier flags 40 62 may be set in the SQE 41 - .I off 63 + .I ioprio 42 64 field. The following flags are supported: 43 65 .TP 44 66 .B IORING_RECVSEND_POLL_FIRST
+1
vendor/liburing/man/io_uring_prep_recv_multishot.3
··· 1 + io_uring_prep_recv.3
+31 -1
vendor/liburing/man/io_uring_prep_recvmsg.3
··· 15 15 .BI " int " fd "," 16 16 .BI " struct msghdr *" msg "," 17 17 .BI " unsigned " flags ");" 18 + .PP 19 + .BI "void io_uring_prep_recvmsg_multishot(struct io_uring_sqe *" sqe "," 20 + .BI " int " fd "," 21 + .BI " struct msghdr *" msg "," 22 + .BI " unsigned " flags ");" 18 23 .fi 19 24 .SH DESCRIPTION 20 25 .PP ··· 37 42 request. See that man page for details on the arguments specified to this 38 43 prep helper. 39 44 45 + The multishot version allows the application to issue a single receive request, 46 + which repeatedly posts a CQE when data is available. It requires the 47 + .B IOSQE_BUFFER_SELECT 48 + flag to be set and no 49 + .B MSG_WAITALL 50 + flag to be set. 51 + Therefore each CQE will take a buffer out of a provided buffer pool for receiving. 52 + The application should check the flags of each CQE, regardless of it's result. 53 + If a posted CQE does not have the 54 + .B IORING_CQE_F_MORE 55 + flag set then the multishot receive will be done and the application should issue a 56 + new request. 57 + 58 + Unlike 59 + .BR recvmsg (2) 60 + , multishot recvmsg will prepend a 61 + .I struct io_uring_recvmsg_out 62 + which describes the layout of the rest of the buffer in combination with the initial 63 + .I struct msghdr 64 + submitted with the request. See 65 + .B io_uring_recvmsg_out (3) 66 + for more information on accessing the data. 67 + 68 + Multishot variants are available since kernel 6.0. 69 + 40 70 After calling this function, additional io_uring internal modifier flags 41 71 may be set in the SQE 42 - .I off 72 + .I ioprio 43 73 field. The following flags are supported: 44 74 .TP 45 75 .B IORING_RECVSEND_POLL_FIRST
+1
vendor/liburing/man/io_uring_prep_recvmsg_multishot.3
··· 1 + io_uring_prep_recvmsg.3
+2 -2
vendor/liburing/man/io_uring_prep_renameat.3
··· 16 16 .BI " const char *" oldpath "," 17 17 .BI " int " newdirfd "," 18 18 .BI " const char *" newpath "," 19 - .BI " int " flags ");" 19 + .BI " unsigned int " flags ");" 20 20 .PP 21 21 .BI "void io_uring_prep_rename(struct io_uring_sqe *" sqe "," 22 22 .BI " const char *" oldpath "," 23 23 .BI " const char *" newpath "," 24 - .BI " int " flags ");" 24 + .BI " unsigned int " flags ");" 25 25 .fi 26 26 .SH DESCRIPTION 27 27 .PP
+2 -2
vendor/liburing/man/io_uring_prep_send.3
··· 26 26 to start sending the data from 27 27 .I buf 28 28 of size 29 - .I size 30 - and with modifier flags 29 + .I len 30 + bytes and with modifier flags 31 31 .IR flags . 32 32 33 33 This function prepares an async
+64
vendor/liburing/man/io_uring_prep_send_zc.3
··· 1 + .\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk> 2 + .\" 3 + .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 + .\" 5 + .TH io_uring_prep_send_zc 3 "September 6, 2022" "liburing-2.3" "liburing Manual" 6 + .SH NAME 7 + io_uring_prep_send_zc \- prepare a zerocopy send request 8 + .SH SYNOPSIS 9 + .nf 10 + .B #include <liburing.h> 11 + .PP 12 + .BI "void io_uring_prep_send_zc(struct io_uring_sqe *" sqe "," 13 + .BI " int " sockfd "," 14 + .BI " const void *" buf "," 15 + .BI " size_t " len "," 16 + .BI " int " flags "," 17 + .BI " int " zc_flags ");" 18 + .fi 19 + .SH DESCRIPTION 20 + .PP 21 + The 22 + .BR io_uring_prep_send_zc (3) 23 + function prepares a zerocopy send request. The submission queue entry 24 + .I sqe 25 + is setup to use the file descriptor 26 + .I sockfd 27 + to start sending the data from 28 + .I buf 29 + of size 30 + .I len 31 + bytes with send modifier flags 32 + .IR flags 33 + and zerocopy modifier flags 34 + .IR zc_flags . 35 + 36 + This function prepares an async zerocopy 37 + .BR send (2) 38 + request. See that man page for details. For details on the zerocopy nature 39 + of it, see 40 + .BR io_uring_enter (2) . 41 + 42 + .SH RETURN VALUE 43 + None 44 + .SH ERRORS 45 + The CQE 46 + .I res 47 + field will contain the result of the operation. See the related man page for 48 + details on possible values. Note that where synchronous system calls will return 49 + .B -1 50 + on failure and set 51 + .I errno 52 + to the actual error value, io_uring never uses 53 + .IR errno . 54 + Instead it returns the negated 55 + .I errno 56 + directly in the CQE 57 + .I res 58 + field. 59 + .SH SEE ALSO 60 + .BR io_uring_get_sqe (3), 61 + .BR io_uring_submit (3), 62 + .BR io_uring_prep_send (3), 63 + .BR io_uring_enter (2), 64 + .BR send (2)
+25 -4
vendor/liburing/man/io_uring_prep_socket.3
··· 22 22 .BI " int " protocol "," 23 23 .BI " unsigned int " file_index "," 24 24 .BI " unsigned int " flags ");" 25 + .PP 26 + .BI "void io_uring_prep_socket_direct_alloc(struct io_uring_sqe *" sqe "," 27 + .BI " int " domain "," 28 + .BI " int " type "," 29 + .BI " int " protocol "," 30 + .BI " unsigned int " flags ");" 25 31 .fi 26 32 .SH DESCRIPTION 27 33 .PP ··· 41 47 42 48 The 43 49 .BR io_uring_prep_socket_direct (3) 44 - works just like 50 + helper works just like 45 51 .BR io_uring_prep_socket (3), 46 52 except it maps the socket to a direct descriptor rather than return a normal 47 53 file descriptor. The 48 54 .I file_index 49 - argument should be set to the slot that should be used for this socket, or 55 + argument should be set to the slot that should be used for this socket. 56 + 57 + The 58 + .BR io_uring_prep_socket_direct_alloc (3) 59 + helper works just like 60 + .BR io_uring_prep_socket_alloc (3), 61 + except it allocates a new direct descriptor rather than pass a free slot in. It 62 + is equivalent to using 63 + .BR io_uring_prep_socket_direct (3) 64 + with 50 65 .B IORING_FILE_INDEX_ALLOC 51 - if io_uring should allocate a free one. 66 + as the 67 + .I 68 + file_index . 69 + Upon completion, the 70 + .I res 71 + field of the CQE will return the direct slot that was allocated for the 72 + socket. 52 73 53 - If the direct variant is used, the application must first have registered 74 + If the direct variants are used, the application must first have registered 54 75 a file table using 55 76 .BR io_uring_register_files (3) 56 77 of the appropriate size. Once registered, a direct socket request may use any
+1
vendor/liburing/man/io_uring_prep_socket_direct_alloc.3
··· 1 + io_uring_prep_socket.3
+1 -1
vendor/liburing/man/io_uring_prep_write.3
··· 40 40 to the file is serialized. It is not encouraged to use this feature if it's 41 41 possible to provide the desired IO offset from the application or library. 42 42 43 - On files that are not capable of seeking, the offset is ignored. 43 + On files that are not capable of seeking, the offset must be 0 or -1. 44 44 45 45 After the write has been prepared, it can be submitted with one of the submit 46 46 functions.
+1 -1
vendor/liburing/man/io_uring_prep_write_fixed.3
··· 42 42 .I buf 43 43 and 44 44 .I nbytes 45 - arguments must fall within a region specificed by 45 + arguments must fall within a region specified by 46 46 .I buf_index 47 47 in the previously registered buffer. The buffer need not be aligned with 48 48 the start of the registered buffer.
+1 -1
vendor/liburing/man/io_uring_prep_writev.3
··· 41 41 to the file is serialized. It is not encouraged to use this feature if it's 42 42 possible to provide the desired IO offset from the application or library. 43 43 44 - On files that are not capable of seeking, the offset is ignored. 44 + On files that are not capable of seeking, the offset must be 0 or -1. 45 45 46 46 After the write has been prepared it can be submitted with one of the submit 47 47 functions.
+1 -1
vendor/liburing/man/io_uring_prep_writev2.3
··· 67 67 to the file is serialized. It is not encouraged to use this feature if it's 68 68 possible to provide the desired IO offset from the application or library. 69 69 70 - On files that are not capable of seeking, the offset is ignored. 70 + On files that are not capable of seeking, the offset must be 0 or -1. 71 71 72 72 After the write has been prepared, it can be submitted with one of the submit 73 73 functions.
+1
vendor/liburing/man/io_uring_recvmsg_cmsg_firsthdr.3
··· 1 + io_uring_recvmsg_out.3
+1
vendor/liburing/man/io_uring_recvmsg_cmsg_nexthdr.3
··· 1 + io_uring_recvmsg_out.3
+1
vendor/liburing/man/io_uring_recvmsg_name.3
··· 1 + io_uring_recvmsg_out.3
+78
vendor/liburing/man/io_uring_recvmsg_out.3
··· 1 + .\" Copyright (C), 2022 Dylan Yudaken <dylany@fb.com> 2 + .\" 3 + .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 + .\" 5 + .TH io_uring_recvmsg_out 3 "Julyu 26, 2022" "liburing-2.2" "liburing Manual" 6 + .SH NAME 7 + io_uring_recvmsg_out - access data from multishot recvmsg 8 + .SH SYNOPSIS 9 + .nf 10 + .B #include <liburing.h> 11 + .PP 12 + .BI "struct io_uring_recvmsg_out *io_uring_recvmsg_validate(void *" buf "," 13 + .BI " int " buf_len "," 14 + .BI " struct msghdr *" msgh ");" 15 + .PP 16 + .BI "void *io_uring_recvmsg_name(struct io_uring_recvmsg_out *" o ");" 17 + .PP 18 + .BI "struct cmsghdr *io_uring_recvmsg_cmsg_firsthdr(struct io_uring_recvmsg_out * " o "," 19 + .BI " struct msghdr *" msgh ");" 20 + .BI "struct cmsghdr *io_uring_recvmsg_cmsg_nexthdr(struct io_uring_recvmsg_out * " o "," 21 + .BI " struct msghdr *" msgh "," 22 + .BI " struct cmsghdr *" cmsg ");" 23 + .PP 24 + .BI "void *io_uring_recvmsg_payload(struct io_uring_recvmsg_out * " o "," 25 + .BI " struct msghdr *" msgh ");" 26 + .BI "unsigned int io_uring_recvmsg_payload_length(struct io_uring_recvmsg_out *" o "," 27 + .BI " int " buf_len "," 28 + .BI " struct msghdr *" msgh ");" 29 + .PP 30 + .fi 31 + 32 + .SH DESCRIPTION 33 + 34 + These functions are used to access data in the payload delivered by 35 + .BR io_uring_prep_recv_multishot (3) 36 + . 37 + .PP 38 + .BR io_uring_recvmsg_validate (3) 39 + will validate a buffer delivered by 40 + .BR io_uring_prep_recv_multishot (3) 41 + and extract the 42 + .I io_uring_recvmsg_out 43 + if it is valid, returning a pointer to it or else NULL. 44 + .PP 45 + The structure is defined as follows: 46 + .PP 47 + .in +4n 48 + .EX 49 + 50 + struct io_uring_recvmsg_out { 51 + __u32 namelen; /* Name byte count as would have been populated 52 + * by recvmsg(2) */ 53 + __u32 controllen; /* Control byte count */ 54 + __u32 payloadlen; /* Payload byte count as would have been returned 55 + * by recvmsg(2) */ 56 + __u32 flags; /* Flags result as would have been populated 57 + * by recvmsg(2) */ 58 + }; 59 + 60 + .IP * 3 61 + .BR io_uring_recvmsg_name (3) 62 + returns a pointer to the name in the buffer. 63 + .IP * 64 + .BR io_uring_recvmsg_cmsg_firsthdr (3) 65 + returns a pointer to the first cmsg in the buffer, or NULL. 66 + .IP * 67 + .BR io_uring_recvmsg_cmsg_nexthdr (3) 68 + returns a pointer to the next cmsg in the buffer, or NULL. 69 + .IP * 70 + .BR io_uring_recvmsg_payload (3) 71 + returns a pointer to the payload in the buffer. 72 + .IP * 73 + .BR io_uring_recvmsg_payload_length (3) 74 + Calculates the usable payload length in bytes. 75 + 76 + 77 + .SH "SEE ALSO" 78 + .BR io_uring_prep_recv_multishot (3)
+1
vendor/liburing/man/io_uring_recvmsg_payload.3
··· 1 + io_uring_recvmsg_out.3
+1
vendor/liburing/man/io_uring_recvmsg_payload_length.3
··· 1 + io_uring_recvmsg_out.3
+1
vendor/liburing/man/io_uring_recvmsg_validate.3
··· 1 + io_uring_recvmsg_out.3
+148 -12
vendor/liburing/man/io_uring_register.2
··· 3 3 .\" 4 4 .\" SPDX-License-Identifier: LGPL-2.0-or-later 5 5 .\" 6 - .TH IO_URING_REGISTER 2 2019-01-17 "Linux" "Linux Programmer's Manual" 6 + .TH io_uring_register 2 2019-01-17 "Linux" "Linux Programmer's Manual" 7 7 .SH NAME 8 8 io_uring_register \- register files or user buffers for asynchronous I/O 9 9 .SH SYNOPSIS 10 10 .nf 11 - .BR "#include <linux/io_uring.h>" 11 + .BR "#include <liburing.h>" 12 12 .PP 13 13 .BI "int io_uring_register(unsigned int " fd ", unsigned int " opcode , 14 14 .BI " void *" arg ", unsigned int " nr_args ); ··· 18 18 .PP 19 19 20 20 The 21 - .BR io_uring_register () 21 + .BR io_uring_register (2) 22 22 system call registers resources (e.g. user buffers, files, eventfd, 23 23 personality, restrictions) for use in an 24 24 .BR io_uring (7) ··· 85 85 An application can increase or decrease the size or number of 86 86 registered buffers by first unregistering the existing buffers, and 87 87 then issuing a new call to 88 - .BR io_uring_register () 88 + .BR io_uring_register (2) 89 89 with the new buffers. 90 90 91 91 Note that before 5.13 registering buffers would wait for the ring to idle. ··· 428 428 entries. 429 429 430 430 With an entry it is possible to allow an 431 - .BR io_uring_register () 431 + .BR io_uring_register (2) 432 432 .I opcode, 433 433 or specify which 434 434 .I opcode ··· 440 440 to be specified (these flags must be set on each submission queue entry). 441 441 442 442 All the restrictions must be submitted with a single 443 - .BR io_uring_register () 443 + .BR io_uring_register (2) 444 444 call and they are handled as an allowlist (opcodes and flags not registered, 445 445 are not allowed). 446 446 ··· 546 546 is used rather than a real file descriptor. 547 547 548 548 Each thread or process using a ring must register the file descriptor directly 549 - by issuing this request.o 549 + by issuing this request. 550 550 551 551 The maximum number of supported registered ring descriptors is currently 552 552 limited to ··· 579 579 580 580 Available since 5.18. 581 581 582 + .TP 583 + .B IORING_REGISTER_PBUF_RING 584 + Registers a shared buffer ring to be used with provided buffers. This is a 585 + newer alternative to using 586 + .B IORING_OP_PROVIDE_BUFFERS 587 + which is more efficient, to be used with request types that support the 588 + .B IOSQE_BUFFER_SELECT 589 + flag. 590 + 591 + The 592 + .I arg 593 + argument must be filled in with the appropriate information. It looks as 594 + follows: 595 + .PP 596 + .in +12n 597 + .EX 598 + struct io_uring_buf_reg { 599 + __u64 ring_addr; 600 + __u32 ring_entries; 601 + __u16 bgid; 602 + __u16 pad; 603 + __u64 resv[3]; 604 + }; 605 + .EE 606 + .in 607 + .PP 608 + .in +8n 609 + The 610 + .I ring_addr 611 + field must contain the address to the memory allocated to fit this ring. 612 + The memory must be page aligned and hence allocated appropriately using eg 613 + .BR posix_memalign (3) 614 + or similar. The size of the ring is the product of 615 + .I ring_entries 616 + and the size of 617 + .IR "struct io_uring_buf" . 618 + .I ring_entries 619 + is the desired size of the ring, and must be a power-of-2 in size. The maximum 620 + size allowed is 2^15 (32768). 621 + .I bgid 622 + is the buffer group ID associated with this ring. SQEs that select a buffer 623 + has a buffer group associated with them in their 624 + .I buf_group 625 + field, and the associated CQE will have 626 + .B IORING_CQE_F_BUFFER 627 + set in their 628 + .I flags 629 + member, which will also contain the specific ID of the buffer selected. The rest 630 + of the fields are reserved and must be cleared to zero. 631 + 632 + The 633 + .I flags 634 + argument is currently unused and must be set to zero. 635 + 636 + .i nr_args 637 + must be set to 1. 638 + 639 + Also see 640 + .BR io_uring_register_buf_ring (3) 641 + for more details. Available since 5.19. 642 + 643 + .TP 644 + .B IORING_UNREGISTER_PBUF_RING 645 + Unregister a previously registered provided buffer ring. 646 + .I arg 647 + must be set to the address of a struct io_uring_buf_reg, with just the 648 + .I bgid 649 + field set to the buffer group ID of the previously registered provided buffer 650 + group. 651 + .I nr_args 652 + must be set to 1. Also see 653 + .B IORING_REGISTER_PBUF_RING . 654 + 655 + Available since 5.19. 656 + 657 + .TP 658 + .B IORING_REGISTER_SYNC_CANCEL 659 + Performs a synchronous cancelation request, which works in a similar fashion to 660 + .B IORING_OP_ASYNC_CANCEL 661 + except it completes inline. This can be useful for scenarios where cancelations 662 + should happen synchronously, rather than needing to issue an SQE and wait for 663 + completion of that specific CQE. 664 + 665 + .I arg 666 + must be set to a pointer to a struct io_uring_sync_cancel_reg structure, with 667 + the details filled in for what request(s) to target for cancelation. See 668 + .BR io_uring_register_sync_cancel (3) 669 + for details on that. The return values are the same, except they are passed 670 + back synchronously rather than through the CQE 671 + .I res 672 + field. 673 + .I nr_args 674 + must be set to 1. 675 + 676 + Available since 6.0. 677 + 678 + .TP 679 + .B IORING_REGISTER_FILE_ALLOC_RANGE 680 + sets the allowable range for fixed file index allocations within the 681 + kernel. When requests that can instantiate a new fixed file are used with 682 + .B IORING_FILE_INDEX_ALLOC , 683 + the application is asking the kernel to allocate a new fixed file descriptor 684 + rather than pass in a specific value for one. By default, the kernel will 685 + pick any available fixed file descriptor within the range available. 686 + This effectively allows the application to set aside a range just for dynamic 687 + allocations, with the remainder being used for specific values. 688 + 689 + .I nr_args 690 + must be set to 1 and 691 + .I arg 692 + must be set to a pointer to a struct io_uring_file_index_range: 693 + .PP 694 + .in +12n 695 + .EX 696 + struct io_uring_file_index_range { 697 + __u32 off; 698 + __u32 len; 699 + __u64 resv; 700 + }; 701 + .EE 702 + .in 703 + .PP 704 + .in +8n 705 + with 706 + .I off 707 + being set to the starting value for the range, and 708 + .I len 709 + being set to the number of descriptors. The reserved 710 + .I resv 711 + field must be cleared to zero. 712 + 713 + The application must have registered a file table first. 714 + 715 + Available since 6.0. 716 + 582 717 .SH RETURN VALUE 583 718 584 719 On success, 585 - .BR io_uring_register () 586 - returns 0. On error, 587 - .B -1 588 - is returned, and 720 + .BR io_uring_register (2) 721 + returns either 0 or a positive value, depending on the 722 + .I opcode 723 + used. On error, a negative error value is returned. The caller should not rely 724 + on the 589 725 .I errno 590 - is set accordingly. 726 + variable. 591 727 592 728 .SH ERRORS 593 729 .TP
+3 -2
vendor/liburing/man/io_uring_register_buf_ring.3
··· 55 55 and the size of 56 56 .IR "struct io_uring_buf" . 57 57 .I ring_entries 58 - is the desired size of the ring, and must be a power-of-2 in size. 58 + is the desired size of the ring, and must be a power-of-2 in size. The maximum 59 + size allowed is 2^15 (32768). 59 60 .I bgid 60 61 is the buffer group ID associated with this ring. SQEs that select a buffer 61 62 has a buffer group associated with them in their ··· 64 65 .B IORING_CQE_F_BUFFER 65 66 set in their 66 67 .I flags 67 - member, which will also contain the specific ID of the buffer seleted. The rest 68 + member, which will also contain the specific ID of the buffer selected. The rest 68 69 of the fields are reserved and must be cleared to zero. 69 70 70 71 The
+52
vendor/liburing/man/io_uring_register_file_alloc_range.3
··· 1 + .\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk> 2 + .\" 3 + .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 + .\" 5 + .TH io_uring_register_file_alloc_range 3 "Oct 21, 2022" "liburing-2.3" "liburing Manual" 6 + .SH NAME 7 + io_uring_register_file_alloc_range \- set range for fixed file allocations 8 + .SH SYNOPSIS 9 + .nf 10 + .B #include <liburing.h> 11 + .PP 12 + .BI "int io_uring_register_file_alloc_range(struct io_uring *" ring ", 13 + .BI " unsigned " off "," 14 + .BI " unsigned " len ");" 15 + .BI " 16 + .fi 17 + .SH DESCRIPTION 18 + .PP 19 + The 20 + .BR io_uring_register_file_alloc_range (3) 21 + function sets the allowable range for fixed file index allocations within the 22 + kernel. When requests that can instantiate a new fixed file are used with 23 + .B IORING_FILE_INDEX_ALLOC , 24 + the application is asking the kernel to allocate a new fixed file descriptor 25 + rather than pass in a specific value for one. By default, the kernel will 26 + pick any available fixed file descriptor within the range available. Calling 27 + this function with 28 + .I off 29 + set to the starting offset and 30 + .I len 31 + set to the number of descriptors, the application can limit the allocated 32 + descriptors to that particular range. This effectively allows the application 33 + to set aside a range just for dynamic allocations, with the remainder being 34 + used for specific values. 35 + 36 + The application must have registered a fixed file table upfront, eg through 37 + .BR io_uring_register_files (3) 38 + or 39 + .BR io_uring_register_files_sparse (3) . 40 + 41 + Available since 6.0. 42 + 43 + .SH RETURN VALUE 44 + On success 45 + .BR io_uring_register_buf_ring (3) 46 + returns 0. On failure it returns 47 + .BR -errno . 48 + .SH SEE ALSO 49 + .BR io_uring_register_files (3) 50 + .BR io_uring_prep_accept_direct (3) 51 + .BR io_uring_prep_openat_direct (3) 52 + .BR io_uring_prep_socket_direct (3)
+7
vendor/liburing/man/io_uring_register_files.3
··· 38 38 Registering a file table is a prerequisite for using any request that uses 39 39 direct descriptors. 40 40 41 + Registered files have less overhead per operation than normal files. This 42 + is due to the kernel grabbing a reference count on a file when an operation 43 + begins, and dropping it when it's done. When the process file table is 44 + shared, for example if the process has ever created any threads, then this 45 + cost goes up even more. Using registered files reduces the overhead of 46 + file reference management across requests that operate on a file. 47 + 41 48 .SH RETURN VALUE 42 49 On success 43 50 .BR io_uring_register_files (3)
+1
vendor/liburing/man/io_uring_register_files_sparse.3
··· 1 + io_uring_register_files.3
+71
vendor/liburing/man/io_uring_register_sync_cancel.3
··· 1 + .\" Copyright (C) 2022 Jens Axboe <axboe@kernel.dk> 2 + .\" 3 + .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 + .\" 5 + .TH io_uring_register_sync_cancel 3 "September 21, 2022" "liburing-2.3" "liburing Manual" 6 + .SH NAME 7 + io_uring_register_sync_cancel \- issue a synchronous cancelation request 8 + .SH SYNOPSIS 9 + .nf 10 + .B #include <liburing.h> 11 + .PP 12 + .BI "int io_uring_register_sync_cancel(struct io_uring *" ring ", 13 + .BI " struct io_uring_sync_cancel_reg *" reg "); 14 + .PP 15 + .SH DESCRIPTION 16 + .PP 17 + The 18 + .BR io_uring_register_sync_cancel (3) 19 + function performs a synchronous cancelation request based on the parameters 20 + specified in 21 + .I reg . 22 + 23 + The 24 + .I reg 25 + argument must be filled in with the appropriate information for the 26 + cancelation request. It looks as follows: 27 + .PP 28 + .in +4n 29 + .EX 30 + struct io_uring_sync_cancel_reg { 31 + __u64 addr; 32 + __s32 fd; 33 + __u32 flags; 34 + struct __kernel_timespec timeout; 35 + __u64 pad[4]; 36 + }; 37 + .EE 38 + .in 39 + .PP 40 + 41 + The arguments largely mirror what the async prep functions support, see 42 + .BR io_uring_prep_cancel (3) 43 + for details. Similarly, the return value is the same. The exception is the 44 + .I timeout 45 + argument, which can be used to limit the time that the kernel will wait for 46 + cancelations to be successful. If the 47 + .I tv_sec 48 + and 49 + .I tv_nsec 50 + values are set to anything but 51 + .B -1UL , 52 + then they indicate a relative timeout upon which cancelations should be 53 + completed by. 54 + 55 + The 56 + .I pad 57 + values must be zero filled. 58 + 59 + .SH RETURN VALUE 60 + See 61 + .BR io_uring_prep_cancel (3) 62 + for details on the return value. If 63 + .I timeout 64 + is set to indicate a timeout, then 65 + .B -ETIME 66 + will be returned if exceeded. If an unknown value is set in the request, 67 + or if the pad values are not cleared to zero, then 68 + .I -EINVAL 69 + is returned. 70 + .SH SEE ALSO 71 + .BR io_uring_prep_cancel (3)
+56 -12
vendor/liburing/man/io_uring_setup.2
··· 4 4 .\" 5 5 .\" SPDX-License-Identifier: LGPL-2.0-or-later 6 6 .\" 7 - .TH IO_URING_SETUP 2 2019-01-29 "Linux" "Linux Programmer's Manual" 7 + .TH io_uring_setup 2 2019-01-29 "Linux" "Linux Programmer's Manual" 8 8 .SH NAME 9 9 io_uring_setup \- setup a context for performing asynchronous I/O 10 10 .SH SYNOPSIS 11 11 .nf 12 - .BR "#include <linux/io_uring.h>" 12 + .BR "#include <liburing.h>" 13 13 .PP 14 14 .BI "int io_uring_setup(u32 " entries ", struct io_uring_params *" p ); 15 15 .fi 16 - .PP 16 + .PPAA 17 17 .SH DESCRIPTION 18 18 .PP 19 - The io_uring_setup() system call sets up a submission queue (SQ) and 20 - completion queue (CQ) with at least 19 + The 20 + .BR io_uring_setup (2) 21 + system call sets up a submission queue (SQ) and completion queue (CQ) with at 22 + least 21 23 .I entries 22 24 entries, and returns a file descriptor which can be used to perform 23 25 subsequent operations on the io_uring instance. The submission and ··· 234 236 passthrough command for NVMe passthrough needs this. Available since 5.19. 235 237 .TP 236 238 .B IORING_SETUP_CQE32 237 - If set, io_uring will use 32-byte CQEs rather than the normal 32-byte sized 239 + If set, io_uring will use 32-byte CQEs rather than the normal 16-byte sized 238 240 variant. This is a requirement for using certain request types, as of 5.19 239 241 only the 240 242 .B IORING_OP_URING_CMD 241 243 passthrough command for NVMe passthrough needs this. Available since 5.19. 244 + .TP 245 + .B IORING_SETUP_SINGLE_ISSUER 246 + A hint to the kernel that only a single task (or thread) will submit requests, which is 247 + used for internal optimisations. The submission task is either the task that created the 248 + ring, or if 249 + .B IORING_SETUP_R_DISABLED 250 + is specified then it is the task that enables the ring through 251 + .BR io_uring_register (2) . 252 + The kernel enforces this rule, failing requests with 253 + .B -EEXIST 254 + if the restriction is violated. 255 + Note that when 256 + .B IORING_SETUP_SQPOLL 257 + is set it is considered that the polling task is doing all submissions 258 + on behalf of the userspace and so it always complies with the rule disregarding 259 + how many userspace tasks do 260 + .BR io_uring_enter(2). 261 + Available since 6.0. 262 + .TP 263 + .B IORING_SETUP_DEFER_TASKRUN 264 + By default, io_uring will process all outstanding work at the end of any system 265 + call or thread interrupt. This can delay the application from making other progress. 266 + Setting this flag will hint to io_uring that it should defer work until an 267 + .BR io_uring_enter(2) 268 + call with the 269 + .B IORING_ENTER_GETEVENTS 270 + flag set. This allows the application to request work to run just before it wants to 271 + process completions. 272 + This flag requires the 273 + .BR IORING_SETUP_SINGLE_ISSUER 274 + flag to be set, and also enforces that the call to 275 + .BR io_uring_enter(2) 276 + is called from the same thread that submitted requests. 277 + Note that if this flag is set then it is the application's responsibility to periodically 278 + trigger work (for example via any of the CQE waiting functions) or else completions may 279 + not be delivered. 280 + Available since 6.1. 242 281 .PP 243 282 If no flags are specified, the io_uring instance is setup for 244 283 interrupt driven I/O. I/O may be submitted using ··· 261 300 calls down from three to two. Available since kernel 5.4. 262 301 .TP 263 302 .B IORING_FEAT_NODROP 264 - If this flag is set, io_uring supports never dropping completion events. 303 + If this flag is set, io_uring supports almost never dropping completion events. 265 304 If a completion event occurs and the CQ ring is full, the kernel stores 266 305 the event internally until such a time that the CQ ring has room for more 267 306 entries. If this overflow condition is entered, attempting to submit more ··· 269 308 .B -EBUSY 270 309 error value, if it can't flush the overflown events to the CQ ring. If this 271 310 happens, the application must reap events from the CQ ring and attempt the 272 - submit again. Available since kernel 5.5. 311 + submit again. If the kernel has no free memory to store the event internally 312 + it will be visible by an increase in the overflow value on the cqring. 313 + Available since kernel 5.5. Additionally 314 + .BR io_uring_enter (2) 315 + will return 316 + .B -EBADR 317 + the next time it would otherwise sleep waiting for completions (since kernel 5.19). 318 + 273 319 .TP 274 320 .B IORING_FEAT_SUBMIT_STABLE 275 321 If this flag is set, applications can be certain that any data for ··· 548 594 .BR io_uring_enter (2) 549 595 system calls. 550 596 551 - On error, 552 - .B -1 553 - is returned and 597 + On error, a negative error code is returned. The caller should not rely on 554 598 .I errno 555 - is set appropriately. 599 + variable. 556 600 .PP 557 601 .SH ERRORS 558 602 .TP
+2 -2
vendor/liburing/man/io_uring_sq_ready.3
··· 2 2 .\" 3 3 .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 4 .\" 5 - .TH io_uring_sq_ready "January 25, 2022" "liburing-2.1" "liburing Manual" 5 + .TH io_uring_sq_ready 3 "January 25, 2022" "liburing-2.1" "liburing Manual" 6 6 .SH NAME 7 7 io_uring_sq_ready \- number of unconsumed or unsubmitted entries in the SQ ring 8 8 .SH SYNOPSIS ··· 15 15 .PP 16 16 The 17 17 .BR io_uring_sq_ready (3) 18 - function retuns the number of unconsumed (if SQPOLL) or unsubmitted entries 18 + function returns the number of unconsumed (if SQPOLL) or unsubmitted entries 19 19 that exist in the SQ ring belonging to the 20 20 .I ring 21 21 param.
+2 -2
vendor/liburing/man/io_uring_sq_space_left.3
··· 2 2 .\" 3 3 .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 4 .\" 5 - .TH io_uring_sq_space-left "January 25, 2022" "liburing-2.1" "liburing Manual" 5 + .TH io_uring_sq_space-left 3 "January 25, 2022" "liburing-2.1" "liburing Manual" 6 6 .SH NAME 7 7 io_uring_sq_space_left \- free space in the SQ ring 8 8 .SH SYNOPSIS ··· 15 15 .PP 16 16 The 17 17 .BR io_uring_sq_space_left (3) 18 - function retuns how much space is left in the SQ ring belonging to the 18 + function returns how much space is left in the SQ ring belonging to the 19 19 .I ring 20 20 param. 21 21
+4 -3
vendor/liburing/man/io_uring_sqe_set_flags.3
··· 2 2 .\" 3 3 .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 4 .\" 5 - .TH io_uring_sqe_set_flags "January 25, 2022" "liburing-2.1" "liburing Manual" 5 + .TH io_uring_sqe_set_flags 3 "January 25, 2022" "liburing-2.1" "liburing Manual" 6 6 .SH NAME 7 7 io_uring_sqe_set_flags \- set flags for submission queue entry 8 8 .SH SYNOPSIS ··· 37 37 always (or most of the time) block, the application can ask for an sqe to be 38 38 issued async from the start. Note that this flag immediately causes the SQE 39 39 to be offloaded to an async helper thread with no initial non-blocking attempt. 40 - This may be less efficient and should not be used sporadically. 40 + This may be less efficient and should not be used liberally or without 41 + understanding the performance and efficiency tradeoffs. 41 42 .TP 42 43 .B IOSQE_IO_LINK 43 44 When this flag is specified, the SQE forms a link with the next SQE in the ··· 65 66 .B IOSQE_CQE_SKIP_SUCCESS 66 67 Request that no CQE be generated for this request, if it completes successfully. 67 68 This can be useful in cases where the application doesn't need to know when 68 - a specific request completed, if it completed succesfully. 69 + a specific request completed, if it completed successfully. 69 70 .TP 70 71 .B IOSQE_BUFFER_SELECT 71 72 If set, and if the request types supports it, select an IO buffer from the
+1 -1
vendor/liburing/man/io_uring_sqring_wait.3
··· 2 2 .\" 3 3 .\" SPDX-License-Identifier: LGPL-2.0-or-later 4 4 .\" 5 - .TH io_uring_sqring_wait "January 25, 2022" "liburing-2.1" "liburing Manual" 5 + .TH io_uring_sqring_wait 3 "January 25, 2022" "liburing-2.1" "liburing Manual" 6 6 .SH NAME 7 7 io_uring_sqring_wait \- wait for free space in the SQ ring 8 8 .SH SYNOPSIS
+31
vendor/liburing/man/io_uring_submit_and_get_events.3
··· 1 + .\" Copyright (C), 2022 dylany 2 + .\" You may distribute this file under the terms of the GNU Free 3 + .\" Documentation License. 4 + .TH io_uring_submit_and_get_events 3 "September 5, 2022" "liburing-2.3" "liburing Manual" 5 + .SH NAME 6 + io_uring_submit_and_get_events \- submit requests to the submission queue and flush completions 7 + .SH SYNOPSIS 8 + .nf 9 + .B #include <liburing.h> 10 + .PP 11 + .BI "int io_uring_submit_and_get_events(struct io_uring *" ring ");" 12 + .fi 13 + 14 + .SH DESCRIPTION 15 + The 16 + .BR io_uring_submit_and_get_events (3) 17 + function submits the next events to the submission queue as with 18 + .BR io_uring_submit (3) . 19 + After submission it will flush CQEs as with 20 + .BR io_uring_get_events (3) . 21 + 22 + The benefit of this function is that it does both with only one system call. 23 + 24 + .SH RETURN VALUE 25 + On success 26 + .BR io_uring_submit_and_get_events (3) 27 + returns the number of submitted submission queue entries. On failure it returns 28 + .BR -errno . 29 + .SH SEE ALSO 30 + .BR io_uring_submit (3), 31 + .BR io_uring_get_events (3)
+1 -1
vendor/liburing/man/io_uring_submit_and_wait.3
··· 16 16 .PP 17 17 The 18 18 .BR io_uring_submit_and_wait (3) 19 - function submits the next events to the submission queue belonging to the 19 + function submits the next requests from the submission queue belonging to the 20 20 .I ring 21 21 and waits for 22 22 .I wait_nr
+4 -2
vendor/liburing/man/io_uring_submit_and_wait_timeout.3
··· 20 20 .PP 21 21 The 22 22 .BR io_uring_submit_and_wait_timeout (3) 23 - function submits the next events to the submission queue belonging to the 23 + function submits the next requests from the submission queue belonging to the 24 24 .I ring 25 25 and waits for 26 26 .I wait_nr 27 - completion events or until the timeout 27 + completion events, or until the timeout 28 28 .I ts 29 29 expires. The completion events are stored in the 30 30 .I cqe_ptr ··· 43 43 .BR io_uring_submit_and_wait_timeout (3) 44 44 returns the number of submitted submission queue entries. On failure it returns 45 45 .BR -errno . 46 + Note that in earlier versions of the liburing library, the return value was 0 47 + on success. 46 48 The most common failure case is not receiving a completion within the specified 47 49 timeout, 48 50 .B -ETIME
+1 -1
vendor/liburing/man/io_uring_wait_cqe.3
··· 31 31 .SH RETURN VALUE 32 32 On success 33 33 .BR io_uring_wait_cqe (3) 34 - returns 0 and the cqe_ptr parm is filled in. On failure it returns 34 + returns 0 and the cqe_ptr param is filled in. On failure it returns 35 35 .BR -errno . 36 36 The return value indicates the result of waiting for a CQE, and it has no 37 37 relation to the CQE result itself.
+1 -1
vendor/liburing/man/io_uring_wait_cqe_nr.3
··· 34 34 .SH RETURN VALUE 35 35 On success 36 36 .BR io_uring_wait_cqe_nr (3) 37 - returns 0 and the cqe_ptr parm is filled in. On failure it returns 37 + returns 0 and the cqe_ptr param is filled in. On failure it returns 38 38 .BR -errno . 39 39 The return value indicates the result of waiting for a CQE, and it has no 40 40 relation to the CQE result itself.
+1 -1
vendor/liburing/man/io_uring_wait_cqe_timeout.3
··· 43 43 .SH RETURN VALUE 44 44 On success 45 45 .BR io_uring_wait_cqes (3) 46 - returns 0 and the cqe_ptr parm is filled in. On failure it returns 46 + returns 0 and the cqe_ptr param is filled in. On failure it returns 47 47 .BR -errno . 48 48 The return value indicates the result of waiting for a CQE, and it has no 49 49 relation to the CQE result itself.
+1 -1
vendor/liburing/man/io_uring_wait_cqes.3
··· 48 48 .SH RETURN VALUE 49 49 On success 50 50 .BR io_uring_wait_cqes (3) 51 - returns 0 and the cqe_ptr parm is filled in. On failure it returns 51 + returns 0 and the cqe_ptr param is filled in. On failure it returns 52 52 .BR -errno . 53 53 .SH SEE ALSO 54 54 .BR io_uring_submit (3),
+6 -5
vendor/liburing/src/Makefile
··· 5 5 libdir ?= $(prefix)/lib 6 6 libdevdir ?= $(prefix)/lib 7 7 8 + LIBURING_CFLAGS ?= 8 9 CPPFLAGS ?= 9 10 override CPPFLAGS += -D_GNU_SOURCE \ 10 11 -Iinclude/ -include ../config-host.h 11 - CFLAGS ?= -g -O2 -Wall -Wextra -fno-stack-protector 12 - override CFLAGS += -Wno-unused-parameter -Wno-sign-compare -DLIBURING_INTERNAL 12 + CFLAGS ?= -g -O3 -Wall -Wextra -fno-stack-protector 13 + override CFLAGS += -Wno-unused-parameter -Wno-sign-compare \ 14 + -DLIBURING_INTERNAL \ 15 + $(LIBURING_CFLAGS) 13 16 SO_CFLAGS=-fPIC $(CFLAGS) 14 17 L_CFLAGS=$(CFLAGS) 15 18 LINK_FLAGS= ··· 32 35 33 36 all: $(all_targets) 34 37 35 - liburing_srcs := setup.c queue.c register.c 38 + liburing_srcs := setup.c queue.c register.c syscall.c 36 39 37 40 ifeq ($(CONFIG_NOLIBC),y) 38 41 liburing_srcs += nolibc.c 39 42 override CFLAGS += -nostdlib -nodefaultlibs -ffreestanding 40 43 override CPPFLAGS += -nostdlib -nodefaultlibs -ffreestanding 41 44 override LINK_FLAGS += -nostdlib -nodefaultlibs 42 - else 43 - liburing_srcs += syscall.c 44 45 endif 45 46 46 47 override CPPFLAGS += -MT "$@" -MMD -MP -MF "$@.d"
+48
vendor/liburing/src/arch/aarch64/lib.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + 3 + #ifndef LIBURING_ARCH_AARCH64_LIB_H 4 + #define LIBURING_ARCH_AARCH64_LIB_H 5 + 6 + #include <elf.h> 7 + #include <sys/auxv.h> 8 + #include "../../syscall.h" 9 + 10 + static inline long __get_page_size(void) 11 + { 12 + Elf64_Off buf[2]; 13 + long ret = 4096; 14 + int fd; 15 + 16 + fd = __sys_open("/proc/self/auxv", O_RDONLY, 0); 17 + if (fd < 0) 18 + return ret; 19 + 20 + while (1) { 21 + ssize_t x; 22 + 23 + x = __sys_read(fd, buf, sizeof(buf)); 24 + if (x < sizeof(buf)) 25 + break; 26 + 27 + if (buf[0] == AT_PAGESZ) { 28 + ret = buf[1]; 29 + break; 30 + } 31 + } 32 + 33 + __sys_close(fd); 34 + return ret; 35 + } 36 + 37 + static inline long get_page_size(void) 38 + { 39 + static long cache_val; 40 + 41 + if (cache_val) 42 + return cache_val; 43 + 44 + cache_val = __get_page_size(); 45 + return cache_val; 46 + } 47 + 48 + #endif /* #ifndef LIBURING_ARCH_AARCH64_LIB_H */
-4
vendor/liburing/src/arch/aarch64/syscall.h
··· 1 1 /* SPDX-License-Identifier: MIT */ 2 2 3 - #ifndef __INTERNAL__LIBURING_SYSCALL_H 4 - #error "This file should be included from src/syscall.h (liburing)" 5 - #endif 6 - 7 3 #ifndef LIBURING_ARCH_AARCH64_SYSCALL_H 8 4 #define LIBURING_ARCH_AARCH64_SYSCALL_H 9 5
-4
vendor/liburing/src/arch/generic/lib.h
··· 1 1 /* SPDX-License-Identifier: MIT */ 2 2 3 - #ifndef __INTERNAL__LIBURING_LIB_H 4 - #error "This file should be included from src/lib.h (liburing)" 5 - #endif 6 - 7 3 #ifndef LIBURING_ARCH_GENERIC_LIB_H 8 4 #define LIBURING_ARCH_GENERIC_LIB_H 9 5
+29 -16
vendor/liburing/src/arch/generic/syscall.h
··· 1 1 /* SPDX-License-Identifier: MIT */ 2 2 3 - #ifndef __INTERNAL__LIBURING_SYSCALL_H 4 - #error "This file should be included from src/syscall.h (liburing)" 5 - #endif 6 - 7 3 #ifndef LIBURING_ARCH_GENERIC_SYSCALL_H 8 4 #define LIBURING_ARCH_GENERIC_SYSCALL_H 9 5 10 - static inline int ____sys_io_uring_register(int fd, unsigned opcode, 11 - const void *arg, unsigned nr_args) 6 + #include <fcntl.h> 7 + 8 + static inline int __sys_io_uring_register(unsigned int fd, unsigned int opcode, 9 + const void *arg, unsigned int nr_args) 12 10 { 13 11 int ret; 14 12 ret = syscall(__NR_io_uring_register, fd, opcode, arg, nr_args); 15 13 return (ret < 0) ? -errno : ret; 16 14 } 17 15 18 - static inline int ____sys_io_uring_setup(unsigned entries, 19 - struct io_uring_params *p) 16 + static inline int __sys_io_uring_setup(unsigned int entries, 17 + struct io_uring_params *p) 20 18 { 21 19 int ret; 22 20 ret = syscall(__NR_io_uring_setup, entries, p); 23 21 return (ret < 0) ? -errno : ret; 24 22 } 25 23 26 - static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, 27 - unsigned min_complete, unsigned flags, 28 - sigset_t *sig, int sz) 24 + static inline int __sys_io_uring_enter2(unsigned int fd, unsigned int to_submit, 25 + unsigned int min_complete, 26 + unsigned int flags, sigset_t *sig, 27 + size_t sz) 29 28 { 30 29 int ret; 31 30 ret = syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, ··· 33 32 return (ret < 0) ? -errno : ret; 34 33 } 35 34 36 - static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, 37 - unsigned min_complete, unsigned flags, 38 - sigset_t *sig) 35 + static inline int __sys_io_uring_enter(unsigned int fd, unsigned int to_submit, 36 + unsigned int min_complete, 37 + unsigned int flags, sigset_t *sig) 39 38 { 40 - return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, 41 - _NSIG / 8); 39 + return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, 40 + _NSIG / 8); 41 + } 42 + 43 + static inline int __sys_open(const char *pathname, int flags, mode_t mode) 44 + { 45 + int ret; 46 + ret = open(pathname, flags, mode); 47 + return (ret < 0) ? -errno : ret; 48 + } 49 + 50 + static inline ssize_t __sys_read(int fd, void *buffer, size_t size) 51 + { 52 + ssize_t ret; 53 + ret = read(fd, buffer, size); 54 + return (ret < 0) ? -errno : ret; 42 55 } 43 56 44 57 static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags,
+33 -13
vendor/liburing/src/arch/syscall-defs.h
··· 3 3 #ifndef LIBURING_ARCH_SYSCALL_DEFS_H 4 4 #define LIBURING_ARCH_SYSCALL_DEFS_H 5 5 6 + #include <fcntl.h> 7 + 8 + static inline int __sys_open(const char *pathname, int flags, mode_t mode) 9 + { 10 + /* 11 + * Some architectures don't have __NR_open, but __NR_openat. 12 + */ 13 + #ifdef __NR_open 14 + return (int) __do_syscall3(__NR_open, pathname, flags, mode); 15 + #else 16 + return (int) __do_syscall4(__NR_openat, AT_FDCWD, pathname, flags, mode); 17 + #endif 18 + } 19 + 20 + static inline ssize_t __sys_read(int fd, void *buffer, size_t size) 21 + { 22 + return (ssize_t) __do_syscall3(__NR_read, fd, buffer, size); 23 + } 24 + 6 25 static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags, 7 26 int fd, off_t offset) 8 27 { 9 28 int nr; 10 29 11 - #if defined(__i386__) 30 + #if defined(__NR_mmap2) 12 31 nr = __NR_mmap2; 13 32 offset >>= 12; 14 33 #else ··· 42 61 return (int) __do_syscall1(__NR_close, fd); 43 62 } 44 63 45 - static inline int ____sys_io_uring_register(int fd, unsigned opcode, 46 - const void *arg, unsigned nr_args) 64 + static inline int __sys_io_uring_register(unsigned int fd, unsigned int opcode, 65 + const void *arg, unsigned int nr_args) 47 66 { 48 67 return (int) __do_syscall4(__NR_io_uring_register, fd, opcode, arg, 49 68 nr_args); 50 69 } 51 70 52 - static inline int ____sys_io_uring_setup(unsigned entries, 53 - struct io_uring_params *p) 71 + static inline int __sys_io_uring_setup(unsigned int entries, 72 + struct io_uring_params *p) 54 73 { 55 74 return (int) __do_syscall2(__NR_io_uring_setup, entries, p); 56 75 } 57 76 58 - static inline int ____sys_io_uring_enter2(int fd, unsigned to_submit, 59 - unsigned min_complete, unsigned flags, 60 - sigset_t *sig, int sz) 77 + static inline int __sys_io_uring_enter2(unsigned int fd, unsigned int to_submit, 78 + unsigned int min_complete, 79 + unsigned int flags, sigset_t *sig, 80 + size_t sz) 61 81 { 62 82 return (int) __do_syscall6(__NR_io_uring_enter, fd, to_submit, 63 83 min_complete, flags, sig, sz); 64 84 } 65 85 66 - static inline int ____sys_io_uring_enter(int fd, unsigned to_submit, 67 - unsigned min_complete, unsigned flags, 68 - sigset_t *sig) 86 + static inline int __sys_io_uring_enter(unsigned int fd, unsigned int to_submit, 87 + unsigned int min_complete, 88 + unsigned int flags, sigset_t *sig) 69 89 { 70 - return ____sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, 71 - _NSIG / 8); 90 + return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, 91 + _NSIG / 8); 72 92 } 73 93 74 94 #endif
-4
vendor/liburing/src/arch/x86/lib.h
··· 1 1 /* SPDX-License-Identifier: MIT */ 2 2 3 - #ifndef __INTERNAL__LIBURING_LIB_H 4 - #error "This file should be included from src/lib.h (liburing)" 5 - #endif 6 - 7 3 #ifndef LIBURING_ARCH_X86_LIB_H 8 4 #define LIBURING_ARCH_X86_LIB_H 9 5
-4
vendor/liburing/src/arch/x86/syscall.h
··· 1 1 /* SPDX-License-Identifier: MIT */ 2 2 3 - #ifndef __INTERNAL__LIBURING_SYSCALL_H 4 - #error "This file should be included from src/syscall.h (liburing)" 5 - #endif 6 - 7 3 #ifndef LIBURING_ARCH_X86_SYSCALL_H 8 4 #define LIBURING_ARCH_X86_SYSCALL_H 9 5
+218 -25
vendor/liburing/src/include/liburing.h
··· 33 33 #define uring_likely(cond) __builtin_expect(!!(cond), 1) 34 34 #endif 35 35 36 + #ifdef __alpha__ 37 + /* 38 + * alpha and mips are the exceptions, all other architectures have 39 + * common numbers for new system calls. 40 + */ 41 + #ifndef __NR_io_uring_setup 42 + #define __NR_io_uring_setup 535 43 + #endif 44 + #ifndef __NR_io_uring_enter 45 + #define __NR_io_uring_enter 536 46 + #endif 47 + #ifndef __NR_io_uring_register 48 + #define __NR_io_uring_register 537 49 + #endif 50 + #elif defined __mips__ 51 + #ifndef __NR_io_uring_setup 52 + #define __NR_io_uring_setup (__NR_Linux + 425) 53 + #endif 54 + #ifndef __NR_io_uring_enter 55 + #define __NR_io_uring_enter (__NR_Linux + 426) 56 + #endif 57 + #ifndef __NR_io_uring_register 58 + #define __NR_io_uring_register (__NR_Linux + 427) 59 + #endif 60 + #else /* !__alpha__ and !__mips__ */ 61 + #ifndef __NR_io_uring_setup 62 + #define __NR_io_uring_setup 425 63 + #endif 64 + #ifndef __NR_io_uring_enter 65 + #define __NR_io_uring_enter 426 66 + #endif 67 + #ifndef __NR_io_uring_register 68 + #define __NR_io_uring_register 427 69 + #endif 70 + #endif 71 + 36 72 #ifdef __cplusplus 37 73 extern "C" { 38 74 #endif ··· 43 79 struct io_uring_sq { 44 80 unsigned *khead; 45 81 unsigned *ktail; 82 + // Deprecated: use `ring_mask` instead of `*kring_mask` 46 83 unsigned *kring_mask; 84 + // Deprecated: use `ring_entries` instead of `*kring_entries` 47 85 unsigned *kring_entries; 48 86 unsigned *kflags; 49 87 unsigned *kdropped; ··· 56 94 size_t ring_sz; 57 95 void *ring_ptr; 58 96 59 - unsigned pad[4]; 97 + unsigned ring_mask; 98 + unsigned ring_entries; 99 + 100 + unsigned pad[2]; 60 101 }; 61 102 62 103 struct io_uring_cq { 63 104 unsigned *khead; 64 105 unsigned *ktail; 106 + // Deprecated: use `ring_mask` instead of `*kring_mask` 65 107 unsigned *kring_mask; 108 + // Deprecated: use `ring_entries` instead of `*kring_entries` 66 109 unsigned *kring_entries; 67 110 unsigned *kflags; 68 111 unsigned *koverflow; ··· 71 114 size_t ring_sz; 72 115 void *ring_ptr; 73 116 74 - unsigned pad[4]; 117 + unsigned ring_mask; 118 + unsigned ring_entries; 119 + 120 + unsigned pad[2]; 75 121 }; 76 122 77 123 struct io_uring { ··· 160 206 161 207 int io_uring_unregister_files(struct io_uring *ring); 162 208 int io_uring_register_files_update(struct io_uring *ring, unsigned off, 163 - int *files, unsigned nr_files); 209 + const int *files, unsigned nr_files); 164 210 int io_uring_register_eventfd(struct io_uring *ring, int fd); 165 211 int io_uring_register_eventfd_async(struct io_uring *ring, int fd); 166 212 int io_uring_unregister_eventfd(struct io_uring *ring); ··· 183 229 int io_uring_register_buf_ring(struct io_uring *ring, 184 230 struct io_uring_buf_reg *reg, unsigned int flags); 185 231 int io_uring_unregister_buf_ring(struct io_uring *ring, int bgid); 232 + int io_uring_register_sync_cancel(struct io_uring *ring, 233 + struct io_uring_sync_cancel_reg *reg); 234 + 235 + int io_uring_register_file_alloc_range(struct io_uring *ring, 236 + unsigned off, unsigned len); 237 + 238 + int io_uring_get_events(struct io_uring *ring); 239 + int io_uring_submit_and_get_events(struct io_uring *ring); 240 + 241 + /* 242 + * io_uring syscalls. 243 + */ 244 + int io_uring_enter(unsigned int fd, unsigned int to_submit, 245 + unsigned int min_complete, unsigned int flags, sigset_t *sig); 246 + int io_uring_enter2(unsigned int fd, unsigned int to_submit, 247 + unsigned int min_complete, unsigned int flags, 248 + sigset_t *sig, size_t sz); 249 + int io_uring_setup(unsigned int entries, struct io_uring_params *p); 250 + int io_uring_register(unsigned int fd, unsigned int opcode, const void *arg, 251 + unsigned int nr_args); 186 252 187 253 /* 188 254 * Helper for the peek/wait single cqe functions. Exported because of that, ··· 211 277 */ \ 212 278 for (head = *(ring)->cq.khead; \ 213 279 (cqe = (head != io_uring_smp_load_acquire((ring)->cq.ktail) ? \ 214 - &(ring)->cq.cqes[io_uring_cqe_index(ring, head, *(ring)->cq.kring_mask)] : NULL)); \ 280 + &(ring)->cq.cqes[io_uring_cqe_index(ring, head, (ring)->cq.ring_mask)] : NULL)); \ 215 281 head++) \ 216 282 217 283 /* ··· 414 480 sqe->msg_flags = flags; 415 481 } 416 482 483 + static inline void io_uring_prep_recvmsg_multishot(struct io_uring_sqe *sqe, int fd, 484 + struct msghdr *msg, unsigned flags) 485 + { 486 + io_uring_prep_recvmsg(sqe, fd, msg, flags); 487 + sqe->ioprio |= IORING_RECV_MULTISHOT; 488 + } 489 + 417 490 static inline void io_uring_prep_sendmsg(struct io_uring_sqe *sqe, int fd, 418 491 const struct msghdr *msg, 419 492 unsigned flags) ··· 585 658 static inline void io_uring_prep_fallocate(struct io_uring_sqe *sqe, int fd, 586 659 int mode, off_t offset, off_t len) 587 660 { 588 - 589 661 io_uring_prep_rw(IORING_OP_FALLOCATE, sqe, fd, 590 - (const uintptr_t *) (unsigned long) len, 591 - (unsigned int) mode, (__u64) offset); 662 + 0, (unsigned int) mode, (__u64) offset); 663 + sqe->addr = (__u64) len; 592 664 } 593 665 594 666 static inline void io_uring_prep_openat(struct io_uring_sqe *sqe, int dfd, ··· 663 735 { 664 736 io_uring_prep_rw(IORING_OP_SEND, sqe, sockfd, buf, (__u32) len, 0); 665 737 sqe->msg_flags = (__u32) flags; 738 + } 739 + 740 + static inline void io_uring_prep_send_zc(struct io_uring_sqe *sqe, int sockfd, 741 + const void *buf, size_t len, int flags, 742 + unsigned zc_flags) 743 + { 744 + io_uring_prep_rw(IORING_OP_SEND_ZC, sqe, sockfd, buf, (__u32) len, 0); 745 + sqe->msg_flags = (__u32) flags; 746 + sqe->ioprio = zc_flags; 747 + } 748 + 749 + static inline void io_uring_prep_send_zc_fixed(struct io_uring_sqe *sqe, 750 + int sockfd, const void *buf, 751 + size_t len, int flags, 752 + unsigned zc_flags, 753 + unsigned buf_index) 754 + { 755 + io_uring_prep_send_zc(sqe, sockfd, buf, len, flags, zc_flags); 756 + sqe->ioprio |= IORING_RECVSEND_FIXED_BUF; 757 + sqe->buf_index = buf_index; 758 + } 759 + 760 + static inline void io_uring_prep_sendmsg_zc(struct io_uring_sqe *sqe, int fd, 761 + const struct msghdr *msg, 762 + unsigned flags) 763 + { 764 + io_uring_prep_sendmsg(sqe, fd, msg, flags); 765 + sqe->opcode = IORING_OP_SENDMSG_ZC; 766 + } 767 + 768 + static inline void io_uring_prep_send_set_addr(struct io_uring_sqe *sqe, 769 + const struct sockaddr *dest_addr, 770 + __u16 addr_len) 771 + { 772 + sqe->addr2 = (unsigned long)(const void *)dest_addr; 773 + sqe->addr_len = addr_len; 666 774 } 667 775 668 776 static inline void io_uring_prep_recv(struct io_uring_sqe *sqe, int sockfd, ··· 672 780 sqe->msg_flags = (__u32) flags; 673 781 } 674 782 783 + static inline void io_uring_prep_recv_multishot(struct io_uring_sqe *sqe, 784 + int sockfd, void *buf, 785 + size_t len, int flags) 786 + { 787 + io_uring_prep_recv(sqe, sockfd, buf, len, flags); 788 + sqe->ioprio |= IORING_RECV_MULTISHOT; 789 + } 790 + 791 + static inline struct io_uring_recvmsg_out * 792 + io_uring_recvmsg_validate(void *buf, int buf_len, struct msghdr *msgh) 793 + { 794 + unsigned long header = msgh->msg_controllen + msgh->msg_namelen + 795 + sizeof(struct io_uring_recvmsg_out); 796 + if (buf_len < 0 || (unsigned long)buf_len < header) 797 + return NULL; 798 + return (struct io_uring_recvmsg_out *)buf; 799 + } 800 + 801 + static inline void *io_uring_recvmsg_name(struct io_uring_recvmsg_out *o) 802 + { 803 + return (void *) &o[1]; 804 + } 805 + 806 + static inline struct cmsghdr * 807 + io_uring_recvmsg_cmsg_firsthdr(struct io_uring_recvmsg_out *o, 808 + struct msghdr *msgh) 809 + { 810 + if (o->controllen < sizeof(struct cmsghdr)) 811 + return NULL; 812 + 813 + return (struct cmsghdr *)((unsigned char *) io_uring_recvmsg_name(o) + 814 + msgh->msg_namelen); 815 + } 816 + 817 + static inline struct cmsghdr * 818 + io_uring_recvmsg_cmsg_nexthdr(struct io_uring_recvmsg_out *o, struct msghdr *msgh, 819 + struct cmsghdr *cmsg) 820 + { 821 + unsigned char *end; 822 + 823 + if (cmsg->cmsg_len < sizeof(struct cmsghdr)) 824 + return NULL; 825 + end = (unsigned char *) io_uring_recvmsg_cmsg_firsthdr(o, msgh) + 826 + o->controllen; 827 + cmsg = (struct cmsghdr *)((unsigned char *) cmsg + 828 + CMSG_ALIGN(cmsg->cmsg_len)); 829 + 830 + if ((unsigned char *) (cmsg + 1) > end) 831 + return NULL; 832 + if (((unsigned char *) cmsg) + CMSG_ALIGN(cmsg->cmsg_len) > end) 833 + return NULL; 834 + 835 + return cmsg; 836 + } 837 + 838 + static inline void *io_uring_recvmsg_payload(struct io_uring_recvmsg_out *o, 839 + struct msghdr *msgh) 840 + { 841 + return (void *)((unsigned char *)io_uring_recvmsg_name(o) + 842 + msgh->msg_namelen + msgh->msg_controllen); 843 + } 844 + 845 + static inline unsigned int 846 + io_uring_recvmsg_payload_length(struct io_uring_recvmsg_out *o, 847 + int buf_len, struct msghdr *msgh) 848 + { 849 + unsigned long payload_start, payload_end; 850 + 851 + payload_start = (unsigned long) io_uring_recvmsg_payload(o, msgh); 852 + payload_end = (unsigned long) o + buf_len; 853 + return (unsigned int) (payload_end - payload_start); 854 + } 855 + 675 856 static inline void io_uring_prep_openat2(struct io_uring_sqe *sqe, int dfd, 676 857 const char *path, struct open_how *how) 677 858 { ··· 735 916 736 917 static inline void io_uring_prep_renameat(struct io_uring_sqe *sqe, int olddfd, 737 918 const char *oldpath, int newdfd, 738 - const char *newpath, int flags) 919 + const char *newpath, unsigned int flags) 739 920 { 740 921 io_uring_prep_rw(IORING_OP_RENAMEAT, sqe, olddfd, oldpath, 741 922 (__u32) newdfd, ··· 808 989 809 990 static inline void io_uring_prep_getxattr(struct io_uring_sqe *sqe, 810 991 const char *name, 811 - const char *value, 992 + char *value, 812 993 const char *path, 813 - size_t len) 994 + unsigned int len) 814 995 { 815 996 io_uring_prep_rw(IORING_OP_GETXATTR, sqe, 0, name, len, 816 997 (__u64) (uintptr_t) value); ··· 823 1004 const char *value, 824 1005 const char *path, 825 1006 int flags, 826 - size_t len) 1007 + unsigned int len) 827 1008 { 828 1009 io_uring_prep_rw(IORING_OP_SETXATTR, sqe, 0, name, len, 829 1010 (__u64) (uintptr_t) value); ··· 832 1013 } 833 1014 834 1015 static inline void io_uring_prep_fgetxattr(struct io_uring_sqe *sqe, 835 - int fd, 1016 + int fd, 836 1017 const char *name, 837 - const char *value, 838 - size_t len) 1018 + char *value, 1019 + unsigned int len) 839 1020 { 840 1021 io_uring_prep_rw(IORING_OP_FGETXATTR, sqe, fd, name, len, 841 1022 (__u64) (uintptr_t) value); ··· 843 1024 } 844 1025 845 1026 static inline void io_uring_prep_fsetxattr(struct io_uring_sqe *sqe, 846 - int fd, 847 - const char *name, 848 - const char *value, 849 - int flags, 850 - size_t len) 1027 + int fd, 1028 + const char *name, 1029 + const char *value, 1030 + int flags, 1031 + unsigned int len) 851 1032 { 852 1033 io_uring_prep_rw(IORING_OP_FSETXATTR, sqe, fd, name, len, 853 1034 (__u64) (uintptr_t) value); ··· 907 1088 */ 908 1089 static inline unsigned io_uring_sq_space_left(const struct io_uring *ring) 909 1090 { 910 - return *ring->sq.kring_entries - io_uring_sq_ready(ring); 1091 + return ring->sq.ring_entries - io_uring_sq_ready(ring); 911 1092 } 912 1093 913 1094 /* ··· 936 1117 } 937 1118 938 1119 /* 1120 + * Returns true if there are overflow entries waiting to be flushed onto 1121 + * the CQ ring 1122 + */ 1123 + static inline bool io_uring_cq_has_overflow(const struct io_uring *ring) 1124 + { 1125 + return IO_URING_READ_ONCE(*ring->sq.kflags) & IORING_SQ_CQ_OVERFLOW; 1126 + } 1127 + 1128 + /* 939 1129 * Returns true if the eventfd notification is currently enabled 940 1130 */ 941 1131 static inline bool io_uring_cq_eventfd_enabled(const struct io_uring *ring) ··· 997 1187 struct io_uring_cqe *cqe; 998 1188 int err = 0; 999 1189 unsigned available; 1000 - unsigned mask = *ring->cq.kring_mask; 1190 + unsigned mask = ring->cq.ring_mask; 1001 1191 int shift = 0; 1002 1192 1003 1193 if (ring->flags & IORING_SETUP_CQE32) ··· 1068 1258 static inline struct io_uring_sqe *_io_uring_get_sqe(struct io_uring *ring) 1069 1259 { 1070 1260 struct io_uring_sq *sq = &ring->sq; 1071 - unsigned int head = io_uring_smp_load_acquire(sq->khead); 1072 - unsigned int next = sq->sqe_tail + 1; 1261 + unsigned int head, next = sq->sqe_tail + 1; 1073 1262 int shift = 0; 1074 1263 1075 1264 if (ring->flags & IORING_SETUP_SQE128) 1076 1265 shift = 1; 1266 + if (!(ring->flags & IORING_SETUP_SQPOLL)) 1267 + head = IO_URING_READ_ONCE(*sq->khead); 1268 + else 1269 + head = io_uring_smp_load_acquire(sq->khead); 1077 1270 1078 - if (next - head <= *sq->kring_entries) { 1271 + if (next - head <= sq->ring_entries) { 1079 1272 struct io_uring_sqe *sqe; 1080 1273 1081 - sqe = &sq->sqes[(sq->sqe_tail & *sq->kring_mask) << shift]; 1274 + sqe = &sq->sqes[(sq->sqe_tail & sq->ring_mask) << shift]; 1082 1275 sq->sqe_tail = next; 1083 1276 return sqe; 1084 1277 }
+132 -8
vendor/liburing/src/include/liburing/io_uring.h
··· 10 10 11 11 #include <linux/fs.h> 12 12 #include <linux/types.h> 13 + /* 14 + * this file is shared with liburing and that has to autodetect 15 + * if linux/time_types.h is available 16 + */ 17 + #ifdef __KERNEL__ 18 + #define HAVE_LINUX_TIME_TYPES_H 1 19 + #endif 20 + #ifdef HAVE_LINUX_TIME_TYPES_H 21 + #include <linux/time_types.h> 22 + #endif 13 23 14 24 #ifdef __cplusplus 15 25 extern "C" { ··· 26 36 union { 27 37 __u64 off; /* offset into file */ 28 38 __u64 addr2; 39 + struct { 40 + __u32 cmd_op; 41 + __u32 __pad1; 42 + }; 29 43 }; 30 44 union { 31 45 __u64 addr; /* pointer to buffer or iovecs */ ··· 50 64 __u32 unlink_flags; 51 65 __u32 hardlink_flags; 52 66 __u32 xattr_flags; 67 + __u32 msg_ring_flags; 68 + __u32 uring_cmd_flags; 53 69 }; 54 70 __u64 user_data; /* data to be passed back at completion time */ 55 71 /* pack this to avoid bogus arm OABI complaints */ ··· 64 80 union { 65 81 __s32 splice_fd_in; 66 82 __u32 file_index; 83 + struct { 84 + __u16 addr_len; 85 + __u16 __pad3[1]; 86 + }; 67 87 }; 68 - __u64 addr3; 69 - __u64 __pad2[1]; 88 + union { 89 + struct { 90 + __u64 addr3; 91 + __u64 __pad2[1]; 92 + }; 93 + /* 94 + * If the ring is initialized with IORING_SETUP_SQE128, then 95 + * this field is used for 80 bytes of arbitrary command data 96 + */ 97 + __u8 cmd[0]; 98 + }; 70 99 }; 71 100 72 101 /* ··· 131 160 * IORING_SQ_TASKRUN in the sq ring flags. Not valid with COOP_TASKRUN. 132 161 */ 133 162 #define IORING_SETUP_TASKRUN_FLAG (1U << 9) 134 - 135 163 #define IORING_SETUP_SQE128 (1U << 10) /* SQEs are 128 byte */ 136 164 #define IORING_SETUP_CQE32 (1U << 11) /* CQEs are 32 byte */ 165 + /* 166 + * Only one task is allowed to submit requests 167 + */ 168 + #define IORING_SETUP_SINGLE_ISSUER (1U << 12) 169 + 170 + /* 171 + * Defer running task work to get events. 172 + * Rather than running bits of task work whenever the task transitions 173 + * try to do it just before it is needed. 174 + */ 175 + #define IORING_SETUP_DEFER_TASKRUN (1U << 13) 137 176 138 177 enum io_uring_op { 139 178 IORING_OP_NOP, ··· 183 222 IORING_OP_GETXATTR, 184 223 IORING_OP_SOCKET, 185 224 IORING_OP_URING_CMD, 225 + IORING_OP_SEND_ZC, 226 + IORING_OP_SENDMSG_ZC, 186 227 187 228 /* this goes last, obviously */ 188 229 IORING_OP_LAST, 189 230 }; 190 231 191 232 /* 233 + * sqe->uring_cmd_flags 234 + * IORING_URING_CMD_FIXED use registered buffer; pass thig flag 235 + * along with setting sqe->buf_index. 236 + */ 237 + #define IORING_URING_CMD_FIXED (1U << 0) 238 + 239 + 240 + /* 192 241 * sqe->fsync_flags 193 242 */ 194 243 #define IORING_FSYNC_DATASYNC (1U << 0) ··· 220 269 * 221 270 * IORING_POLL_UPDATE Update existing poll request, matching 222 271 * sqe->addr as the old user_data field. 272 + * 273 + * IORING_POLL_LEVEL Level triggered poll. 223 274 */ 224 275 #define IORING_POLL_ADD_MULTI (1U << 0) 225 276 #define IORING_POLL_UPDATE_EVENTS (1U << 1) 226 277 #define IORING_POLL_UPDATE_USER_DATA (1U << 2) 278 + #define IORING_POLL_ADD_LEVEL (1U << 3) 227 279 228 280 /* 229 281 * ASYNC_CANCEL flags. ··· 232 284 * IORING_ASYNC_CANCEL_FD Key off 'fd' for cancelation rather than the 233 285 * request 'user_data' 234 286 * IORING_ASYNC_CANCEL_ANY Match any request 287 + * IORING_ASYNC_CANCEL_FD_FIXED 'fd' passed in is a fixed descriptor 235 288 */ 236 289 #define IORING_ASYNC_CANCEL_ALL (1U << 0) 237 290 #define IORING_ASYNC_CANCEL_FD (1U << 1) 238 - #define IORING_ASYNC_CANCEL_ANY (1U << 2) 291 + #define IORING_ASYNC_CANCEL_ANY (1U << 2) 292 + #define IORING_ASYNC_CANCEL_FD_FIXED (1U << 3) 239 293 240 294 /* 241 - * send/sendmsg and recv/recvmsg flags (sqe->addr2) 295 + * send/sendmsg and recv/recvmsg flags (sqe->ioprio) 242 296 * 243 297 * IORING_RECVSEND_POLL_FIRST If set, instead of first attempting to send 244 298 * or receive and arm poll if that yields an 245 299 * -EAGAIN result, arm poll upfront and skip 246 300 * the initial transfer attempt. 301 + * 302 + * IORING_RECV_MULTISHOT Multishot recv. Sets IORING_CQE_F_MORE if 303 + * the handler will continue to report 304 + * CQEs on behalf of the same SQE. 305 + * 306 + * IORING_RECVSEND_FIXED_BUF Use registered buffers, the index is stored in 307 + * the buf_index field. 247 308 */ 248 309 #define IORING_RECVSEND_POLL_FIRST (1U << 0) 310 + #define IORING_RECV_MULTISHOT (1U << 1) 311 + #define IORING_RECVSEND_FIXED_BUF (1U << 2) 249 312 250 313 /* 251 314 * accept flags stored in sqe->ioprio ··· 253 316 #define IORING_ACCEPT_MULTISHOT (1U << 0) 254 317 255 318 /* 319 + * IORING_OP_MSG_RING command types, stored in sqe->addr 320 + */ 321 + enum { 322 + IORING_MSG_DATA, /* pass sqe->len as 'res' and off as user_data */ 323 + IORING_MSG_SEND_FD, /* send a registered fd to another ring */ 324 + }; 325 + 326 + /* 327 + * IORING_OP_MSG_RING flags (sqe->msg_ring_flags) 328 + * 329 + * IORING_MSG_RING_CQE_SKIP Don't post a CQE to the target ring. Not 330 + * applicable for IORING_MSG_DATA, obviously. 331 + */ 332 + #define IORING_MSG_RING_CQE_SKIP (1U << 0) 333 + 334 + /* 256 335 * IO completion data structure (Completion Queue Entry) 257 336 */ 258 337 struct io_uring_cqe { ··· 273 352 * IORING_CQE_F_BUFFER If set, the upper 16 bits are the buffer ID 274 353 * IORING_CQE_F_MORE If set, parent SQE will generate more CQE entries 275 354 * IORING_CQE_F_SOCK_NONEMPTY If set, more data to read after socket recv 355 + * IORING_CQE_F_NOTIF Set for notification CQEs. Can be used to distinct 356 + * them from sends. 276 357 */ 277 358 #define IORING_CQE_F_BUFFER (1U << 0) 278 359 #define IORING_CQE_F_MORE (1U << 1) 279 360 #define IORING_CQE_F_SOCK_NONEMPTY (1U << 2) 361 + #define IORING_CQE_F_NOTIF (1U << 3) 280 362 281 363 enum { 282 364 IORING_CQE_BUFFER_SHIFT = 16, ··· 411 493 IORING_REGISTER_PBUF_RING = 22, 412 494 IORING_UNREGISTER_PBUF_RING = 23, 413 495 496 + /* sync cancelation API */ 497 + IORING_REGISTER_SYNC_CANCEL = 24, 498 + 499 + /* register a range of fixed file slots for automatic slot allocation */ 500 + IORING_REGISTER_FILE_ALLOC_RANGE = 25, 501 + 414 502 /* this goes last */ 415 503 IORING_REGISTER_LAST 416 504 }; ··· 457 545 __u32 resv2; 458 546 }; 459 547 548 + struct io_uring_notification_slot { 549 + __u64 tag; 550 + __u64 resv[3]; 551 + }; 552 + 553 + struct io_uring_notification_register { 554 + __u32 nr_slots; 555 + __u32 resv; 556 + __u64 resv2; 557 + __u64 data; 558 + __u64 resv3; 559 + }; 560 + 460 561 /* Skip updating fd indexes set to this value in the fd table */ 461 562 #define IORING_REGISTER_FILES_SKIP (-2) 462 563 ··· 474 575 __u8 ops_len; /* length of ops[] array below */ 475 576 __u16 resv; 476 577 __u32 resv2[3]; 477 - struct io_uring_probe_op ops[0]; 578 + struct io_uring_probe_op ops[]; 478 579 }; 479 580 480 581 struct io_uring_restriction { ··· 547 648 }; 548 649 549 650 /* 550 - * accept flags stored in sqe->ioprio 651 + * Argument for IORING_REGISTER_SYNC_CANCEL 652 + */ 653 + struct io_uring_sync_cancel_reg { 654 + __u64 addr; 655 + __s32 fd; 656 + __u32 flags; 657 + struct __kernel_timespec timeout; 658 + __u64 pad[4]; 659 + }; 660 + 661 + /* 662 + * Argument for IORING_REGISTER_FILE_ALLOC_RANGE 663 + * The range is specified as [off, off + len) 551 664 */ 552 - #define IORING_ACCEPT_MULTISHOT (1U << 0) 665 + struct io_uring_file_index_range { 666 + __u32 off; 667 + __u32 len; 668 + __u64 resv; 669 + }; 670 + 671 + struct io_uring_recvmsg_out { 672 + __u32 namelen; 673 + __u32 controllen; 674 + __u32 payloadlen; 675 + __u32 flags; 676 + }; 553 677 554 678 #ifdef __cplusplus 555 679 }
+20 -16
vendor/liburing/src/lib.h
··· 6 6 #include <string.h> 7 7 #include <unistd.h> 8 8 9 - #define __INTERNAL__LIBURING_LIB_H 10 9 #if defined(__x86_64__) || defined(__i386__) 11 - #include "arch/x86/lib.h" 10 + #include "arch/x86/lib.h" 11 + #elif defined(__aarch64__) 12 + #include "arch/aarch64/lib.h" 12 13 #else 13 - /* 14 - * We don't have nolibc support for this arch. Must use libc! 15 - */ 16 - #ifdef CONFIG_NOLIBC 17 - #error "This arch doesn't support building liburing without libc" 18 - #endif 19 - /* libc wrappers. */ 20 - #include "arch/generic/lib.h" 14 + /* 15 + * We don't have nolibc support for this arch. Must use libc! 16 + */ 17 + #ifdef CONFIG_NOLIBC 18 + #error "This arch doesn't support building liburing without libc" 21 19 #endif 22 - #undef __INTERNAL__LIBURING_LIB_H 20 + /* libc wrappers. */ 21 + #include "arch/generic/lib.h" 22 + #endif 23 23 24 24 25 25 #ifndef offsetof 26 - #define offsetof(TYPE, FIELD) ((size_t) &((TYPE *)0)->FIELD) 26 + #define offsetof(TYPE, FIELD) ((size_t) &((TYPE *)0)->FIELD) 27 27 #endif 28 28 29 29 #ifndef container_of 30 - #define container_of(PTR, TYPE, FIELD) ({ \ 31 - __typeof__(((TYPE *)0)->FIELD) *__FIELD_PTR = (PTR); \ 32 - (TYPE *)((char *) __FIELD_PTR - offsetof(TYPE, FIELD)); \ 33 - }) 30 + #define container_of(PTR, TYPE, FIELD) ({ \ 31 + __typeof__(((TYPE *)0)->FIELD) *__FIELD_PTR = (PTR); \ 32 + (TYPE *)((char *) __FIELD_PTR - offsetof(TYPE, FIELD)); \ 33 + }) 34 34 #endif 35 + 36 + #define __maybe_unused __attribute__((__unused__)) 37 + #define __hot __attribute__((__hot__)) 38 + #define __cold __attribute__((__cold__)) 35 39 36 40 void *__uring_malloc(size_t len); 37 41 void __uring_free(void *p);
+12
vendor/liburing/src/liburing.map
··· 55 55 io_uring_register_buf_ring; 56 56 io_uring_unregister_buf_ring; 57 57 } LIBURING_2.1; 58 + 59 + LIBURING_2.3 { 60 + global: 61 + io_uring_register_sync_cancel; 62 + io_uring_register_file_alloc_range; 63 + io_uring_enter; 64 + io_uring_enter2; 65 + io_uring_setup; 66 + io_uring_register; 67 + io_uring_get_events; 68 + io_uring_submit_and_get_events; 69 + } LIBURING_2.2;
+73 -49
vendor/liburing/src/queue.c
··· 12 12 * Returns true if we're not using SQ thread (thus nobody submits but us) 13 13 * or if IORING_SQ_NEED_WAKEUP is set, so submit thread must be explicitly 14 14 * awakened. For the latter case, we set the thread wakeup flag. 15 + * If no SQEs are ready for submission, returns false. 15 16 */ 16 - static inline bool sq_ring_needs_enter(struct io_uring *ring, unsigned *flags) 17 + static inline bool sq_ring_needs_enter(struct io_uring *ring, 18 + unsigned submit, 19 + unsigned *flags) 17 20 { 21 + if (!submit) 22 + return false; 23 + 18 24 if (!(ring->flags & IORING_SETUP_SQPOLL)) 19 25 return true; 20 26 ··· 49 55 unsigned wait_nr; 50 56 unsigned get_flags; 51 57 int sz; 58 + int has_ts; 52 59 void *arg; 53 60 }; 54 61 ··· 58 65 { 59 66 struct io_uring_cqe *cqe = NULL; 60 67 bool looped = false; 61 - int err; 68 + int err = 0; 62 69 63 70 do { 64 71 bool need_enter = false; ··· 66 73 unsigned nr_available; 67 74 int ret; 68 75 69 - err = __io_uring_peek_cqe(ring, &cqe, &nr_available); 70 - if (err) 76 + ret = __io_uring_peek_cqe(ring, &cqe, &nr_available); 77 + if (ret) { 78 + if (!err) 79 + err = ret; 71 80 break; 81 + } 72 82 if (!cqe && !data->wait_nr && !data->submit) { 73 83 /* 74 84 * If we already looped once, we already entererd ··· 76 86 * wait for, don't keep retrying. 77 87 */ 78 88 if (looped || !cq_ring_needs_enter(ring)) { 79 - err = -EAGAIN; 89 + if (!err) 90 + err = -EAGAIN; 80 91 break; 81 92 } 82 93 need_enter = true; ··· 85 96 flags = IORING_ENTER_GETEVENTS | data->get_flags; 86 97 need_enter = true; 87 98 } 88 - if (data->submit && sq_ring_needs_enter(ring, &flags)) 99 + if (sq_ring_needs_enter(ring, data->submit, &flags)) 89 100 need_enter = true; 90 101 if (!need_enter) 91 102 break; 103 + if (looped && data->has_ts) { 104 + struct io_uring_getevents_arg *arg = data->arg; 105 + 106 + if (!cqe && arg->ts && !err) 107 + err = -ETIME; 108 + break; 109 + } 92 110 93 111 if (ring->int_flags & INT_FLAG_REG_RING) 94 112 flags |= IORING_ENTER_REGISTERED_RING; 95 - ret = ____sys_io_uring_enter2(ring->enter_ring_fd, data->submit, 96 - data->wait_nr, flags, data->arg, 97 - data->sz); 113 + ret = __sys_io_uring_enter2(ring->enter_ring_fd, data->submit, 114 + data->wait_nr, flags, data->arg, 115 + data->sz); 98 116 if (ret < 0) { 99 - err = ret; 117 + if (!err) 118 + err = ret; 100 119 break; 101 120 } 102 121 103 122 data->submit -= ret; 104 123 if (cqe) 105 124 break; 106 - looped = true; 125 + if (!looped) { 126 + looped = true; 127 + err = ret; 128 + } 107 129 } while (1); 108 130 109 131 *cqe_ptr = cqe; ··· 124 146 return _io_uring_get_cqe(ring, cqe_ptr, &data); 125 147 } 126 148 149 + int io_uring_get_events(struct io_uring *ring) 150 + { 151 + int flags = IORING_ENTER_GETEVENTS; 152 + 153 + if (ring->int_flags & INT_FLAG_REG_RING) 154 + flags |= IORING_ENTER_REGISTERED_RING; 155 + return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL); 156 + } 157 + 127 158 /* 128 159 * Fill in an array of IO completions up to count, if any are available. 129 160 * Returns the amount of IO completions filled. ··· 142 173 ready = io_uring_cq_ready(ring); 143 174 if (ready) { 144 175 unsigned head = *ring->cq.khead; 145 - unsigned mask = *ring->cq.kring_mask; 176 + unsigned mask = ring->cq.ring_mask; 146 177 unsigned last; 147 178 int i = 0; 148 179 ··· 155 186 } 156 187 157 188 if (overflow_checked) 158 - goto done; 189 + return 0; 159 190 160 191 if (cq_ring_needs_flush(ring)) { 161 - int flags = IORING_ENTER_GETEVENTS; 162 - 163 - if (ring->int_flags & INT_FLAG_REG_RING) 164 - flags |= IORING_ENTER_REGISTERED_RING; 165 - ____sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL); 192 + io_uring_get_events(ring); 166 193 overflow_checked = true; 167 194 goto again; 168 195 } 169 196 170 - done: 171 197 return 0; 172 198 } 173 199 ··· 175 201 * Sync internal state with kernel ring state on the SQ side. Returns the 176 202 * number of pending items in the SQ ring, for the shared ring. 177 203 */ 178 - int __io_uring_flush_sq(struct io_uring *ring) 204 + unsigned __io_uring_flush_sq(struct io_uring *ring) 179 205 { 180 206 struct io_uring_sq *sq = &ring->sq; 181 - const unsigned mask = *sq->kring_mask; 182 - unsigned ktail = *sq->ktail; 183 - unsigned to_submit = sq->sqe_tail - sq->sqe_head; 207 + unsigned tail = sq->sqe_tail; 184 208 185 - if (!to_submit) 186 - goto out; 187 - 188 - /* 189 - * Fill in sqes that we have queued up, adding them to the kernel ring 190 - */ 191 - do { 192 - sq->array[ktail & mask] = sq->sqe_head & mask; 193 - ktail++; 194 - sq->sqe_head++; 195 - } while (--to_submit); 196 - 197 - /* 198 - * Ensure that the kernel sees the SQE updates before it sees the tail 199 - * update. 200 - */ 201 - io_uring_smp_store_release(sq->ktail, ktail); 202 - out: 209 + if (sq->sqe_head != tail) { 210 + sq->sqe_head = tail; 211 + /* 212 + * Ensure kernel sees the SQE updates before the tail update. 213 + */ 214 + if (!(ring->flags & IORING_SETUP_SQPOLL)) 215 + IO_URING_WRITE_ONCE(*sq->ktail, tail); 216 + else 217 + io_uring_smp_store_release(sq->ktail, tail); 218 + } 203 219 /* 204 220 * This _may_ look problematic, as we're not supposed to be reading 205 221 * SQ->head without acquire semantics. When we're in SQPOLL mode, the ··· 211 227 * we can submit. The point is, we need to be able to deal with this 212 228 * situation regardless of any perceived atomicity. 213 229 */ 214 - return ktail - *sq->khead; 230 + return tail - *sq->khead; 215 231 } 216 232 217 233 /* ··· 233 249 .wait_nr = wait_nr, 234 250 .get_flags = IORING_ENTER_EXT_ARG, 235 251 .sz = sizeof(arg), 252 + .has_ts = ts != NULL, 236 253 .arg = &arg 237 254 }; 238 255 ··· 317 334 .wait_nr = wait_nr, 318 335 .get_flags = IORING_ENTER_EXT_ARG, 319 336 .sz = sizeof(arg), 337 + .has_ts = ts != NULL, 320 338 .arg = &arg 321 339 }; 322 340 ··· 348 366 * Returns number of sqes submitted 349 367 */ 350 368 static int __io_uring_submit(struct io_uring *ring, unsigned submitted, 351 - unsigned wait_nr) 369 + unsigned wait_nr, bool getevents) 352 370 { 371 + bool cq_needs_enter = getevents || wait_nr || cq_ring_needs_enter(ring); 353 372 unsigned flags; 354 373 int ret; 355 374 356 375 flags = 0; 357 - if (sq_ring_needs_enter(ring, &flags) || wait_nr) { 358 - if (wait_nr || (ring->flags & IORING_SETUP_IOPOLL)) 376 + if (sq_ring_needs_enter(ring, submitted, &flags) || cq_needs_enter) { 377 + if (cq_needs_enter) 359 378 flags |= IORING_ENTER_GETEVENTS; 360 379 if (ring->int_flags & INT_FLAG_REG_RING) 361 380 flags |= IORING_ENTER_REGISTERED_RING; 362 381 363 - ret = ____sys_io_uring_enter(ring->enter_ring_fd, submitted, 364 - wait_nr, flags, NULL); 382 + ret = __sys_io_uring_enter(ring->enter_ring_fd, submitted, 383 + wait_nr, flags, NULL); 365 384 } else 366 385 ret = submitted; 367 386 ··· 370 389 371 390 static int __io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr) 372 391 { 373 - return __io_uring_submit(ring, __io_uring_flush_sq(ring), wait_nr); 392 + return __io_uring_submit(ring, __io_uring_flush_sq(ring), wait_nr, false); 374 393 } 375 394 376 395 /* ··· 393 412 return __io_uring_submit_and_wait(ring, wait_nr); 394 413 } 395 414 415 + int io_uring_submit_and_get_events(struct io_uring *ring) 416 + { 417 + return __io_uring_submit(ring, __io_uring_flush_sq(ring), 0, true); 418 + } 419 + 396 420 #ifdef LIBURING_INTERNAL 397 421 struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) 398 422 { ··· 407 431 if (ring->int_flags & INT_FLAG_REG_RING) 408 432 flags |= IORING_ENTER_REGISTERED_RING; 409 433 410 - return ____sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL); 434 + return __sys_io_uring_enter(ring->enter_ring_fd, 0, 0, flags, NULL); 411 435 }
+87 -65
vendor/liburing/src/register.c
··· 20 20 .nr = nr, 21 21 }; 22 22 23 - return ____sys_io_uring_register(ring->ring_fd, 24 - IORING_REGISTER_BUFFERS_UPDATE, &up, 23 + return __sys_io_uring_register(ring->ring_fd,IORING_REGISTER_BUFFERS_UPDATE, &up, 25 24 sizeof(up)); 26 25 } 27 26 ··· 36 35 .tags = (unsigned long)tags, 37 36 }; 38 37 39 - return ____sys_io_uring_register(ring->ring_fd, 40 - IORING_REGISTER_BUFFERS2, &reg, 41 - sizeof(reg)); 38 + return __sys_io_uring_register(ring->ring_fd, 39 + IORING_REGISTER_BUFFERS2, &reg, 40 + sizeof(reg)); 42 41 } 43 42 44 43 int io_uring_register_buffers_sparse(struct io_uring *ring, unsigned nr) ··· 48 47 .nr = nr, 49 48 }; 50 49 51 - return ____sys_io_uring_register(ring->ring_fd, 52 - IORING_REGISTER_BUFFERS2, &reg, 53 - sizeof(reg)); 50 + return __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS2, 51 + &reg, sizeof(reg)); 54 52 } 55 53 56 54 int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, ··· 58 56 { 59 57 int ret; 60 58 61 - ret = ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS, 62 - iovecs, nr_iovecs); 59 + ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_BUFFERS, 60 + iovecs, nr_iovecs); 63 61 return (ret < 0) ? ret : 0; 64 62 } 65 63 ··· 67 65 { 68 66 int ret; 69 67 70 - ret = ____sys_io_uring_register(ring->ring_fd, 71 - IORING_UNREGISTER_BUFFERS, NULL, 0); 68 + ret = __sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_BUFFERS, 69 + NULL, 0); 72 70 return (ret < 0) ? ret : 0; 73 71 } 74 72 ··· 83 81 .nr = nr_files, 84 82 }; 85 83 86 - return ____sys_io_uring_register(ring->ring_fd, 87 - IORING_REGISTER_FILES_UPDATE2, &up, 88 - sizeof(up)); 84 + return __sys_io_uring_register(ring->ring_fd, 85 + IORING_REGISTER_FILES_UPDATE2, &up, 86 + sizeof(up)); 89 87 } 90 88 91 89 /* ··· 96 94 * Returns number of files updated on success, -ERROR on failure. 97 95 */ 98 96 int io_uring_register_files_update(struct io_uring *ring, unsigned off, 99 - int *files, unsigned nr_files) 97 + const int *files, unsigned nr_files) 100 98 { 101 99 struct io_uring_files_update up = { 102 100 .offset = off, 103 101 .fds = (unsigned long) files, 104 102 }; 105 103 106 - return ____sys_io_uring_register(ring->ring_fd, 107 - IORING_REGISTER_FILES_UPDATE, &up, 108 - nr_files); 104 + return __sys_io_uring_register(ring->ring_fd, 105 + IORING_REGISTER_FILES_UPDATE, &up, 106 + nr_files); 109 107 } 110 108 111 109 static int increase_rlimit_nofile(unsigned nr) ··· 134 132 int ret, did_increase = 0; 135 133 136 134 do { 137 - ret = ____sys_io_uring_register(ring->ring_fd, 138 - IORING_REGISTER_FILES2, &reg, 139 - sizeof(reg)); 135 + ret = __sys_io_uring_register(ring->ring_fd, 136 + IORING_REGISTER_FILES2, &reg, 137 + sizeof(reg)); 140 138 if (ret >= 0) 141 139 break; 142 140 if (ret == -EMFILE && !did_increase) { ··· 161 159 int ret, did_increase = 0; 162 160 163 161 do { 164 - ret = ____sys_io_uring_register(ring->ring_fd, 165 - IORING_REGISTER_FILES2, &reg, 166 - sizeof(reg)); 162 + ret = __sys_io_uring_register(ring->ring_fd, 163 + IORING_REGISTER_FILES2, &reg, 164 + sizeof(reg)); 167 165 if (ret >= 0) 168 166 break; 169 167 if (ret == -EMFILE && !did_increase) { ··· 183 181 int ret, did_increase = 0; 184 182 185 183 do { 186 - ret = ____sys_io_uring_register(ring->ring_fd, 187 - IORING_REGISTER_FILES, files, 188 - nr_files); 184 + ret = __sys_io_uring_register(ring->ring_fd, 185 + IORING_REGISTER_FILES, files, 186 + nr_files); 189 187 if (ret >= 0) 190 188 break; 191 189 if (ret == -EMFILE && !did_increase) { ··· 203 201 { 204 202 int ret; 205 203 206 - ret = ____sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, 207 - NULL, 0); 204 + ret = __sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_FILES, 205 + NULL, 0); 208 206 return (ret < 0) ? ret : 0; 209 207 } 210 208 ··· 212 210 { 213 211 int ret; 214 212 215 - ret = ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_EVENTFD, 216 - &event_fd, 1); 213 + ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_EVENTFD, 214 + &event_fd, 1); 217 215 return (ret < 0) ? ret : 0; 218 216 } 219 217 ··· 221 219 { 222 220 int ret; 223 221 224 - ret = ____sys_io_uring_register(ring->ring_fd, 225 - IORING_UNREGISTER_EVENTFD, NULL, 0); 222 + ret = __sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_EVENTFD, 223 + NULL, 0); 226 224 return (ret < 0) ? ret : 0; 227 225 } 228 226 ··· 230 228 { 231 229 int ret; 232 230 233 - ret = ____sys_io_uring_register(ring->ring_fd, 234 - IORING_REGISTER_EVENTFD_ASYNC, 235 - &event_fd, 1); 231 + ret = __sys_io_uring_register(ring->ring_fd, 232 + IORING_REGISTER_EVENTFD_ASYNC, &event_fd, 233 + 1); 236 234 return (ret < 0) ? ret : 0; 237 235 } 238 236 ··· 241 239 { 242 240 int ret; 243 241 244 - ret = ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_PROBE, p, 245 - nr_ops); 242 + ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_PROBE, p, 243 + nr_ops); 246 244 return (ret < 0) ? ret : 0; 247 245 } 248 246 249 247 int io_uring_register_personality(struct io_uring *ring) 250 248 { 251 - return ____sys_io_uring_register(ring->ring_fd, 252 - IORING_REGISTER_PERSONALITY, NULL, 0); 249 + return __sys_io_uring_register(ring->ring_fd, 250 + IORING_REGISTER_PERSONALITY, NULL, 0); 253 251 } 254 252 255 253 int io_uring_unregister_personality(struct io_uring *ring, int id) 256 254 { 257 - return ____sys_io_uring_register(ring->ring_fd, 258 - IORING_UNREGISTER_PERSONALITY, NULL, 259 - id); 255 + return __sys_io_uring_register(ring->ring_fd, 256 + IORING_UNREGISTER_PERSONALITY, NULL, id); 260 257 } 261 258 262 259 int io_uring_register_restrictions(struct io_uring *ring, ··· 265 262 { 266 263 int ret; 267 264 268 - ret = ____sys_io_uring_register(ring->ring_fd, 269 - IORING_REGISTER_RESTRICTIONS, res, 270 - nr_res); 265 + ret = __sys_io_uring_register(ring->ring_fd, 266 + IORING_REGISTER_RESTRICTIONS, res, 267 + nr_res); 271 268 return (ret < 0) ? ret : 0; 272 269 } 273 270 274 271 int io_uring_enable_rings(struct io_uring *ring) 275 272 { 276 - return ____sys_io_uring_register(ring->ring_fd, 277 - IORING_REGISTER_ENABLE_RINGS, NULL, 0); 273 + return __sys_io_uring_register(ring->ring_fd, 274 + IORING_REGISTER_ENABLE_RINGS, NULL, 0); 278 275 } 279 276 280 277 int io_uring_register_iowq_aff(struct io_uring *ring, size_t cpusz, 281 278 const cpu_set_t *mask) 282 279 { 283 - return ____sys_io_uring_register(ring->ring_fd, 284 - IORING_REGISTER_IOWQ_AFF, mask, cpusz); 280 + if (cpusz >= (1U << 31)) 281 + return -EINVAL; 282 + 283 + return __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_IOWQ_AFF, 284 + mask, (int) cpusz); 285 285 } 286 286 287 287 int io_uring_unregister_iowq_aff(struct io_uring *ring) 288 288 { 289 - return ____sys_io_uring_register(ring->ring_fd, 290 - IORING_UNREGISTER_IOWQ_AFF, NULL, 0); 289 + return __sys_io_uring_register(ring->ring_fd, 290 + IORING_UNREGISTER_IOWQ_AFF, NULL, 0); 291 291 } 292 292 293 293 int io_uring_register_iowq_max_workers(struct io_uring *ring, unsigned int *val) 294 294 { 295 - return ____sys_io_uring_register(ring->ring_fd, 296 - IORING_REGISTER_IOWQ_MAX_WORKERS, val, 297 - 2); 295 + return __sys_io_uring_register(ring->ring_fd, 296 + IORING_REGISTER_IOWQ_MAX_WORKERS, val, 297 + 2); 298 298 } 299 299 300 300 int io_uring_register_ring_fd(struct io_uring *ring) ··· 305 305 }; 306 306 int ret; 307 307 308 - ret = ____sys_io_uring_register(ring->ring_fd, IORING_REGISTER_RING_FDS, 309 - &up, 1); 308 + ret = __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_RING_FDS, 309 + &up, 1); 310 310 if (ret == 1) { 311 311 ring->enter_ring_fd = up.offset; 312 312 ring->int_flags |= INT_FLAG_REG_RING; ··· 322 322 }; 323 323 int ret; 324 324 325 - ret = ____sys_io_uring_register(ring->ring_fd, 326 - IORING_UNREGISTER_RING_FDS, &up, 1); 325 + ret = __sys_io_uring_register(ring->ring_fd, IORING_UNREGISTER_RING_FDS, 326 + &up, 1); 327 327 if (ret == 1) { 328 328 ring->enter_ring_fd = ring->ring_fd; 329 329 ring->int_flags &= ~INT_FLAG_REG_RING; ··· 332 332 } 333 333 334 334 int io_uring_register_buf_ring(struct io_uring *ring, 335 - struct io_uring_buf_reg *reg, unsigned int flags) 335 + struct io_uring_buf_reg *reg, 336 + unsigned int __maybe_unused flags) 336 337 { 337 - return ____sys_io_uring_register(ring->ring_fd, 338 - IORING_REGISTER_PBUF_RING, reg, 1); 338 + return __sys_io_uring_register(ring->ring_fd, IORING_REGISTER_PBUF_RING, 339 + reg, 1); 339 340 } 340 341 341 342 int io_uring_unregister_buf_ring(struct io_uring *ring, int bgid) 342 343 { 343 344 struct io_uring_buf_reg reg = { .bgid = bgid }; 344 345 345 - return ____sys_io_uring_register(ring->ring_fd, 346 - IORING_UNREGISTER_PBUF_RING, &reg, 1); 346 + return __sys_io_uring_register(ring->ring_fd, 347 + IORING_UNREGISTER_PBUF_RING, &reg, 1); 348 + } 349 + 350 + int io_uring_register_sync_cancel(struct io_uring *ring, 351 + struct io_uring_sync_cancel_reg *reg) 352 + { 353 + return __sys_io_uring_register(ring->ring_fd, 354 + IORING_REGISTER_SYNC_CANCEL, reg, 1); 355 + } 356 + 357 + int io_uring_register_file_alloc_range(struct io_uring *ring, 358 + unsigned off, unsigned len) 359 + { 360 + struct io_uring_file_index_range range; 361 + 362 + memset(&range, 0, sizeof(range)); 363 + range.off = off; 364 + range.len = len; 365 + 366 + return __sys_io_uring_register(ring->ring_fd, 367 + IORING_REGISTER_FILE_ALLOC_RANGE, &range, 368 + 0); 347 369 }
+38 -20
vendor/liburing/src/setup.c
··· 80 80 cq->cqes = cq->ring_ptr + p->cq_off.cqes; 81 81 if (p->cq_off.flags) 82 82 cq->kflags = cq->ring_ptr + p->cq_off.flags; 83 + 84 + sq->ring_mask = *sq->kring_mask; 85 + sq->ring_entries = *sq->kring_entries; 86 + cq->ring_mask = *cq->kring_mask; 87 + cq->ring_entries = *cq->kring_entries; 83 88 return 0; 84 89 } 85 90 ··· 89 94 * Returns -errno on error, or zero on success. On success, 'ring' 90 95 * contains the necessary information to read/write to the rings. 91 96 */ 92 - int io_uring_queue_mmap(int fd, struct io_uring_params *p, struct io_uring *ring) 97 + __cold int io_uring_queue_mmap(int fd, struct io_uring_params *p, 98 + struct io_uring *ring) 93 99 { 94 100 int ret; 95 101 ··· 107 113 * Ensure that the mmap'ed rings aren't available to a child after a fork(2). 108 114 * This uses madvise(..., MADV_DONTFORK) on the mmap'ed ranges. 109 115 */ 110 - int io_uring_ring_dontfork(struct io_uring *ring) 116 + __cold int io_uring_ring_dontfork(struct io_uring *ring) 111 117 { 112 118 size_t len; 113 119 int ret; ··· 118 124 len = sizeof(struct io_uring_sqe); 119 125 if (ring->flags & IORING_SETUP_SQE128) 120 126 len += 64; 121 - len *= *ring->sq.kring_entries; 127 + len *= ring->sq.ring_entries; 122 128 ret = __sys_madvise(ring->sq.sqes, len, MADV_DONTFORK); 123 129 if (ret < 0) 124 130 return ret; ··· 138 144 return 0; 139 145 } 140 146 141 - int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, 142 - struct io_uring_params *p) 147 + __cold int io_uring_queue_init_params(unsigned entries, struct io_uring *ring, 148 + struct io_uring_params *p) 143 149 { 144 150 int fd, ret; 151 + unsigned *sq_array; 152 + unsigned sq_entries, index; 145 153 146 - fd = ____sys_io_uring_setup(entries, p); 154 + fd = __sys_io_uring_setup(entries, p); 147 155 if (fd < 0) 148 156 return fd; 149 157 ··· 153 161 return ret; 154 162 } 155 163 164 + /* 165 + * Directly map SQ slots to SQEs 166 + */ 167 + sq_array = ring->sq.array; 168 + sq_entries = ring->sq.ring_entries; 169 + for (index = 0; index < sq_entries; index++) 170 + sq_array[index] = index; 171 + 156 172 ring->features = p->features; 157 173 return 0; 158 174 } ··· 161 177 * Returns -errno on error, or zero on success. On success, 'ring' 162 178 * contains the necessary information to read/write to the rings. 163 179 */ 164 - int io_uring_queue_init(unsigned entries, struct io_uring *ring, unsigned flags) 180 + __cold int io_uring_queue_init(unsigned entries, struct io_uring *ring, 181 + unsigned flags) 165 182 { 166 183 struct io_uring_params p; 167 184 ··· 171 188 return io_uring_queue_init_params(entries, ring, &p); 172 189 } 173 190 174 - void io_uring_queue_exit(struct io_uring *ring) 191 + __cold void io_uring_queue_exit(struct io_uring *ring) 175 192 { 176 193 struct io_uring_sq *sq = &ring->sq; 177 194 struct io_uring_cq *cq = &ring->cq; ··· 180 197 sqe_size = sizeof(struct io_uring_sqe); 181 198 if (ring->flags & IORING_SETUP_SQE128) 182 199 sqe_size += 64; 183 - __sys_munmap(sq->sqes, sqe_size * *sq->kring_entries); 200 + __sys_munmap(sq->sqes, sqe_size * sq->ring_entries); 184 201 io_uring_unmap_rings(sq, cq); 185 202 /* 186 203 * Not strictly required, but frees up the slot we used now rather ··· 191 208 __sys_close(ring->ring_fd); 192 209 } 193 210 194 - struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring) 211 + __cold struct io_uring_probe *io_uring_get_probe_ring(struct io_uring *ring) 195 212 { 196 213 struct io_uring_probe *probe; 197 214 size_t len; ··· 211 228 return NULL; 212 229 } 213 230 214 - struct io_uring_probe *io_uring_get_probe(void) 231 + __cold struct io_uring_probe *io_uring_get_probe(void) 215 232 { 216 233 struct io_uring ring; 217 234 struct io_uring_probe *probe; ··· 226 243 return probe; 227 244 } 228 245 229 - void io_uring_free_probe(struct io_uring_probe *probe) 246 + __cold void io_uring_free_probe(struct io_uring_probe *probe) 230 247 { 231 248 uring_free(probe); 232 249 } 233 250 234 - static inline int __fls(int x) 251 + static inline int __fls(unsigned long x) 235 252 { 236 253 if (!x) 237 254 return 0; 238 - return 8 * sizeof(x) - __builtin_clz(x); 255 + return 8 * sizeof(x) - __builtin_clzl(x); 239 256 } 240 257 241 258 static unsigned roundup_pow2(unsigned depth) 242 259 { 243 - return 1UL << __fls(depth - 1); 260 + return 1U << __fls(depth - 1); 244 261 } 245 262 246 - static size_t npages(size_t size, unsigned page_size) 263 + static size_t npages(size_t size, long page_size) 247 264 { 248 265 size--; 249 266 size /= page_size; 250 - return __fls(size); 267 + return __fls((int) size); 251 268 } 252 269 253 270 #define KRING_SIZE 320 254 271 255 272 static size_t rings_size(struct io_uring_params *p, unsigned entries, 256 - unsigned cq_entries, unsigned page_size) 273 + unsigned cq_entries, long page_size) 257 274 { 258 275 size_t pages, sq_size, cq_size; 259 276 ··· 284 301 * return the required memory so that the caller can ensure that enough space 285 302 * is available before setting up a ring with the specified parameters. 286 303 */ 287 - ssize_t io_uring_mlock_size_params(unsigned entries, struct io_uring_params *p) 304 + __cold ssize_t io_uring_mlock_size_params(unsigned entries, 305 + struct io_uring_params *p) 288 306 { 289 307 struct io_uring_params lp = { }; 290 308 struct io_uring ring; ··· 343 361 * Return required ulimit -l memory space for a given ring setup. See 344 362 * @io_uring_mlock_size_params(). 345 363 */ 346 - ssize_t io_uring_mlock_size(unsigned entries, unsigned flags) 364 + __cold ssize_t io_uring_mlock_size(unsigned entries, unsigned flags) 347 365 { 348 366 struct io_uring_params p = { .flags = flags, }; 349 367
+14 -32
vendor/liburing/src/syscall.c
··· 1 1 /* SPDX-License-Identifier: MIT */ 2 - #define _DEFAULT_SOURCE 3 2 4 - /* 5 - * Functions in this file require libc, only build them when we use libc. 6 - * 7 - * Note: 8 - * liburing's tests still need these functions. 9 - */ 10 - #if defined(CONFIG_NOLIBC) && !defined(LIBURING_BUILD_TEST) 11 - #error "This file should only be compiled for libc build, or for liburing tests" 12 - #endif 13 - 14 - /* 15 - * Will go away once libc support is there 16 - */ 17 - #include <unistd.h> 18 - #include <sys/syscall.h> 19 - #include <sys/uio.h> 20 - #include "liburing/compat.h" 21 - #include "liburing/io_uring.h" 22 3 #include "syscall.h" 4 + #include <liburing.h> 23 5 24 - int __sys_io_uring_register(int fd, unsigned opcode, const void *arg, 25 - unsigned nr_args) 6 + int io_uring_enter(unsigned int fd, unsigned int to_submit, 7 + unsigned int min_complete, unsigned int flags, sigset_t *sig) 26 8 { 27 - return syscall(__NR_io_uring_register, fd, opcode, arg, nr_args); 9 + return __sys_io_uring_enter(fd, to_submit, min_complete, flags, sig); 28 10 } 29 11 30 - int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p) 12 + int io_uring_enter2(unsigned int fd, unsigned int to_submit, 13 + unsigned int min_complete, unsigned int flags, 14 + sigset_t *sig, size_t sz) 31 15 { 32 - return syscall(__NR_io_uring_setup, entries, p); 16 + return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, 17 + sz); 33 18 } 34 19 35 - int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, 36 - unsigned flags, sigset_t *sig, int sz) 20 + int io_uring_setup(unsigned int entries, struct io_uring_params *p) 37 21 { 38 - return syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, 39 - sig, sz); 22 + return __sys_io_uring_setup(entries, p); 40 23 } 41 24 42 - int __sys_io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, 43 - unsigned flags, sigset_t *sig) 25 + int io_uring_register(unsigned int fd, unsigned int opcode, const void *arg, 26 + unsigned int nr_args) 44 27 { 45 - return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig, 46 - _NSIG / 8); 28 + return __sys_io_uring_register(fd, opcode, arg, nr_args); 47 29 }
+2 -54
vendor/liburing/src/syscall.h
··· 10 10 #include <sys/mman.h> 11 11 #include <sys/syscall.h> 12 12 #include <sys/resource.h> 13 - 14 13 #include <liburing.h> 15 14 16 - #ifdef __alpha__ 17 - /* 18 - * alpha and mips are exception, other architectures have 19 - * common numbers for new system calls. 20 - */ 21 - #ifndef __NR_io_uring_setup 22 - #define __NR_io_uring_setup 535 23 - #endif 24 - #ifndef __NR_io_uring_enter 25 - #define __NR_io_uring_enter 536 26 - #endif 27 - #ifndef __NR_io_uring_register 28 - #define __NR_io_uring_register 537 29 - #endif 30 - #elif defined __mips__ 31 - #ifndef __NR_io_uring_setup 32 - #define __NR_io_uring_setup (__NR_Linux + 425) 33 - #endif 34 - #ifndef __NR_io_uring_enter 35 - #define __NR_io_uring_enter (__NR_Linux + 426) 36 - #endif 37 - #ifndef __NR_io_uring_register 38 - #define __NR_io_uring_register (__NR_Linux + 427) 39 - #endif 40 - #else /* !__alpha__ and !__mips__ */ 41 - #ifndef __NR_io_uring_setup 42 - #define __NR_io_uring_setup 425 43 - #endif 44 - #ifndef __NR_io_uring_enter 45 - #define __NR_io_uring_enter 426 46 - #endif 47 - #ifndef __NR_io_uring_register 48 - #define __NR_io_uring_register 427 49 - #endif 50 - #endif 51 - 52 15 /* 53 16 * Don't put this below the #include "arch/$arch/syscall.h", that 54 17 * file may need it. ··· 60 23 return (void *) n; 61 24 } 62 25 63 - static inline intptr_t PTR_ERR(const void *ptr) 26 + static inline int PTR_ERR(const void *ptr) 64 27 { 65 - return (intptr_t) ptr; 28 + return (int) (intptr_t) ptr; 66 29 } 67 30 68 31 static inline bool IS_ERR(const void *ptr) ··· 70 33 return uring_unlikely((uintptr_t) ptr >= (uintptr_t) -4095UL); 71 34 } 72 35 73 - #define __INTERNAL__LIBURING_SYSCALL_H 74 36 #if defined(__x86_64__) || defined(__i386__) 75 37 #include "arch/x86/syscall.h" 76 38 #elif defined(__aarch64__) ··· 86 48 /* libc syscall wrappers. */ 87 49 #include "arch/generic/syscall.h" 88 50 #endif 89 - #undef __INTERNAL__LIBURING_SYSCALL_H 90 - 91 - /* 92 - * For backward compatibility. 93 - * (these __sys* functions always use libc, see syscall.c) 94 - */ 95 - int __sys_io_uring_setup(unsigned entries, struct io_uring_params *p); 96 - int __sys_io_uring_enter(int fd, unsigned to_submit, unsigned min_complete, 97 - unsigned flags, sigset_t *sig); 98 - int __sys_io_uring_enter2(int fd, unsigned to_submit, unsigned min_complete, 99 - unsigned flags, sigset_t *sig, int sz); 100 - int __sys_io_uring_register(int fd, unsigned int opcode, const void *arg, 101 - unsigned int nr_args); 102 - 103 51 #endif
+8 -9
vendor/liburing/test/232c93d07b74.c
··· 21 21 #include <netinet/in.h> 22 22 #include <arpa/inet.h> 23 23 24 + #include "helpers.h" 24 25 #include "liburing.h" 25 26 26 27 #define RECV_BUFF_SIZE 2 27 28 #define SEND_BUFF_SIZE 3 28 29 29 - #define PORT 0x1234 30 - 31 30 struct params { 32 31 int tcp; 33 32 int non_blocking; 33 + __be16 bind_port; 34 34 }; 35 35 36 36 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ··· 76 76 struct sockaddr_in addr; 77 77 78 78 addr.sin_family = AF_INET; 79 - addr.sin_port = htons(PORT); 80 79 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 81 - res = bind(s0, (struct sockaddr *) &addr, sizeof(addr)); 82 - assert(res != -1); 80 + assert(t_bind_ephemeral_port(s0, &addr) == 0); 81 + p->bind_port = addr.sin_port; 83 82 } else { 84 83 s0 = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); 85 84 assert(s0 != -1); ··· 191 190 struct sockaddr_in addr; 192 191 193 192 addr.sin_family = AF_INET; 194 - addr.sin_port = htons(PORT); 193 + addr.sin_port = p->bind_port; 195 194 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 196 195 ret = connect(s0, (struct sockaddr*) &addr, sizeof(addr)); 197 196 assert(ret != -1); ··· 281 280 struct params p; 282 281 pthread_t t1, t2; 283 282 void *res1, *res2; 284 - int i, exit_val = 0; 283 + int i, exit_val = T_EXIT_PASS; 285 284 286 285 if (argc > 1) 287 - return 0; 286 + return T_EXIT_SKIP; 288 287 289 288 for (i = 0; i < 4; i++) { 290 289 p.tcp = i & 1; ··· 298 297 pthread_join(t2, &res2); 299 298 if (res1 || res2) { 300 299 fprintf(stderr, "Failed tcp=%d, non_blocking=%d\n", p.tcp, p.non_blocking); 301 - exit_val = 1; 300 + exit_val = T_EXIT_FAIL; 302 301 } 303 302 } 304 303
+3 -2
vendor/liburing/test/35fa71a030ca.c
··· 25 25 #include <linux/futex.h> 26 26 27 27 #include "liburing.h" 28 + #include "helpers.h" 28 29 #include "../src/syscall.h" 29 30 30 31 #if !defined(SYS_futex) && defined(SYS_futex_time64) ··· 317 318 int main(int argc, char *argv[]) 318 319 { 319 320 if (argc > 1) 320 - return 0; 321 + return T_EXIT_SKIP; 321 322 signal(SIGINT, sig_int); 322 323 mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); 323 324 signal(SIGALRM, sig_int); 324 325 alarm(5); 325 326 326 327 loop(); 327 - return 0; 328 + return T_EXIT_PASS; 328 329 }
+7 -7
vendor/liburing/test/500f9fbadef8.c
··· 27 27 int ret, fd; 28 28 29 29 if (argc > 1) 30 - return 0; 30 + return T_EXIT_SKIP; 31 31 32 32 t_posix_memalign(&iov.iov_base, 4096, 4096); 33 33 iov.iov_len = 4096; ··· 35 35 ret = io_uring_queue_init(1, &ring, IORING_SETUP_IOPOLL); 36 36 if (ret) { 37 37 fprintf(stderr, "ring setup failed\n"); 38 - return 1; 38 + return T_EXIT_FAIL; 39 39 40 40 } 41 41 ··· 43 43 fd = mkostemp(buf, O_WRONLY | O_DIRECT | O_CREAT); 44 44 if (fd < 0) { 45 45 perror("mkostemp"); 46 - return 1; 46 + return T_EXIT_FAIL; 47 47 } 48 48 49 49 offset = 0; ··· 73 73 io_uring_cqe_seen(&ring, cqe); 74 74 offset += 4096; 75 75 } while (--blocks); 76 - 76 + 77 77 close(fd); 78 78 unlink(buf); 79 - return 0; 79 + return T_EXIT_PASS; 80 80 err: 81 81 close(fd); 82 82 unlink(buf); 83 - return 1; 83 + return T_EXIT_FAIL; 84 84 skipped: 85 85 fprintf(stderr, "Polling not supported in current dir, test skipped\n"); 86 86 close(fd); 87 87 unlink(buf); 88 - return 0; 88 + return T_EXIT_SKIP; 89 89 }
+8 -7
vendor/liburing/test/7ad0e4b2f83c.c
··· 3 3 #include <time.h> 4 4 #include <sys/time.h> 5 5 #include "liburing.h" 6 + #include "helpers.h" 6 7 7 8 static unsigned long long mtime_since(const struct timeval *s, 8 9 const struct timeval *e) ··· 40 41 int ret; 41 42 42 43 if (argc > 1) 43 - return 0; 44 + return T_EXIT_SKIP; 44 45 45 46 ret = io_uring_queue_init(32, &ring, 0); 46 47 if (ret) { 47 48 fprintf(stderr, "io_uring_queue_init=%d\n", ret); 48 - return 1; 49 + return T_EXIT_FAIL; 49 50 } 50 51 51 52 sqe = io_uring_get_sqe(&ring); ··· 53 54 ret = io_uring_submit(&ring); 54 55 if (ret != 1) { 55 56 fprintf(stderr, "io_uring_submit1=%d\n", ret); 56 - return 1; 57 + return T_EXIT_FAIL; 57 58 } 58 59 59 60 ··· 62 63 ret = io_uring_wait_cqe_timeout(&ring, &cqe, &ts1); 63 64 if (ret) { 64 65 fprintf(stderr, "io_uring_wait_cqe_timeout=%d\n", ret); 65 - return 1; 66 + return T_EXIT_FAIL; 66 67 } 67 68 io_uring_cqe_seen(&ring, cqe); 68 69 gettimeofday(&tv, NULL); ··· 75 76 ret = io_uring_submit(&ring); 76 77 if (ret != 1) { 77 78 fprintf(stderr, "io_uring_submit2=%d\n", ret); 78 - return 1; 79 + return T_EXIT_FAIL; 79 80 } 80 81 81 82 io_uring_wait_cqe(&ring, &cqe); ··· 83 84 msec = mtime_since_now(&tv); 84 85 if (msec >= 900 && msec <= 1100) { 85 86 io_uring_queue_exit(&ring); 86 - return 0; 87 + return T_EXIT_PASS; 87 88 } 88 89 89 90 fprintf(stderr, "%s: Timeout seems wonky (got %lu)\n", __FUNCTION__, 90 91 msec); 91 92 io_uring_queue_exit(&ring); 92 - return 1; 93 + return T_EXIT_FAIL; 93 94 }
+4 -3
vendor/liburing/test/8a9973408177.c
··· 7 7 #include <fcntl.h> 8 8 9 9 #include "liburing.h" 10 + #include "helpers.h" 10 11 11 12 static int register_file(struct io_uring *ring) 12 13 { ··· 85 86 int ret; 86 87 87 88 if (argc > 1) 88 - return 0; 89 + return T_EXIT_SKIP; 89 90 90 91 ret = io_uring_queue_init(8, &ring, 0); 91 92 if (ret) { 92 93 printf("ring setup failed\n"); 93 - return 1; 94 + return T_EXIT_FAIL; 94 95 } 95 96 96 97 ret = register_file(&ring); ··· 102 103 return ret; 103 104 } 104 105 105 - return 0; 106 + return T_EXIT_PASS; 106 107 }
+3 -2
vendor/liburing/test/917257daa0fe.c
··· 11 11 #include <unistd.h> 12 12 13 13 #include "liburing.h" 14 + #include "helpers.h" 14 15 #include "../src/syscall.h" 15 16 16 17 int main(int argc, char *argv[]) 17 18 { 18 19 if (argc > 1) 19 - return 0; 20 + return T_EXIT_SKIP; 20 21 21 22 mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); 22 23 ··· 49 50 *(uint32_t*)0x2000006c = 0; 50 51 *(uint64_t*)0x20000070 = 0; 51 52 __sys_io_uring_setup(0x7a6, (struct io_uring_params *) 0x20000000UL); 52 - return 0; 53 + return T_EXIT_PASS; 53 54 }
+13 -14
vendor/liburing/test/Makefile
··· 15 15 -I../src/include/ \ 16 16 -include ../config-host.h 17 17 18 - CFLAGS ?= -g -O2 -Wall -Wextra 18 + CFLAGS ?= -g -O3 -Wall -Wextra 19 19 XCFLAGS = -Wno-unused-parameter -Wno-sign-compare 20 20 21 21 ifdef CONFIG_HAVE_STRINGOP_OVERFLOW ··· 62 62 d4ae271dfaae.c \ 63 63 d77a67ed5f27.c \ 64 64 defer.c \ 65 + defer-taskrun.c \ 65 66 double-poll-crash.c \ 66 67 drop-submit.c \ 67 68 eeed8b54e0df.c \ ··· 75 76 fadvise.c \ 76 77 fallocate.c \ 77 78 fc2a85cb02ef.c \ 79 + fd-pass.c \ 78 80 file-register.c \ 79 81 files-exit-hang-poll.c \ 80 82 files-exit-hang-timeout.c \ ··· 88 90 hardlink.c \ 89 91 io-cancel.c \ 90 92 iopoll.c \ 93 + iopoll-leak.c \ 91 94 io_uring_enter.c \ 95 + io_uring_passthrough.c \ 92 96 io_uring_register.c \ 93 97 io_uring_setup.c \ 94 98 lfs-openat.c \ ··· 100 104 mkdir.c \ 101 105 msg-ring.c \ 102 106 multicqes_drain.c \ 107 + nolibc.c \ 103 108 nop-all-sizes.c \ 104 109 nop.c \ 105 110 openat2.c \ ··· 116 121 poll-link.c \ 117 122 poll-many.c \ 118 123 poll-mshot-update.c \ 124 + poll-mshot-overflow.c \ 119 125 poll-ring.c \ 120 126 poll-v-poll.c \ 121 127 pollfree.c \ ··· 124 130 read-write.c \ 125 131 recv-msgall.c \ 126 132 recv-msgall-stream.c \ 133 + recv-multishot.c \ 127 134 register-restrictions.c \ 128 135 rename.c \ 129 136 ringbuf-read.c \ ··· 156 163 sqpoll-sleep.c \ 157 164 sq-space_left.c \ 158 165 stdout.c \ 166 + submit-and-wait.c \ 159 167 submit-link-fail.c \ 160 168 submit-reuse.c \ 169 + sync-cancel.c \ 161 170 symlink.c \ 162 171 teardowns.c \ 163 172 thread-exit.c \ ··· 169 178 wakeup-hang.c \ 170 179 xattr.c \ 171 180 skip-cqe.c \ 181 + single-issuer.c \ 182 + send-zerocopy.c \ 172 183 # EOL 173 184 174 185 all_targets := ··· 192 203 run_test_targets := $(patsubst %,%.run_test,$(test_targets)) 193 204 test_targets := $(patsubst %,%.t,$(test_targets)) 194 205 all_targets += $(test_targets) 195 - 196 - # 197 - # Build ../src/syscall.c manually from test's Makefile to support 198 - # liburing nolibc. 199 - # 200 - # Functions in ../src/syscall.c require libc to work with, if we 201 - # build liburing without libc, we don't have those functions 202 - # in liburing.a. So build it manually here. 203 - # 204 - helpers = helpers.o ../src/syscall.o 206 + helpers = helpers.o 205 207 206 208 all: $(test_targets) 207 - 208 - ../src/syscall.o: ../src/syscall.c 209 - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $< 210 209 211 210 helpers.o: helpers.c 212 211 $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<
+3 -2
vendor/liburing/test/a0908ae19763.c
··· 11 11 #include <unistd.h> 12 12 13 13 #include "liburing.h" 14 + #include "helpers.h" 14 15 #include "../src/syscall.h" 15 16 16 17 uint64_t r[1] = {0xffffffffffffffff}; ··· 18 19 int main(int argc, char *argv[]) 19 20 { 20 21 if (argc > 1) 21 - return 0; 22 + return T_EXIT_SKIP; 22 23 mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); 23 24 intptr_t res = 0; 24 25 *(uint32_t*)0x20000080 = 0; ··· 54 55 r[0] = res; 55 56 *(uint32_t*)0x20000280 = -1; 56 57 __sys_io_uring_register(r[0], 2, (const void *) 0x20000280, 1); 57 - return 0; 58 + return T_EXIT_PASS; 58 59 }
+3 -2
vendor/liburing/test/a4c0b3decb33.c
··· 21 21 #include <unistd.h> 22 22 23 23 #include "liburing.h" 24 + #include "helpers.h" 24 25 #include "../src/syscall.h" 25 26 26 27 static void sleep_ms(uint64_t ms) ··· 172 173 int main(int argc, char *argv[]) 173 174 { 174 175 if (argc > 1) 175 - return 0; 176 + return T_EXIT_SKIP; 176 177 signal(SIGINT, sig_int); 177 178 mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); 178 179 loop(); 179 - return 0; 180 + return T_EXIT_PASS; 180 181 }
+5 -4
vendor/liburing/test/accept-link.c
··· 14 14 #include <arpa/inet.h> 15 15 16 16 #include "liburing.h" 17 + #include "helpers.h" 17 18 18 19 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 19 20 pthread_cond_t cond = PTHREAD_COND_INITIALIZER; ··· 239 240 int main(int argc, char *argv[]) 240 241 { 241 242 if (argc > 1) 242 - return 0; 243 + return T_EXIT_SKIP; 243 244 if (test_accept_timeout(0, 200000000)) { 244 245 fprintf(stderr, "accept timeout 0 failed\n"); 245 - return 1; 246 + return T_EXIT_FAIL; 246 247 } 247 248 248 249 if (test_accept_timeout(1, 1000000000)) { 249 250 fprintf(stderr, "accept and connect timeout 0 failed\n"); 250 - return 1; 251 + return T_EXIT_FAIL; 251 252 } 252 253 253 - return 0; 254 + return T_EXIT_PASS; 254 255 }
+17 -16
vendor/liburing/test/accept-reuse.c
··· 8 8 #include <stdio.h> 9 9 #include <errno.h> 10 10 #include "liburing.h" 11 + #include "helpers.h" 11 12 #include "../src/syscall.h" 12 13 13 14 struct io_uring io_uring; ··· 25 26 struct io_uring_sq *sq = &io_uring.sq; 26 27 const unsigned tail = *sq->ktail; 27 28 28 - sq->array[tail & *sq->kring_mask] = 0; 29 + sq->array[tail & sq->ring_mask] = 0; 29 30 io_uring_smp_store_release(sq->ktail, tail + 1); 30 31 31 32 return sys_io_uring_enter(io_uring.ring_fd, 1, 0, 0, NULL); ··· 43 44 int ret, listen_fd, connect_fd, val, i; 44 45 45 46 if (argc > 1) 46 - return 0; 47 + return T_EXIT_SKIP; 47 48 48 49 memset(&params, 0, sizeof(params)); 49 50 ret = io_uring_queue_init_params(4, &io_uring, &params); 50 51 if (ret) { 51 52 fprintf(stderr, "io_uring_init_failed: %d\n", ret); 52 - return 1; 53 + return T_EXIT_FAIL; 53 54 } 54 55 if (!(params.features & IORING_FEAT_SUBMIT_STABLE)) { 55 56 fprintf(stdout, "FEAT_SUBMIT_STABLE not there, skipping\n"); 56 - return 0; 57 + return T_EXIT_SKIP; 57 58 } 58 59 59 60 memset(&hints, 0, sizeof(hints)); ··· 64 65 ret = getaddrinfo(NULL, "12345", &hints, &addr_info_list); 65 66 if (ret < 0) { 66 67 perror("getaddrinfo"); 67 - return 1; 68 + return T_EXIT_FAIL; 68 69 } 69 70 70 71 for (ai = addr_info_list; ai; ai = ai->ai_next) { ··· 75 76 } 76 77 if (!addr_info) { 77 78 fprintf(stderr, "addrinfo not found\n"); 78 - return 1; 79 + return T_EXIT_FAIL; 79 80 } 80 81 81 82 sqe = &io_uring.sq.sqes[0]; ··· 85 86 addr_info->ai_protocol); 86 87 if (ret < 0) { 87 88 perror("socket"); 88 - return 1; 89 + return T_EXIT_FAIL; 89 90 } 90 91 listen_fd = ret; 91 92 ··· 96 97 ret = bind(listen_fd, addr_info->ai_addr, addr_info->ai_addrlen); 97 98 if (ret < 0) { 98 99 perror("bind"); 99 - return 1; 100 + return T_EXIT_FAIL; 100 101 } 101 102 102 103 ret = listen(listen_fd, SOMAXCONN); 103 104 if (ret < 0) { 104 105 perror("listen"); 105 - return 1; 106 + return T_EXIT_FAIL; 106 107 } 107 108 108 109 memset(&sa, 0, sizeof(sa)); ··· 112 113 ret = submit_sqe(); 113 114 if (ret != 1) { 114 115 fprintf(stderr, "submit failed: %d\n", ret); 115 - return 1; 116 + return T_EXIT_FAIL; 116 117 } 117 118 118 119 connect_fd = -1; 119 120 ret = socket(addr_info->ai_family, SOCK_STREAM, addr_info->ai_protocol); 120 121 if (ret < 0) { 121 122 perror("socket"); 122 - return 1; 123 + return T_EXIT_FAIL; 123 124 } 124 125 connect_fd = ret; 125 126 ··· 129 130 ret = submit_sqe(); 130 131 if (ret != 1) { 131 132 fprintf(stderr, "submit failed: %d\n", ret); 132 - return 1; 133 + return T_EXIT_FAIL; 133 134 } 134 135 135 136 for (i = 0; i < 2; i++) { ··· 138 139 ret = io_uring_wait_cqe(&io_uring, &cqe); 139 140 if (ret) { 140 141 fprintf(stderr, "io_uring_wait_cqe: %d\n", ret); 141 - return 1; 142 + return T_EXIT_FAIL; 142 143 } 143 144 144 145 switch (cqe->user_data) { 145 146 case 1: 146 147 if (cqe->res < 0) { 147 148 fprintf(stderr, "accept failed: %d\n", cqe->res); 148 - return 1; 149 + return T_EXIT_FAIL; 149 150 } 150 151 break; 151 152 case 2: 152 153 if (cqe->res) { 153 154 fprintf(stderr, "connect failed: %d\n", cqe->res); 154 - return 1; 155 + return T_EXIT_FAIL; 155 156 } 156 157 break; 157 158 } ··· 160 161 161 162 freeaddrinfo(addr_info_list); 162 163 io_uring_queue_exit(&io_uring); 163 - return 0; 164 + return T_EXIT_PASS; 164 165 }
+13 -9
vendor/liburing/test/accept-test.c
··· 8 8 #include <sys/un.h> 9 9 #include <assert.h> 10 10 #include "liburing.h" 11 + #include "helpers.h" 11 12 12 13 int main(int argc, char *argv[]) 13 14 { ··· 23 24 }; 24 25 25 26 if (argc > 1) 26 - return 0; 27 + return T_EXIT_SKIP; 27 28 28 29 if (io_uring_queue_init(4, &ring, 0) != 0) { 29 30 fprintf(stderr, "ring setup failed\n"); 30 - return 1; 31 + return T_EXIT_FAIL; 31 32 } 32 33 33 34 fd = socket(AF_UNIX, SOCK_STREAM, 0); ··· 45 46 sqe = io_uring_get_sqe(&ring); 46 47 if (!sqe) { 47 48 fprintf(stderr, "get sqe failed\n"); 48 - return 1; 49 + return T_EXIT_FAIL; 49 50 } 50 51 io_uring_prep_accept(sqe, fd, (struct sockaddr*)&addr, &addrlen, 0); 51 52 sqe->user_data = 1; ··· 53 54 ret = io_uring_submit(&ring); 54 55 if (ret != 1) { 55 56 fprintf(stderr, "Got submit %d, expected 1\n", ret); 56 - return 1; 57 + return T_EXIT_FAIL; 57 58 } 58 59 59 60 ret = io_uring_wait_cqe_timeout(&ring, &cqe, &ts); 60 61 if (!ret) { 61 62 if (cqe->res == -EBADF || cqe->res == -EINVAL) { 62 63 fprintf(stdout, "Accept not supported, skipping\n"); 63 - goto out; 64 + goto skip; 64 65 } else if (cqe->res < 0) { 65 66 fprintf(stderr, "cqe error %d\n", cqe->res); 66 67 goto err; 67 68 } 68 69 } else if (ret != -ETIME) { 69 70 fprintf(stderr, "accept() failed to use addr & addrlen parameters!\n"); 70 - return 1; 71 + return T_EXIT_FAIL; 71 72 } 72 73 73 - out: 74 + io_uring_queue_exit(&ring); 75 + return T_EXIT_PASS; 76 + 77 + skip: 74 78 io_uring_queue_exit(&ring); 75 - return 0; 79 + return T_EXIT_SKIP; 76 80 err: 77 81 io_uring_queue_exit(&ring); 78 - return 1; 82 + return T_EXIT_FAIL; 79 83 }
+108 -38
vendor/liburing/test/accept.c
··· 24 24 #include "liburing.h" 25 25 26 26 #define MAX_FDS 32 27 + #define NOP_USER_DATA (1LLU << 50) 28 + #define INITIAL_USER_DATA 1000 29 + 27 30 static int no_accept; 28 31 static int no_accept_multi; 29 32 ··· 39 42 bool queue_accept_before_connect; 40 43 bool multishot; 41 44 int extra_loops; 45 + bool overflow; 42 46 }; 43 47 44 48 static void close_fds(int fds[], int nr) ··· 86 90 sqe->flags |= IOSQE_FIXED_FILE; 87 91 } 88 92 93 + static void queue_accept_multishot(struct io_uring *ring, int fd, 94 + int idx, bool fixed) 95 + { 96 + struct io_uring_sqe *sqe = io_uring_get_sqe(ring); 97 + int ret; 98 + 99 + if (fixed) 100 + io_uring_prep_multishot_accept_direct(sqe, fd, 101 + NULL, NULL, 102 + 0); 103 + else 104 + io_uring_prep_multishot_accept(sqe, fd, NULL, NULL, 0); 105 + 106 + io_uring_sqe_set_data64(sqe, idx); 107 + ret = io_uring_submit(ring); 108 + assert(ret != -1); 109 + } 110 + 89 111 static void queue_accept_conn(struct io_uring *ring, int fd, 90 112 struct accept_test_args args) 91 113 { ··· 93 115 int ret; 94 116 int fixed_idx = args.fixed ? 0 : -1; 95 117 int count = 1 + args.extra_loops; 96 - bool multishot = args.multishot; 118 + 119 + if (args.multishot) { 120 + queue_accept_multishot(ring, fd, INITIAL_USER_DATA, args.fixed); 121 + return; 122 + } 97 123 98 124 while (count--) { 99 125 sqe = io_uring_get_sqe(ring); 100 126 if (fixed_idx < 0) { 101 - if (!multishot) 102 - io_uring_prep_accept(sqe, fd, NULL, NULL, 0); 103 - else 104 - io_uring_prep_multishot_accept(sqe, fd, NULL, 105 - NULL, 0); 127 + io_uring_prep_accept(sqe, fd, NULL, NULL, 0); 106 128 } else { 107 - if (!multishot) 108 - io_uring_prep_accept_direct(sqe, fd, NULL, NULL, 109 - 0, fixed_idx); 110 - else 111 - io_uring_prep_multishot_accept_direct(sqe, fd, 112 - NULL, NULL, 113 - 0); 129 + io_uring_prep_accept_direct(sqe, fd, NULL, NULL, 130 + 0, fixed_idx); 114 131 } 115 - 116 132 ret = io_uring_submit(ring); 117 133 assert(ret != -1); 118 134 } 119 135 } 120 136 121 - static int accept_conn(struct io_uring *ring, int fixed_idx, bool multishot) 137 + static int accept_conn(struct io_uring *ring, int fixed_idx, int *multishot, int fd) 122 138 { 123 - struct io_uring_cqe *cqe; 139 + struct io_uring_cqe *pcqe; 140 + struct io_uring_cqe cqe; 124 141 int ret; 125 142 126 - ret = io_uring_wait_cqe(ring, &cqe); 127 - assert(!ret); 128 - ret = cqe->res; 129 - io_uring_cqe_seen(ring, cqe); 143 + do { 144 + ret = io_uring_wait_cqe(ring, &pcqe); 145 + assert(!ret); 146 + cqe = *pcqe; 147 + io_uring_cqe_seen(ring, pcqe); 148 + } while (cqe.user_data == NOP_USER_DATA); 149 + 150 + if (*multishot) { 151 + if (!(cqe.flags & IORING_CQE_F_MORE)) { 152 + (*multishot)++; 153 + queue_accept_multishot(ring, fd, *multishot, fixed_idx == 0); 154 + } else { 155 + if (cqe.user_data != *multishot) { 156 + fprintf(stderr, "received multishot after told done!\n"); 157 + return -ECANCELED; 158 + } 159 + } 160 + } 161 + 162 + ret = cqe.res; 130 163 131 164 if (fixed_idx >= 0) { 132 165 if (ret > 0) { ··· 161 194 addr = &laddr; 162 195 163 196 addr->sin_family = AF_INET; 164 - addr->sin_port = htons(0x1235 + port_off); 165 197 addr->sin_addr.s_addr = inet_addr("127.0.0.1"); 166 - 167 - ret = bind(fd, (struct sockaddr*)addr, sizeof(*addr)); 168 - assert(ret != -1); 198 + assert(!t_bind_ephemeral_port(fd, addr)); 169 199 ret = listen(fd, 128); 170 200 assert(ret != -1); 171 201 ··· 203 233 return fd; 204 234 } 205 235 236 + static void cause_overflow(struct io_uring *ring) 237 + { 238 + int i, ret; 239 + 240 + for (i = 0; i < ring->cq.ring_entries; i++) { 241 + struct io_uring_sqe *sqe = io_uring_get_sqe(ring); 242 + 243 + io_uring_prep_nop(sqe); 244 + io_uring_sqe_set_data64(sqe, NOP_USER_DATA); 245 + ret = io_uring_submit(ring); 246 + assert(ret != -1); 247 + } 248 + 249 + } 250 + 251 + static void clear_overflow(struct io_uring *ring) 252 + { 253 + struct io_uring_cqe *cqe; 254 + 255 + while (!io_uring_peek_cqe(ring, &cqe)) { 256 + if (cqe->user_data != NOP_USER_DATA) 257 + break; 258 + io_uring_cqe_seen(ring, cqe); 259 + } 260 + } 261 + 206 262 static int test_loop(struct io_uring *ring, 207 263 struct accept_test_args args, 208 264 int recv_s0, ··· 215 271 bool multishot = args.multishot; 216 272 uint32_t multishot_mask = 0; 217 273 int nr_fds = multishot ? MAX_FDS : 1; 274 + int multishot_idx = multishot ? INITIAL_USER_DATA : 0; 218 275 219 - for (i = 0; i < nr_fds; i++) 276 + if (args.overflow) 277 + cause_overflow(ring); 278 + 279 + for (i = 0; i < nr_fds; i++) { 220 280 c_fd[i] = set_client_fd(addr); 281 + if (args.overflow && i == nr_fds / 2) 282 + clear_overflow(ring); 283 + } 221 284 222 285 if (!args.queue_accept_before_connect) 223 286 queue_accept_conn(ring, recv_s0, args); 224 287 225 288 for (i = 0; i < nr_fds; i++) { 226 - s_fd[i] = accept_conn(ring, fixed ? 0 : -1, multishot); 289 + s_fd[i] = accept_conn(ring, fixed ? 0 : -1, &multishot_idx, recv_s0); 227 290 if (s_fd[i] == -EINVAL) { 228 291 if (args.accept_should_error) 229 292 goto out; ··· 444 507 int fd, i, ret; 445 508 446 509 if (multishot && no_accept_multi) 447 - return 0; 510 + return T_EXIT_SKIP; 448 511 449 512 ret = io_uring_queue_init(32, &m_io_uring, 0); 450 513 assert(ret >= 0); ··· 527 590 return ret; 528 591 } 529 592 530 - static int test_multishot_accept(int count, bool before) 593 + static int test_multishot_accept(int count, bool before, bool overflow) 531 594 { 532 595 struct io_uring m_io_uring; 533 596 int ret; 534 597 struct accept_test_args args = { 535 598 .queue_accept_before_connect = before, 536 599 .multishot = true, 537 - .extra_loops = count - 1 600 + .extra_loops = count - 1, 601 + .overflow = overflow 538 602 }; 539 603 540 604 if (no_accept_multi) 541 - return 0; 605 + return T_EXIT_SKIP; 542 606 543 607 ret = io_uring_queue_init(MAX_FDS + 10, &m_io_uring, 0); 544 608 assert(ret >= 0); ··· 628 692 }; 629 693 630 694 if (no_accept_multi) 631 - return 0; 695 + return T_EXIT_SKIP; 632 696 633 697 memset(fd, -1, sizeof(fd)); 634 698 ret = io_uring_queue_init(MAX_FDS + 10, &m_io_uring, 0); ··· 668 732 int ret; 669 733 670 734 if (argc > 1) 671 - return 0; 735 + return T_EXIT_SKIP; 672 736 ret = test_accept(1, false); 673 737 if (ret) { 674 738 fprintf(stderr, "test_accept failed\n"); 675 739 return ret; 676 740 } 677 741 if (no_accept) 678 - return 0; 742 + return T_EXIT_SKIP; 679 743 680 744 ret = test_accept(2, false); 681 745 if (ret) { ··· 779 843 return ret; 780 844 } 781 845 782 - ret = test_multishot_accept(1, false); 846 + ret = test_multishot_accept(1, true, true); 783 847 if (ret) { 784 - fprintf(stderr, "test_multishot_accept(1, false) failed\n"); 848 + fprintf(stderr, "test_multishot_accept(1, false, true) failed\n"); 785 849 return ret; 786 850 } 787 851 788 - ret = test_multishot_accept(1, true); 852 + ret = test_multishot_accept(1, false, false); 789 853 if (ret) { 790 - fprintf(stderr, "test_multishot_accept(1, true) failed\n"); 854 + fprintf(stderr, "test_multishot_accept(1, false, false) failed\n"); 855 + return ret; 856 + } 857 + 858 + ret = test_multishot_accept(1, true, false); 859 + if (ret) { 860 + fprintf(stderr, "test_multishot_accept(1, true, false) failed\n"); 791 861 return ret; 792 862 } 793 863 ··· 825 895 fprintf(stderr, "test_accept_pending_on_exit failed\n"); 826 896 return ret; 827 897 } 828 - return 0; 898 + return T_EXIT_PASS; 829 899 }
+7 -6
vendor/liburing/test/across-fork.c
··· 15 15 #include <unistd.h> 16 16 17 17 #include "liburing.h" 18 + #include "helpers.h" 18 19 19 20 20 21 struct forktestmem ··· 141 142 pid_t p; 142 143 143 144 if (argc > 1) 144 - return 0; 145 + return T_EXIT_SKIP; 145 146 146 147 shmem = mmap(0, sizeof(struct forktestmem), PROT_READ|PROT_WRITE, 147 148 MAP_SHARED | MAP_ANONYMOUS, 0, 0); 148 149 if (!shmem) { 149 150 fprintf(stderr, "mmap failed\n"); 150 - exit(1); 151 + exit(T_EXIT_FAIL); 151 152 } 152 153 153 154 pthread_barrierattr_init(&shmem->barrierattr); ··· 157 158 ret = io_uring_queue_init(10, &shmem->ring, 0); 158 159 if (ret < 0) { 159 160 fprintf(stderr, "queue init failed\n"); 160 - exit(1); 161 + exit(T_EXIT_FAIL); 161 162 } 162 163 163 164 if (mkdtemp(tmpdir) == NULL) { 164 165 fprintf(stderr, "temp directory creation failed\n"); 165 - exit(1); 166 + exit(T_EXIT_FAIL); 166 167 } 167 168 168 169 shared_fd = open_tempfile(tmpdir, "shared"); ··· 275 276 goto errcleanup; 276 277 277 278 cleanup(tmpdir); 278 - exit(0); 279 + exit(T_EXIT_PASS); 279 280 280 281 errcleanup: 281 282 cleanup(tmpdir); 282 - exit(1); 283 + exit(T_EXIT_FAIL); 283 284 }
+3 -2
vendor/liburing/test/b19062a56726.c
··· 11 11 #include <unistd.h> 12 12 13 13 #include "liburing.h" 14 + #include "helpers.h" 14 15 #include "../src/syscall.h" 15 16 16 17 int main(int argc, char *argv[]) 17 18 { 18 19 if (argc > 1) 19 - return 0; 20 + return T_EXIT_SKIP; 20 21 21 22 mmap((void *) 0x20000000, 0x1000000, 3, 0x32, -1, 0); 22 23 ··· 49 50 *(uint32_t*)0x2000026c = 0; 50 51 *(uint64_t*)0x20000270 = 0; 51 52 __sys_io_uring_setup(0xc9f, (struct io_uring_params *) 0x20000200); 52 - return 0; 53 + return T_EXIT_PASS; 53 54 }
+10 -9
vendor/liburing/test/b5837bd5311d.c
··· 4 4 */ 5 5 #include <stdio.h> 6 6 #include "liburing.h" 7 + #include "helpers.h" 7 8 8 9 int main(int argc, char *argv[]) 9 10 { ··· 17 18 }; 18 19 19 20 if (argc > 1) 20 - return 0; 21 + return T_EXIT_SKIP; 21 22 22 23 if (io_uring_queue_init(4, &ring, 0) != 0) { 23 24 fprintf(stderr, "ring setup failed\n"); 24 - return 1; 25 + return T_EXIT_FAIL; 25 26 } 26 27 27 28 /* ··· 31 32 sqe = io_uring_get_sqe(&ring); 32 33 if (!sqe) { 33 34 fprintf(stderr, "get sqe failed\n"); 34 - return 1; 35 + return T_EXIT_FAIL; 35 36 } 36 37 io_uring_prep_timeout(sqe, &ts, (unsigned)-1, 0); 37 38 38 39 ret = io_uring_submit(&ring); 39 40 if (ret != 1) { 40 41 fprintf(stderr, "Got submit %d, expected 1\n", ret); 41 - return 1; 42 + return T_EXIT_FAIL; 42 43 } 43 44 44 45 /* ··· 50 51 sqe = io_uring_get_sqe(&ring); 51 52 if (!sqe) { 52 53 fprintf(stderr, "get sqe failed\n"); 53 - return 1; 54 + return T_EXIT_FAIL; 54 55 } 55 56 io_uring_prep_nop(sqe); 56 57 57 58 ret = io_uring_submit_and_wait(&ring, 2); 58 59 if (ret != 1) { 59 60 fprintf(stderr, "Got submit %d, expected 1\n", ret); 60 - return 1; 61 + return T_EXIT_FAIL; 61 62 } 62 63 63 64 if (io_uring_peek_cqe(&ring, &cqe) != 0) { 64 65 fprintf(stderr, "Unable to peek cqe!\n"); 65 - return 1; 66 + return T_EXIT_FAIL; 66 67 } 67 68 68 69 io_uring_cqe_seen(&ring, cqe); 69 70 70 71 if (io_uring_peek_cqe(&ring, &cqe) != 0) { 71 72 fprintf(stderr, "Unable to peek cqe!\n"); 72 - return 1; 73 + return T_EXIT_FAIL; 73 74 } 74 75 75 76 io_uring_queue_exit(&ring); 76 - return 0; 77 + return T_EXIT_PASS; 77 78 }
+37 -7
vendor/liburing/test/buf-ring.c
··· 206 206 return 0; 207 207 } 208 208 209 + static int test_bad_reg(int bgid) 210 + { 211 + struct io_uring ring; 212 + int ret; 213 + struct io_uring_buf_reg reg = { }; 214 + 215 + ret = t_create_ring(1, &ring, 0); 216 + if (ret == T_SETUP_SKIP) 217 + return 0; 218 + else if (ret != T_SETUP_OK) 219 + return 1; 220 + 221 + reg.ring_addr = 4096; 222 + reg.ring_entries = 32; 223 + reg.bgid = bgid; 224 + 225 + ret = io_uring_register_buf_ring(&ring, &reg, 0); 226 + if (!ret) 227 + fprintf(stderr, "Buffer ring register worked unexpectedly\n"); 228 + 229 + io_uring_queue_exit(&ring); 230 + return !ret; 231 + } 232 + 209 233 static int test_one_read(int fd, int bgid, struct io_uring *ring) 210 234 { 211 235 int ret; ··· 348 372 int ret, i; 349 373 350 374 if (argc > 1) 351 - return 0; 375 + return T_EXIT_SKIP; 352 376 353 377 for (i = 0; bgids[i] != -1; i++) { 354 378 ret = test_reg_unreg(bgids[i]); 355 379 if (ret) { 356 380 fprintf(stderr, "test_reg_unreg failed\n"); 357 - return 1; 381 + return T_EXIT_FAIL; 358 382 } 359 383 if (no_buf_ring) 360 384 break; 385 + 386 + ret = test_bad_reg(bgids[i]); 387 + if (ret) { 388 + fprintf(stderr, "test_bad_reg failed\n"); 389 + return T_EXIT_FAIL; 390 + } 361 391 362 392 ret = test_double_reg_unreg(bgids[i]); 363 393 if (ret) { 364 394 fprintf(stderr, "test_double_reg_unreg failed\n"); 365 - return 1; 395 + return T_EXIT_FAIL; 366 396 } 367 397 368 398 ret = test_mixed_reg(bgids[i]); 369 399 if (ret) { 370 400 fprintf(stderr, "test_mixed_reg failed\n"); 371 - return 1; 401 + return T_EXIT_FAIL; 372 402 } 373 403 374 404 ret = test_mixed_reg2(bgids[i]); 375 405 if (ret) { 376 406 fprintf(stderr, "test_mixed_reg2 failed\n"); 377 - return 1; 407 + return T_EXIT_FAIL; 378 408 } 379 409 } 380 410 ··· 382 412 ret = test_running(2, entries[i], 3); 383 413 if (ret) { 384 414 fprintf(stderr, "test_running(%d) failed\n", entries[i]); 385 - return 1; 415 + return T_EXIT_FAIL; 386 416 } 387 417 } 388 418 389 - return 0; 419 + return T_EXIT_PASS; 390 420 }
+15 -12
vendor/liburing/test/ce593a6c480a.c
··· 46 46 pthread_t tid; 47 47 48 48 if (argc > 1) 49 - return 0; 49 + return T_EXIT_SKIP; 50 50 51 51 /* Create an eventfd to be registered with the loop to be 52 52 * notified of events being ready ··· 54 54 loop_fd = eventfd(0, EFD_CLOEXEC); 55 55 if (loop_fd == -1) { 56 56 fprintf(stderr, "eventfd errno=%d\n", errno); 57 - return 1; 57 + return T_EXIT_FAIL; 58 58 } 59 59 60 60 /* Create an eventfd that can create events */ 61 61 use_fd = other_fd = eventfd(0, EFD_CLOEXEC); 62 62 if (other_fd == -1) { 63 63 fprintf(stderr, "eventfd errno=%d\n", errno); 64 - return 1; 64 + return T_EXIT_FAIL; 65 65 } 66 66 67 67 if (use_sqpoll) ··· 70 70 /* Setup the ring with a registered event fd to be notified on events */ 71 71 ret = t_create_ring_params(8, &ring, &p); 72 72 if (ret == T_SETUP_SKIP) 73 - return 0; 73 + return T_EXIT_PASS; 74 74 else if (ret < 0) 75 75 return ret; 76 76 77 77 ret = io_uring_register_eventfd(&ring, loop_fd); 78 78 if (ret < 0) { 79 79 fprintf(stderr, "register_eventfd=%d\n", ret); 80 - return 1; 80 + return T_EXIT_FAIL; 81 81 } 82 82 83 83 if (use_sqpoll) { 84 84 ret = io_uring_register_files(&ring, &other_fd, 1); 85 85 if (ret < 0) { 86 86 fprintf(stderr, "register_files=%d\n", ret); 87 - return 1; 87 + return T_EXIT_FAIL; 88 88 } 89 89 use_fd = 0; 90 90 } ··· 98 98 ret = io_uring_submit(&ring); 99 99 if (ret != 1) { 100 100 fprintf(stderr, "submit=%d\n", ret); 101 - return 1; 101 + return T_EXIT_FAIL; 102 102 } 103 103 104 104 /* ··· 111 111 (void*) (intptr_t) other_fd); 112 112 113 113 /* Wait on the event fd for an event to be ready */ 114 - ret = read(loop_fd, buf, 8); 114 + do { 115 + ret = read(loop_fd, buf, 8); 116 + } while (ret < 0 && errno == EINTR); 117 + 115 118 if (ret < 0) { 116 119 perror("read"); 117 - return 1; 120 + return T_EXIT_FAIL; 118 121 } else if (ret != 8) { 119 122 fprintf(stderr, "Odd-sized eventfd read: %d\n", ret); 120 - return 1; 123 + return T_EXIT_FAIL; 121 124 } 122 125 123 126 ··· 128 131 } 129 132 if (cqe->res < 0) { 130 133 fprintf(stderr, "cqe->res=%d\n", cqe->res); 131 - return 1; 134 + return T_EXIT_FAIL; 132 135 } 133 136 134 137 io_uring_cqe_seen(&ring, cqe); 135 - return 0; 138 + return T_EXIT_PASS; 136 139 }
+8 -7
vendor/liburing/test/connect.c
··· 17 17 #include <arpa/inet.h> 18 18 19 19 #include "liburing.h" 20 + #include "helpers.h" 20 21 21 22 static int no_connect; 22 23 static unsigned short use_port; ··· 360 361 int ret; 361 362 362 363 if (argc > 1) 363 - return 0; 364 + return T_EXIT_SKIP; 364 365 365 366 ret = io_uring_queue_init(8, &ring, 0); 366 367 if (ret) { 367 368 fprintf(stderr, "io_uring_queue_setup() = %d\n", ret); 368 - return 1; 369 + return T_EXIT_FAIL; 369 370 } 370 371 371 372 srand(getpid()); ··· 376 377 ret = test_connect_with_no_peer(&ring); 377 378 if (ret == -1) { 378 379 fprintf(stderr, "test_connect_with_no_peer(): failed\n"); 379 - return 1; 380 + return T_EXIT_FAIL; 380 381 } 381 382 if (no_connect) 382 - return 0; 383 + return T_EXIT_SKIP; 383 384 384 385 ret = test_connect(&ring); 385 386 if (ret == -1) { 386 387 fprintf(stderr, "test_connect(): failed\n"); 387 - return 1; 388 + return T_EXIT_FAIL; 388 389 } 389 390 390 391 ret = test_connect_timeout(&ring); 391 392 if (ret == -1) { 392 393 fprintf(stderr, "test_connect_timeout(): failed\n"); 393 - return 1; 394 + return T_EXIT_FAIL; 394 395 } 395 396 396 397 io_uring_queue_exit(&ring); 397 - return 0; 398 + return T_EXIT_PASS; 398 399 }
+5 -4
vendor/liburing/test/cq-full.c
··· 11 11 #include <fcntl.h> 12 12 13 13 #include "liburing.h" 14 + #include "helpers.h" 14 15 15 16 static int queue_n_nops(struct io_uring *ring, int n) 16 17 { ··· 49 50 int i, ret; 50 51 51 52 if (argc > 1) 52 - return 0; 53 + return T_EXIT_SKIP; 53 54 54 55 memset(&p, 0, sizeof(p)); 55 56 ret = io_uring_queue_init_params(4, &ring, &p); 56 57 if (ret) { 57 58 printf("ring setup failed\n"); 58 - return 1; 59 + return T_EXIT_FAIL; 59 60 60 61 } 61 62 ··· 89 90 } 90 91 91 92 io_uring_queue_exit(&ring); 92 - return 0; 93 + return T_EXIT_PASS; 93 94 err: 94 95 io_uring_queue_exit(&ring); 95 - return 1; 96 + return T_EXIT_FAIL; 96 97 }
+242 -12
vendor/liburing/test/cq-overflow.c
··· 9 9 #include <stdlib.h> 10 10 #include <string.h> 11 11 #include <fcntl.h> 12 + #include <assert.h> 12 13 13 14 #include "helpers.h" 14 15 #include "liburing.h" ··· 21 22 22 23 #define ENTRIES 8 23 24 25 + /* 26 + * io_uring has rare cases where CQEs are lost. 27 + * This happens when there is no space in the CQ ring, and also there is no 28 + * GFP_ATOMIC memory available. In reality this probably means that the process 29 + * is about to be killed as many other things might start failing, but we still 30 + * want to test that liburing and the kernel deal with this properly. The fault 31 + * injection framework allows us to test this scenario. Unfortunately this 32 + * requires some system wide changes and so we do not enable this by default. 33 + * The tests in this file should work in both cases (where overflows are queued 34 + * and where they are dropped) on recent kernels. 35 + * 36 + * In order to test dropped CQEs you should enable fault injection in the kernel 37 + * config: 38 + * 39 + * CONFIG_FAULT_INJECTION=y 40 + * CONFIG_FAILSLAB=y 41 + * CONFIG_FAULT_INJECTION_DEBUG_FS=y 42 + * 43 + * and then run the test as follows: 44 + * echo Y > /sys/kernel/debug/failslab/task-filter 45 + * echo 100 > /sys/kernel/debug/failslab/probability 46 + * echo 0 > /sys/kernel/debug/failslab/verbose 47 + * echo 100000 > /sys/kernel/debug/failslab/times 48 + * bash -c "echo 1 > /proc/self/make-it-fail && exec ./cq-overflow.t" 49 + */ 50 + 24 51 static int test_io(const char *file, unsigned long usecs, unsigned *drops, int fault) 25 52 { 26 53 struct io_uring_sqe *sqe; ··· 29 56 unsigned reaped, total; 30 57 struct io_uring ring; 31 58 int nodrop, i, fd, ret; 59 + bool cqe_dropped = false; 32 60 33 61 fd = open(file, O_RDONLY | O_DIRECT); 34 62 if (fd < 0) { 35 63 perror("file open"); 36 - goto err; 64 + return 1; 37 65 } 38 66 39 67 memset(&p, 0, sizeof(p)); 40 68 ret = io_uring_queue_init_params(ENTRIES, &ring, &p); 41 69 if (ret) { 70 + close(fd); 42 71 fprintf(stderr, "ring create failed: %d\n", ret); 43 - goto err; 72 + return 1; 44 73 } 45 74 nodrop = 0; 46 75 if (p.features & IORING_FEAT_NODROP) ··· 103 132 reap_it: 104 133 reaped = 0; 105 134 do { 106 - if (nodrop) { 107 - /* nodrop should never lose events */ 135 + if (nodrop && !cqe_dropped) { 136 + /* nodrop should never lose events unless cqe_dropped */ 108 137 if (reaped == total) 109 138 break; 110 139 } else { ··· 112 141 break; 113 142 } 114 143 ret = io_uring_wait_cqe(&ring, &cqe); 115 - if (ret) { 144 + if (nodrop && ret == -EBADR) { 145 + cqe_dropped = true; 146 + continue; 147 + } else if (ret) { 116 148 fprintf(stderr, "wait_cqe=%d\n", ret); 117 149 goto err; 118 150 } ··· 132 164 goto err; 133 165 } 134 166 135 - if (!nodrop) { 167 + if (!nodrop || cqe_dropped) { 136 168 *drops = *ring.cq.koverflow; 137 169 } else if (*ring.cq.koverflow) { 138 170 fprintf(stderr, "Found %u overflows\n", *ring.cq.koverflow); ··· 153 185 { 154 186 struct io_uring_cqe *cqe; 155 187 int i, ret = 0, seq = 0; 188 + unsigned int start_overflow = *ring->cq.koverflow; 189 + bool dropped = false; 156 190 157 191 for (i = 0; i < nr_events; i++) { 158 192 if (do_wait) 159 193 ret = io_uring_wait_cqe(ring, &cqe); 160 194 else 161 195 ret = io_uring_peek_cqe(ring, &cqe); 162 - if (ret) { 196 + if (do_wait && ret == -EBADR) { 197 + unsigned int this_drop = *ring->cq.koverflow - 198 + start_overflow; 199 + 200 + dropped = true; 201 + start_overflow = *ring->cq.koverflow; 202 + assert(this_drop > 0); 203 + i += (this_drop - 1); 204 + continue; 205 + } else if (ret) { 163 206 if (ret != -EAGAIN) 164 207 fprintf(stderr, "cqe peek failed: %d\n", ret); 165 208 break; 166 209 } 167 - if (cqe->user_data != seq) { 210 + if (!dropped && cqe->user_data != seq) { 168 211 fprintf(stderr, "cqe sequence out-of-order\n"); 169 212 fprintf(stderr, "got %d, wanted %d\n", (int) cqe->user_data, 170 213 seq); ··· 241 284 return 1; 242 285 } 243 286 287 + 288 + static void submit_one_nop(struct io_uring *ring, int ud) 289 + { 290 + struct io_uring_sqe *sqe; 291 + int ret; 292 + 293 + sqe = io_uring_get_sqe(ring); 294 + assert(sqe); 295 + io_uring_prep_nop(sqe); 296 + sqe->user_data = ud; 297 + ret = io_uring_submit(ring); 298 + assert(ret == 1); 299 + } 300 + 301 + /* 302 + * Create an overflow condition and ensure that SQEs are still processed 303 + */ 304 + static int test_overflow_handling(bool batch, int cqe_multiple, bool poll, 305 + bool defer) 306 + { 307 + struct io_uring ring; 308 + struct io_uring_params p; 309 + int ret, i, j, ud, cqe_count; 310 + unsigned int count; 311 + int const N = 8; 312 + int const LOOPS = 128; 313 + int const QUEUE_LENGTH = 1024; 314 + int completions[N]; 315 + int queue[QUEUE_LENGTH]; 316 + int queued = 0; 317 + int outstanding = 0; 318 + bool cqe_dropped = false; 319 + 320 + memset(&completions, 0, sizeof(int) * N); 321 + memset(&p, 0, sizeof(p)); 322 + p.cq_entries = 2 * cqe_multiple; 323 + p.flags |= IORING_SETUP_CQSIZE; 324 + 325 + if (poll) 326 + p.flags |= IORING_SETUP_IOPOLL; 327 + 328 + if (defer) 329 + p.flags |= IORING_SETUP_SINGLE_ISSUER | 330 + IORING_SETUP_DEFER_TASKRUN; 331 + 332 + ret = io_uring_queue_init_params(2, &ring, &p); 333 + if (ret) { 334 + fprintf(stderr, "io_uring_queue_init failed %d\n", ret); 335 + return 1; 336 + } 337 + 338 + assert(p.cq_entries < N); 339 + /* submit N SQEs, some should overflow */ 340 + for (i = 0; i < N; i++) { 341 + submit_one_nop(&ring, i); 342 + outstanding++; 343 + } 344 + 345 + for (i = 0; i < LOOPS; i++) { 346 + struct io_uring_cqe *cqes[N]; 347 + 348 + if (io_uring_cq_has_overflow(&ring)) { 349 + /* 350 + * Flush any overflowed CQEs and process those. Actively 351 + * flush these to make sure CQEs arrive in vague order 352 + * of being sent. 353 + */ 354 + ret = io_uring_get_events(&ring); 355 + if (ret != 0) { 356 + fprintf(stderr, 357 + "io_uring_get_events returned %d\n", 358 + ret); 359 + goto err; 360 + } 361 + } else if (!cqe_dropped) { 362 + for (j = 0; j < queued; j++) { 363 + submit_one_nop(&ring, queue[j]); 364 + outstanding++; 365 + } 366 + queued = 0; 367 + } 368 + 369 + /* We have lost some random cqes, stop if no remaining. */ 370 + if (cqe_dropped && outstanding == *ring.cq.koverflow) 371 + break; 372 + 373 + ret = io_uring_wait_cqe(&ring, &cqes[0]); 374 + if (ret == -EBADR) { 375 + cqe_dropped = true; 376 + fprintf(stderr, "CQE dropped\n"); 377 + continue; 378 + } else if (ret != 0) { 379 + fprintf(stderr, "io_uring_wait_cqes failed %d\n", ret); 380 + goto err; 381 + } 382 + cqe_count = 1; 383 + if (batch) { 384 + ret = io_uring_peek_batch_cqe(&ring, &cqes[0], 2); 385 + if (ret < 0) { 386 + fprintf(stderr, 387 + "io_uring_peek_batch_cqe failed %d\n", 388 + ret); 389 + goto err; 390 + } 391 + cqe_count = ret; 392 + } 393 + for (j = 0; j < cqe_count; j++) { 394 + assert(cqes[j]->user_data < N); 395 + ud = cqes[j]->user_data; 396 + completions[ud]++; 397 + assert(queued < QUEUE_LENGTH); 398 + queue[queued++] = (int)ud; 399 + } 400 + io_uring_cq_advance(&ring, cqe_count); 401 + outstanding -= cqe_count; 402 + } 403 + 404 + /* See if there were any drops by flushing the CQ ring *and* overflow */ 405 + do { 406 + struct io_uring_cqe *cqe; 407 + 408 + ret = io_uring_get_events(&ring); 409 + if (ret < 0) { 410 + if (ret == -EBADR) { 411 + fprintf(stderr, "CQE dropped\n"); 412 + cqe_dropped = true; 413 + break; 414 + } 415 + goto err; 416 + } 417 + if (outstanding && !io_uring_cq_ready(&ring)) 418 + ret = io_uring_wait_cqe_timeout(&ring, &cqe, NULL); 419 + 420 + if (ret && ret != -ETIME) { 421 + if (ret == -EBADR) { 422 + fprintf(stderr, "CQE dropped\n"); 423 + cqe_dropped = true; 424 + break; 425 + } 426 + fprintf(stderr, "wait_cqe_timeout = %d\n", ret); 427 + goto err; 428 + } 429 + count = io_uring_cq_ready(&ring); 430 + io_uring_cq_advance(&ring, count); 431 + outstanding -= count; 432 + } while (count); 433 + 434 + io_uring_queue_exit(&ring); 435 + 436 + /* Make sure that completions come back in the same order they were 437 + * sent. If they come back unfairly then this will concentrate on a 438 + * couple of indices. 439 + */ 440 + for (i = 1; !cqe_dropped && i < N; i++) { 441 + if (abs(completions[i] - completions[i - 1]) > 1) { 442 + fprintf(stderr, "bad completion size %d %d\n", 443 + completions[i], completions[i - 1]); 444 + goto err; 445 + } 446 + } 447 + return 0; 448 + err: 449 + io_uring_queue_exit(&ring); 450 + return 1; 451 + } 452 + 244 453 int main(int argc, char *argv[]) 245 454 { 246 455 const char *fname = ".cq-overflow"; 247 456 unsigned iters, drops; 248 457 unsigned long usecs; 249 458 int ret; 459 + int i; 460 + bool can_defer; 250 461 251 462 if (argc > 1) 252 - return 0; 463 + return T_EXIT_SKIP; 464 + 465 + can_defer = t_probe_defer_taskrun(); 466 + for (i = 0; i < 16; i++) { 467 + bool batch = i & 1; 468 + int mult = (i & 2) ? 1 : 2; 469 + bool poll = i & 4; 470 + bool defer = i & 8; 471 + 472 + if (defer && !can_defer) 473 + continue; 474 + 475 + ret = test_overflow_handling(batch, mult, poll, defer); 476 + if (ret) { 477 + fprintf(stderr, "test_overflow_handling(" 478 + "batch=%d, mult=%d, poll=%d, defer=%d) failed\n", 479 + batch, mult, poll, defer); 480 + goto err; 481 + } 482 + } 253 483 254 484 ret = test_overflow(); 255 485 if (ret) { 256 - printf("test_overflow failed\n"); 486 + fprintf(stderr, "test_overflow failed\n"); 257 487 return ret; 258 488 } 259 489 ··· 287 517 } 288 518 289 519 unlink(fname); 290 - return 0; 520 + return T_EXIT_PASS; 291 521 err: 292 522 unlink(fname); 293 - return 1; 523 + return T_EXIT_FAIL; 294 524 }
+5 -4
vendor/liburing/test/cq-peek-batch.c
··· 11 11 #include <fcntl.h> 12 12 13 13 #include "liburing.h" 14 + #include "helpers.h" 14 15 15 16 static int queue_n_nops(struct io_uring *ring, int n, int offset) 16 17 { ··· 58 59 unsigned got; 59 60 60 61 if (argc > 1) 61 - return 0; 62 + return T_EXIT_SKIP; 62 63 63 64 ret = io_uring_queue_init(4, &ring, 0); 64 65 if (ret) { 65 66 printf("ring setup failed\n"); 66 - return 1; 67 + return T_EXIT_FAIL; 67 68 68 69 } 69 70 ··· 95 96 96 97 io_uring_cq_advance(&ring, 8); 97 98 io_uring_queue_exit(&ring); 98 - return 0; 99 + return T_EXIT_PASS; 99 100 err: 100 101 io_uring_queue_exit(&ring); 101 - return 1; 102 + return T_EXIT_FAIL; 102 103 }
+5 -4
vendor/liburing/test/cq-ready.c
··· 11 11 #include <fcntl.h> 12 12 13 13 #include "liburing.h" 14 + #include "helpers.h" 14 15 15 16 static int queue_n_nops(struct io_uring *ring, int n) 16 17 { ··· 56 57 unsigned ready; 57 58 58 59 if (argc > 1) 59 - return 0; 60 + return T_EXIT_SKIP; 60 61 61 62 ret = io_uring_queue_init(4, &ring, 0); 62 63 if (ret) { 63 64 printf("ring setup failed\n"); 64 - return 1; 65 + return T_EXIT_FAIL; 65 66 66 67 } 67 68 ··· 87 88 CHECK_READY(&ring, 0); 88 89 89 90 io_uring_queue_exit(&ring); 90 - return 0; 91 + return T_EXIT_PASS; 91 92 err: 92 93 io_uring_queue_exit(&ring); 93 - return 1; 94 + return T_EXIT_FAIL; 94 95 }
+5 -4
vendor/liburing/test/cq-size.c
··· 10 10 #include <fcntl.h> 11 11 12 12 #include "liburing.h" 13 + #include "helpers.h" 13 14 14 15 int main(int argc, char *argv[]) 15 16 { ··· 18 19 int ret; 19 20 20 21 if (argc > 1) 21 - return 0; 22 + return T_EXIT_SKIP; 22 23 23 24 memset(&p, 0, sizeof(p)); 24 25 p.flags = IORING_SETUP_CQSIZE; ··· 31 32 goto done; 32 33 } 33 34 printf("ring setup failed\n"); 34 - return 1; 35 + return T_EXIT_FAIL; 35 36 } 36 37 37 38 if (p.cq_entries < 64) { ··· 58 59 } 59 60 60 61 done: 61 - return 0; 62 + return T_EXIT_PASS; 62 63 err: 63 - return 1; 64 + return T_EXIT_FAIL; 64 65 }
+2 -2
vendor/liburing/test/d4ae271dfaae.c
··· 31 31 p.flags = IORING_SETUP_SQPOLL; 32 32 ret = t_create_ring_params(4, &ring, &p); 33 33 if (ret == T_SETUP_SKIP) 34 - return 0; 34 + return T_EXIT_SKIP; 35 35 else if (ret < 0) 36 - return 1; 36 + return T_EXIT_FAIL; 37 37 38 38 if (argc > 1) { 39 39 fname = argv[1];
+6 -6
vendor/liburing/test/d77a67ed5f27.c
··· 22 22 int ret, data; 23 23 24 24 if (argc > 1) 25 - return 0; 25 + return T_EXIT_SKIP; 26 26 27 27 signal(SIGALRM, sig_alrm); 28 28 ··· 31 31 p.flags = IORING_SETUP_SQPOLL; 32 32 ret = t_create_ring_params(4, &ring, &p); 33 33 if (ret == T_SETUP_SKIP) 34 - return 0; 34 + return T_EXIT_SKIP; 35 35 else if (ret < 0) 36 - return 1; 36 + return T_EXIT_FAIL; 37 37 38 38 /* make sure sq thread is sleeping at this point */ 39 39 usleep(150000); ··· 42 42 sqe = io_uring_get_sqe(&ring); 43 43 if (!sqe) { 44 44 fprintf(stderr, "sqe get failed\n"); 45 - return 1; 45 + return T_EXIT_FAIL; 46 46 } 47 47 48 48 io_uring_prep_nop(sqe); ··· 58 58 data = (unsigned long) io_uring_cqe_get_data(cqe); 59 59 if (data != 42) { 60 60 fprintf(stderr, "invalid data: %d\n", data); 61 - return 1; 61 + return T_EXIT_FAIL; 62 62 } 63 63 64 - return 0; 64 + return T_EXIT_PASS; 65 65 }
+336
vendor/liburing/test/defer-taskrun.c
··· 1 + // SPDX-License-Identifier: MIT 2 + #include <errno.h> 3 + #include <stdio.h> 4 + #include <unistd.h> 5 + #include <stdlib.h> 6 + #include <string.h> 7 + #include <error.h> 8 + #include <sys/eventfd.h> 9 + #include <signal.h> 10 + #include <poll.h> 11 + #include <assert.h> 12 + #include <pthread.h> 13 + #include <sys/types.h> 14 + #include <sys/wait.h> 15 + 16 + #include "liburing.h" 17 + #include "test.h" 18 + #include "helpers.h" 19 + 20 + #define EXEC_FILENAME ".defer-taskrun" 21 + #define EXEC_FILESIZE (1U<<20) 22 + 23 + static bool can_read_t(int fd, int time) 24 + { 25 + int ret; 26 + struct pollfd p = { 27 + .fd = fd, 28 + .events = POLLIN, 29 + }; 30 + 31 + ret = poll(&p, 1, time); 32 + 33 + return ret == 1; 34 + } 35 + 36 + static bool can_read(int fd) 37 + { 38 + return can_read_t(fd, 0); 39 + } 40 + 41 + static void eventfd_clear(int fd) 42 + { 43 + uint64_t val; 44 + int ret; 45 + 46 + assert(can_read(fd)); 47 + ret = read(fd, &val, 8); 48 + assert(ret == 8); 49 + } 50 + 51 + static void eventfd_trigger(int fd) 52 + { 53 + uint64_t val = 1; 54 + int ret; 55 + 56 + ret = write(fd, &val, sizeof(val)); 57 + assert(ret == sizeof(val)); 58 + } 59 + 60 + #define CHECK(x) if (!(x)) { \ 61 + fprintf(stderr, "%s:%d %s failed\n", __FILE__, __LINE__, #x); \ 62 + return -1; } 63 + 64 + static int test_eventfd(void) 65 + { 66 + struct io_uring ring; 67 + int ret; 68 + int fda, fdb; 69 + struct io_uring_cqe *cqe; 70 + 71 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER | 72 + IORING_SETUP_DEFER_TASKRUN); 73 + if (ret) 74 + return ret; 75 + 76 + fda = eventfd(0, EFD_NONBLOCK); 77 + fdb = eventfd(0, EFD_NONBLOCK); 78 + 79 + CHECK(fda >= 0 && fdb >= 0); 80 + 81 + ret = io_uring_register_eventfd(&ring, fda); 82 + if (ret) 83 + return ret; 84 + 85 + CHECK(!can_read(fda)); 86 + CHECK(!can_read(fdb)); 87 + 88 + io_uring_prep_poll_add(io_uring_get_sqe(&ring), fdb, POLLIN); 89 + io_uring_submit(&ring); 90 + CHECK(!can_read(fda)); /* poll should not have completed */ 91 + 92 + io_uring_prep_nop(io_uring_get_sqe(&ring)); 93 + io_uring_submit(&ring); 94 + CHECK(can_read(fda)); /* nop should have */ 95 + 96 + CHECK(io_uring_peek_cqe(&ring, &cqe) == 0); 97 + CHECK(cqe->res == 0); 98 + io_uring_cqe_seen(&ring, cqe); 99 + eventfd_clear(fda); 100 + 101 + eventfd_trigger(fdb); 102 + /* can take time due to rcu_call */ 103 + CHECK(can_read_t(fda, 1000)); 104 + 105 + /* should not have processed the cqe yet */ 106 + CHECK(io_uring_cq_ready(&ring) == 0); 107 + 108 + io_uring_get_events(&ring); 109 + CHECK(io_uring_cq_ready(&ring) == 1); 110 + 111 + 112 + io_uring_queue_exit(&ring); 113 + return 0; 114 + } 115 + 116 + struct thread_data { 117 + struct io_uring ring; 118 + int efd; 119 + char buff[8]; 120 + }; 121 + 122 + void *thread(void *t) 123 + { 124 + struct thread_data *td = t; 125 + 126 + io_uring_enable_rings(&td->ring); 127 + io_uring_prep_read(io_uring_get_sqe(&td->ring), td->efd, td->buff, sizeof(td->buff), 0); 128 + io_uring_submit(&td->ring); 129 + 130 + return NULL; 131 + } 132 + 133 + static int test_thread_shutdown(void) 134 + { 135 + pthread_t t1; 136 + int ret; 137 + struct thread_data td; 138 + struct io_uring_cqe *cqe; 139 + uint64_t val = 1; 140 + 141 + ret = io_uring_queue_init(8, &td.ring, IORING_SETUP_SINGLE_ISSUER | 142 + IORING_SETUP_DEFER_TASKRUN | 143 + IORING_SETUP_R_DISABLED); 144 + if (ret) 145 + return ret; 146 + 147 + CHECK(io_uring_get_events(&td.ring) == -EBADFD); 148 + 149 + td.efd = eventfd(0, 0); 150 + CHECK(td.efd >= 0); 151 + 152 + CHECK(pthread_create(&t1, NULL, thread, &td) == 0); 153 + CHECK(pthread_join(t1, NULL) == 0); 154 + 155 + CHECK(io_uring_get_events(&td.ring) == -EEXIST); 156 + 157 + CHECK(write(td.efd, &val, sizeof(val)) == sizeof(val)); 158 + CHECK(io_uring_wait_cqe(&td.ring, &cqe) == -EEXIST); 159 + 160 + close(td.efd); 161 + io_uring_queue_exit(&td.ring); 162 + return 0; 163 + } 164 + 165 + static int test_exec(const char *filename) 166 + { 167 + int ret; 168 + int fd; 169 + struct io_uring ring; 170 + pid_t fork_pid; 171 + static char * const new_argv[] = {"1", "2", "3", NULL}; 172 + static char * const new_env[] = {NULL}; 173 + char *buff; 174 + 175 + fork_pid = fork(); 176 + CHECK(fork_pid >= 0); 177 + if (fork_pid > 0) { 178 + int wstatus; 179 + 180 + CHECK(waitpid(fork_pid, &wstatus, 0) != (pid_t)-1); 181 + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != T_EXIT_SKIP) { 182 + fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus)); 183 + return -1; 184 + } 185 + return 0; 186 + } 187 + 188 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER | 189 + IORING_SETUP_DEFER_TASKRUN); 190 + if (ret) 191 + return ret; 192 + 193 + if (filename) { 194 + fd = open(filename, O_RDONLY | O_DIRECT); 195 + } else { 196 + t_create_file(EXEC_FILENAME, EXEC_FILESIZE); 197 + fd = open(EXEC_FILENAME, O_RDONLY | O_DIRECT); 198 + unlink(EXEC_FILENAME); 199 + } 200 + buff = (char*)malloc(EXEC_FILESIZE); 201 + CHECK(posix_memalign((void **)&buff, 4096, EXEC_FILESIZE) == 0); 202 + CHECK(buff); 203 + 204 + CHECK(fd >= 0); 205 + io_uring_prep_read(io_uring_get_sqe(&ring), fd, buff, EXEC_FILESIZE, 0); 206 + io_uring_submit(&ring); 207 + ret = execve("/proc/self/exe", new_argv, new_env); 208 + /* if we get here it failed anyway */ 209 + fprintf(stderr, "execve failed %d\n", ret); 210 + return -1; 211 + } 212 + 213 + static int test_flag(void) 214 + { 215 + struct io_uring ring; 216 + int ret; 217 + int fd; 218 + struct io_uring_cqe *cqe; 219 + 220 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER | 221 + IORING_SETUP_DEFER_TASKRUN | 222 + IORING_SETUP_TASKRUN_FLAG); 223 + CHECK(!ret); 224 + 225 + fd = eventfd(0, EFD_NONBLOCK); 226 + CHECK(fd >= 0); 227 + 228 + io_uring_prep_poll_add(io_uring_get_sqe(&ring), fd, POLLIN); 229 + io_uring_submit(&ring); 230 + CHECK(!can_read(fd)); /* poll should not have completed */ 231 + 232 + eventfd_trigger(fd); 233 + CHECK(can_read(fd)); 234 + 235 + /* should not have processed the poll cqe yet */ 236 + CHECK(io_uring_cq_ready(&ring) == 0); 237 + 238 + /* flag should be set */ 239 + CHECK(IO_URING_READ_ONCE(*ring.sq.kflags) & IORING_SQ_TASKRUN); 240 + 241 + /* Specifically peek, knowing we have only no cqe 242 + * but because the flag is set, liburing should try and get more 243 + */ 244 + ret = io_uring_peek_cqe(&ring, &cqe); 245 + 246 + CHECK(ret == 0 && cqe); 247 + CHECK(!(IO_URING_READ_ONCE(*ring.sq.kflags) & IORING_SQ_TASKRUN)); 248 + 249 + close(fd); 250 + io_uring_queue_exit(&ring); 251 + return 0; 252 + } 253 + 254 + static int test_ring_shutdown(void) 255 + { 256 + struct io_uring ring; 257 + int ret; 258 + int fd[2]; 259 + char buff = '\0'; 260 + char send = 'X'; 261 + 262 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER | 263 + IORING_SETUP_DEFER_TASKRUN | 264 + IORING_SETUP_TASKRUN_FLAG); 265 + CHECK(!ret); 266 + 267 + ret = t_create_socket_pair(fd, true); 268 + CHECK(!ret); 269 + 270 + io_uring_prep_recv(io_uring_get_sqe(&ring), fd[0], &buff, 1, 0); 271 + io_uring_submit(&ring); 272 + 273 + ret = write(fd[1], &send, 1); 274 + CHECK(ret == 1); 275 + 276 + /* should not have processed the poll cqe yet */ 277 + CHECK(io_uring_cq_ready(&ring) == 0); 278 + io_uring_queue_exit(&ring); 279 + 280 + /* task work should have been processed by now */ 281 + CHECK(buff = 'X'); 282 + 283 + return 0; 284 + } 285 + 286 + int main(int argc, char *argv[]) 287 + { 288 + int ret; 289 + const char *filename = NULL; 290 + 291 + if (argc > 2) 292 + return T_EXIT_SKIP; 293 + if (argc == 2) { 294 + /* This test exposes interesting behaviour with a null-blk 295 + * device configured like: 296 + * $ modprobe null-blk completion_nsec=100000000 irqmode=2 297 + * and then run with $ defer-taskrun.t /dev/nullb0 298 + */ 299 + filename = argv[1]; 300 + } 301 + 302 + if (!t_probe_defer_taskrun()) 303 + return T_EXIT_SKIP; 304 + 305 + ret = test_thread_shutdown(); 306 + if (ret) { 307 + fprintf(stderr, "test_thread_shutdown failed\n"); 308 + return T_EXIT_FAIL; 309 + } 310 + 311 + ret = test_exec(filename); 312 + if (ret) { 313 + fprintf(stderr, "test_exec failed\n"); 314 + return T_EXIT_FAIL; 315 + } 316 + 317 + ret = test_eventfd(); 318 + if (ret) { 319 + fprintf(stderr, "eventfd failed\n"); 320 + return T_EXIT_FAIL; 321 + } 322 + 323 + ret = test_flag(); 324 + if (ret) { 325 + fprintf(stderr, "flag failed\n"); 326 + return T_EXIT_FAIL; 327 + } 328 + 329 + ret = test_ring_shutdown(); 330 + if (ret) { 331 + fprintf(stderr, "test_ring_shutdown failed\n"); 332 + return T_EXIT_FAIL; 333 + } 334 + 335 + return T_EXIT_PASS; 336 + }
+6 -6
vendor/liburing/test/defer.c
··· 260 260 int ret; 261 261 262 262 if (argc > 1) 263 - return 0; 263 + return T_EXIT_SKIP; 264 264 265 265 memset(&p, 0, sizeof(p)); 266 266 ret = io_uring_queue_init_params(RING_SIZE, &ring, &p); 267 267 if (ret) { 268 268 printf("ring setup failed %i\n", ret); 269 - return 1; 269 + return T_EXIT_FAIL; 270 270 } 271 271 272 272 ret = io_uring_queue_init(RING_SIZE, &poll_ring, IORING_SETUP_IOPOLL); 273 273 if (ret) { 274 274 printf("poll_ring setup failed\n"); 275 - return 1; 275 + return T_EXIT_FAIL; 276 276 } 277 277 278 278 ··· 305 305 ret = t_create_ring(RING_SIZE, &sqthread_ring, 306 306 IORING_SETUP_SQPOLL | IORING_SETUP_IOPOLL); 307 307 if (ret == T_SETUP_SKIP) 308 - return 0; 308 + return T_EXIT_SKIP; 309 309 else if (ret < 0) 310 - return 1; 310 + return T_EXIT_FAIL; 311 311 312 312 ret = test_thread_link_cancel(&sqthread_ring); 313 313 if (ret) { ··· 315 315 return ret; 316 316 } 317 317 318 - return 0; 318 + return T_EXIT_PASS; 319 319 }
+6 -5
vendor/liburing/test/double-poll-crash.c
··· 15 15 #include <unistd.h> 16 16 17 17 #include "liburing.h" 18 + #include "helpers.h" 18 19 #include "../src/syscall.h" 19 20 20 21 #define SIZEOF_IO_URING_SQE 64 ··· 114 115 { 115 116 void *mmap_ret; 116 117 #if !defined(__i386) && !defined(__x86_64__) 117 - return 0; 118 + return T_EXIT_SKIP; 118 119 #endif 119 120 120 121 if (argc > 1) 121 - return 0; 122 + return T_EXIT_SKIP; 122 123 123 124 mmap_ret = mmap((void *)0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul); 124 125 if (mmap_ret == MAP_FAILED) 125 - return 0; 126 + return T_EXIT_SKIP; 126 127 mmap_ret = mmap((void *)0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul); 127 128 if (mmap_ret == MAP_FAILED) 128 - return 0; 129 + return T_EXIT_SKIP; 129 130 intptr_t res = 0; 130 131 *(uint32_t*)0x20000484 = 0; 131 132 *(uint32_t*)0x20000488 = 0; ··· 190 191 "\xbd\x43\x7d\x16\x69\x3e\x05", 191 192 19); 192 193 ioctl(r[3], 0x5404, 0x20000080ul); 193 - return 0; 194 + return T_EXIT_PASS; 194 195 }
+4 -3
vendor/liburing/test/drop-submit.c
··· 9 9 #include <stdlib.h> 10 10 11 11 #include "liburing.h" 12 + #include "helpers.h" 12 13 13 14 static int test(struct io_uring *ring, int expect_drops) 14 15 { ··· 63 64 int ret; 64 65 65 66 if (argc > 1) 66 - return 0; 67 + return T_EXIT_SKIP; 67 68 68 69 ret = io_uring_queue_init(8, &ring, IORING_SETUP_SUBMIT_ALL); 69 70 if (ret) ··· 80 81 ret = io_uring_queue_init(8, &ring, 0); 81 82 if (ret) { 82 83 fprintf(stderr, "ring setup failed\n"); 83 - return 0; 84 + return T_EXIT_FAIL; 84 85 } 85 86 86 87 ret = test(&ring, 1); ··· 89 90 return ret; 90 91 } 91 92 92 - return 0; 93 + return T_EXIT_PASS; 93 94 }
+7 -6
vendor/liburing/test/eeed8b54e0df.c
··· 33 33 } 34 34 35 35 buf = t_malloc(BLOCK); 36 + memset(buf, 0, BLOCK); 36 37 ret = write(fd, buf, BLOCK); 37 38 if (ret != BLOCK) { 38 39 if (ret < 0) ··· 64 65 int ret, fd; 65 66 66 67 if (argc > 1) 67 - return 0; 68 + return T_EXIT_SKIP; 68 69 69 70 iov.iov_base = t_malloc(4096); 70 71 iov.iov_len = 4096; ··· 72 73 ret = io_uring_queue_init(2, &ring, 0); 73 74 if (ret) { 74 75 printf("ring setup failed\n"); 75 - return 1; 76 + return T_EXIT_FAIL; 76 77 77 78 } 78 79 79 80 sqe = io_uring_get_sqe(&ring); 80 81 if (!sqe) { 81 82 printf("get sqe failed\n"); 82 - return 1; 83 + return T_EXIT_FAIL; 83 84 } 84 85 85 86 fd = get_file_fd(); 86 87 if (fd < 0) 87 - return 1; 88 + return T_EXIT_FAIL; 88 89 89 90 io_uring_prep_readv(sqe, fd, &iov, 1, 0); 90 91 sqe->rw_flags = RWF_NOWAIT; ··· 107 108 } 108 109 109 110 close(fd); 110 - return 0; 111 + return T_EXIT_PASS; 111 112 err: 112 113 close(fd); 113 - return 1; 114 + return T_EXIT_FAIL; 114 115 }
+4 -4
vendor/liburing/test/empty-eownerdead.c
··· 17 17 int ret; 18 18 19 19 if (argc > 1) 20 - return 0; 20 + return T_EXIT_SKIP; 21 21 22 22 p.flags = IORING_SETUP_SQPOLL; 23 23 p.sq_thread_idle = 100; 24 24 25 25 ret = t_create_ring_params(1, &ring, &p); 26 26 if (ret == T_SETUP_SKIP) 27 - return 0; 27 + return T_EXIT_SKIP; 28 28 else if (ret < 0) 29 29 goto err; 30 30 ··· 39 39 goto err; 40 40 } 41 41 42 - return 0; 42 + return T_EXIT_PASS; 43 43 err: 44 - return 1; 44 + return T_EXIT_FAIL; 45 45 }
+48 -20
vendor/liburing/test/eventfd-disable.c
··· 13 13 #include <sys/eventfd.h> 14 14 15 15 #include "liburing.h" 16 + #include "helpers.h" 16 17 17 - int main(int argc, char *argv[]) 18 + static int test(bool defer) 18 19 { 19 20 struct io_uring_params p = {}; 20 21 struct io_uring_sqe *sqe; ··· 27 28 }; 28 29 int ret, evfd, i; 29 30 30 - if (argc > 1) 31 - return 0; 31 + if (defer) 32 + p.flags |= IORING_SETUP_SINGLE_ISSUER | 33 + IORING_SETUP_DEFER_TASKRUN; 32 34 33 35 ret = io_uring_queue_init_params(64, &ring, &p); 34 36 if (ret) { 35 37 fprintf(stderr, "ring setup failed: %d\n", ret); 36 - return 1; 38 + return T_EXIT_FAIL; 37 39 } 38 40 39 41 evfd = eventfd(0, EFD_CLOEXEC); 40 42 if (evfd < 0) { 41 43 perror("eventfd"); 42 - return 1; 44 + return T_EXIT_FAIL; 43 45 } 44 46 45 47 ret = io_uring_register_eventfd(&ring, evfd); 46 48 if (ret) { 47 49 fprintf(stderr, "failed to register evfd: %d\n", ret); 48 - return 1; 50 + return T_EXIT_FAIL; 49 51 } 50 52 51 53 if (!io_uring_cq_eventfd_enabled(&ring)) { 52 54 fprintf(stderr, "eventfd disabled\n"); 53 - return 1; 55 + return T_EXIT_FAIL; 54 56 } 55 57 56 58 ret = io_uring_cq_eventfd_toggle(&ring, false); 57 59 if (ret) { 58 60 fprintf(stdout, "Skipping, CQ flags not available!\n"); 59 - return 0; 61 + return T_EXIT_SKIP; 60 62 } 61 63 62 64 sqe = io_uring_get_sqe(&ring); ··· 66 68 ret = io_uring_submit(&ring); 67 69 if (ret != 1) { 68 70 fprintf(stderr, "submit: %d\n", ret); 69 - return 1; 71 + return T_EXIT_FAIL; 70 72 } 71 73 72 74 for (i = 0; i < 63; i++) { ··· 78 80 ret = io_uring_submit(&ring); 79 81 if (ret != 63) { 80 82 fprintf(stderr, "submit: %d\n", ret); 81 - return 1; 83 + return T_EXIT_FAIL; 82 84 } 83 85 84 86 for (i = 0; i < 63; i++) { 85 87 ret = io_uring_wait_cqe(&ring, &cqe); 86 88 if (ret) { 87 89 fprintf(stderr, "wait: %d\n", ret); 88 - return 1; 90 + return T_EXIT_FAIL; 89 91 } 90 92 91 93 switch (cqe->user_data) { 92 94 case 1: /* eventfd */ 93 95 fprintf(stderr, "eventfd unexpected: %d\n", (int)ptr); 94 - return 1; 96 + return T_EXIT_FAIL; 95 97 case 2: 96 98 if (cqe->res) { 97 99 fprintf(stderr, "nop: %d\n", cqe->res); 98 - return 1; 100 + return T_EXIT_FAIL; 99 101 } 100 102 break; 101 103 } ··· 105 107 ret = io_uring_cq_eventfd_toggle(&ring, true); 106 108 if (ret) { 107 109 fprintf(stderr, "io_uring_cq_eventfd_toggle: %d\n", ret); 108 - return 1; 110 + return T_EXIT_FAIL; 109 111 } 110 112 111 113 sqe = io_uring_get_sqe(&ring); ··· 115 117 ret = io_uring_submit(&ring); 116 118 if (ret != 1) { 117 119 fprintf(stderr, "submit: %d\n", ret); 118 - return 1; 120 + return T_EXIT_FAIL; 119 121 } 120 122 121 123 for (i = 0; i < 2; i++) { 122 124 ret = io_uring_wait_cqe(&ring, &cqe); 123 125 if (ret) { 124 126 fprintf(stderr, "wait: %d\n", ret); 125 - return 1; 127 + return T_EXIT_FAIL; 126 128 } 127 129 128 130 switch (cqe->user_data) { 129 131 case 1: /* eventfd */ 130 132 if (cqe->res != sizeof(ptr)) { 131 133 fprintf(stderr, "read res: %d\n", cqe->res); 132 - return 1; 134 + return T_EXIT_FAIL; 133 135 } 134 136 135 137 if (ptr != 1) { 136 138 fprintf(stderr, "eventfd: %d\n", (int)ptr); 137 - return 1; 139 + return T_EXIT_FAIL; 138 140 } 139 141 break; 140 142 case 2: 141 143 if (cqe->res) { 142 144 fprintf(stderr, "nop: %d\n", cqe->res); 143 - return 1; 145 + return T_EXIT_FAIL; 144 146 } 145 147 break; 146 148 } 147 149 io_uring_cqe_seen(&ring, cqe); 148 150 } 149 151 150 - return 0; 152 + io_uring_queue_exit(&ring); 153 + close(evfd); 154 + return T_EXIT_PASS; 155 + } 156 + 157 + int main(int argc, char *argv[]) 158 + { 159 + int ret; 160 + 161 + if (argc > 1) 162 + return T_EXIT_SKIP; 163 + 164 + ret = test(false); 165 + if (ret != T_EXIT_PASS) { 166 + fprintf(stderr, "%s: test(false) failed\n", argv[0]); 167 + return ret; 168 + } 169 + 170 + if (t_probe_defer_taskrun()) { 171 + ret = test(true); 172 + if (ret != T_EXIT_PASS) { 173 + fprintf(stderr, "%s: test(true) failed\n", argv[0]); 174 + return ret; 175 + } 176 + } 177 + 178 + return ret; 151 179 }
+10 -9
vendor/liburing/test/eventfd-reg.c
··· 13 13 #include <sys/eventfd.h> 14 14 15 15 #include "liburing.h" 16 + #include "helpers.h" 16 17 17 18 int main(int argc, char *argv[]) 18 19 { ··· 21 22 int ret, evfd[2], i; 22 23 23 24 if (argc > 1) 24 - return 0; 25 + return T_EXIT_SKIP; 25 26 26 27 ret = io_uring_queue_init_params(8, &ring, &p); 27 28 if (ret) { 28 29 fprintf(stderr, "ring setup failed: %d\n", ret); 29 - return 1; 30 + return T_EXIT_FAIL; 30 31 } 31 32 32 33 evfd[0] = eventfd(0, EFD_CLOEXEC); 33 34 evfd[1] = eventfd(0, EFD_CLOEXEC); 34 35 if (evfd[0] < 0 || evfd[1] < 0) { 35 36 perror("eventfd"); 36 - return 1; 37 + return T_EXIT_FAIL; 37 38 } 38 39 39 40 ret = io_uring_register_eventfd(&ring, evfd[0]); 40 41 if (ret) { 41 42 fprintf(stderr, "failed to register evfd: %d\n", ret); 42 - return 1; 43 + return T_EXIT_FAIL; 43 44 } 44 45 45 46 /* Check that registrering again will get -EBUSY */ 46 47 ret = io_uring_register_eventfd(&ring, evfd[1]); 47 48 if (ret != -EBUSY) { 48 49 fprintf(stderr, "unexpected 2nd register: %d\n", ret); 49 - return 1; 50 + return T_EXIT_FAIL; 50 51 } 51 52 close(evfd[1]); 52 53 53 54 ret = io_uring_unregister_eventfd(&ring); 54 55 if (ret) { 55 56 fprintf(stderr, "unexpected unregister: %d\n", ret); 56 - return 1; 57 + return T_EXIT_FAIL; 57 58 } 58 59 59 60 /* loop 100 registers/unregister */ ··· 61 62 ret = io_uring_register_eventfd(&ring, evfd[0]); 62 63 if (ret) { 63 64 fprintf(stderr, "failed to register evfd: %d\n", ret); 64 - return 1; 65 + return T_EXIT_FAIL; 65 66 } 66 67 67 68 ret = io_uring_unregister_eventfd(&ring); 68 69 if (ret) { 69 70 fprintf(stderr, "unexpected unregister: %d\n", ret); 70 - return 1; 71 + return T_EXIT_FAIL; 71 72 } 72 73 } 73 74 74 75 close(evfd[0]); 75 - return 0; 76 + return T_EXIT_PASS; 76 77 }
+13 -12
vendor/liburing/test/eventfd-ring.c
··· 13 13 #include <sys/eventfd.h> 14 14 15 15 #include "liburing.h" 16 + #include "helpers.h" 16 17 17 18 int main(int argc, char *argv[]) 18 19 { ··· 22 23 int ret, evfd1, evfd2; 23 24 24 25 if (argc > 1) 25 - return 0; 26 + return T_EXIT_SKIP; 26 27 27 28 ret = io_uring_queue_init_params(8, &ring1, &p); 28 29 if (ret) { 29 30 fprintf(stderr, "ring setup failed: %d\n", ret); 30 - return 1; 31 + return T_EXIT_FAIL; 31 32 } 32 33 if (!(p.features & IORING_FEAT_CUR_PERSONALITY)) { 33 34 fprintf(stdout, "Skipping\n"); 34 - return 0; 35 + return T_EXIT_SKIP; 35 36 } 36 37 ret = io_uring_queue_init(8, &ring2, 0); 37 38 if (ret) { 38 39 fprintf(stderr, "ring setup failed: %d\n", ret); 39 - return 1; 40 + return T_EXIT_FAIL; 40 41 } 41 42 42 43 evfd1 = eventfd(0, EFD_CLOEXEC); 43 44 if (evfd1 < 0) { 44 45 perror("eventfd"); 45 - return 1; 46 + return T_EXIT_FAIL; 46 47 } 47 48 48 49 evfd2 = eventfd(0, EFD_CLOEXEC); 49 50 if (evfd2 < 0) { 50 51 perror("eventfd"); 51 - return 1; 52 + return T_EXIT_FAIL; 52 53 } 53 54 54 55 ret = io_uring_register_eventfd(&ring1, evfd1); 55 56 if (ret) { 56 57 fprintf(stderr, "failed to register evfd: %d\n", ret); 57 - return 1; 58 + return T_EXIT_FAIL; 58 59 } 59 60 60 61 ret = io_uring_register_eventfd(&ring2, evfd2); 61 62 if (ret) { 62 63 fprintf(stderr, "failed to register evfd: %d\n", ret); 63 - return 1; 64 + return T_EXIT_FAIL; 64 65 } 65 66 66 67 sqe = io_uring_get_sqe(&ring1); ··· 74 75 ret = io_uring_submit(&ring1); 75 76 if (ret != 1) { 76 77 fprintf(stderr, "submit: %d\n", ret); 77 - return 1; 78 + return T_EXIT_FAIL; 78 79 } 79 80 80 81 ret = io_uring_submit(&ring2); 81 82 if (ret != 1) { 82 83 fprintf(stderr, "submit: %d\n", ret); 83 - return 1; 84 + return T_EXIT_FAIL; 84 85 } 85 86 86 87 sqe = io_uring_get_sqe(&ring1); ··· 90 91 ret = io_uring_submit(&ring1); 91 92 if (ret != 1) { 92 93 fprintf(stderr, "submit: %d\n", ret); 93 - return 1; 94 + return T_EXIT_FAIL; 94 95 } 95 96 96 - return 0; 97 + return T_EXIT_PASS; 97 98 }
+13 -12
vendor/liburing/test/eventfd.c
··· 13 13 #include <sys/eventfd.h> 14 14 15 15 #include "liburing.h" 16 + #include "helpers.h" 16 17 17 18 int main(int argc, char *argv[]) 18 19 { ··· 28 29 int ret, evfd, i; 29 30 30 31 if (argc > 1) 31 - return 0; 32 + return T_EXIT_SKIP; 32 33 33 34 ret = io_uring_queue_init_params(8, &ring, &p); 34 35 if (ret) { 35 36 fprintf(stderr, "ring setup failed: %d\n", ret); 36 - return 1; 37 + return T_EXIT_FAIL; 37 38 } 38 39 if (!(p.features & IORING_FEAT_CUR_PERSONALITY)) { 39 40 fprintf(stdout, "Skipping\n"); 40 - return 0; 41 + return T_EXIT_SKIP; 41 42 } 42 43 43 44 evfd = eventfd(0, EFD_CLOEXEC); 44 45 if (evfd < 0) { 45 46 perror("eventfd"); 46 - return 1; 47 + return T_EXIT_FAIL; 47 48 } 48 49 49 50 ret = io_uring_register_eventfd(&ring, evfd); 50 51 if (ret) { 51 52 fprintf(stderr, "failed to register evfd: %d\n", ret); 52 - return 1; 53 + return T_EXIT_FAIL; 53 54 } 54 55 55 56 sqe = io_uring_get_sqe(&ring); ··· 65 66 ret = io_uring_submit(&ring); 66 67 if (ret != 2) { 67 68 fprintf(stderr, "submit: %d\n", ret); 68 - return 1; 69 + return T_EXIT_FAIL; 69 70 } 70 71 71 72 sqe = io_uring_get_sqe(&ring); ··· 75 76 ret = io_uring_submit(&ring); 76 77 if (ret != 1) { 77 78 fprintf(stderr, "submit: %d\n", ret); 78 - return 1; 79 + return T_EXIT_FAIL; 79 80 } 80 81 81 82 for (i = 0; i < 3; i++) { 82 83 ret = io_uring_wait_cqe(&ring, &cqe); 83 84 if (ret) { 84 85 fprintf(stderr, "wait: %d\n", ret); 85 - return 1; 86 + return T_EXIT_FAIL; 86 87 } 87 88 switch (cqe->user_data) { 88 89 case 1: 89 90 /* POLLIN */ 90 91 if (cqe->res != 1) { 91 92 fprintf(stderr, "poll: %d\n", cqe->res); 92 - return 1; 93 + return T_EXIT_FAIL; 93 94 } 94 95 break; 95 96 case 2: 96 97 if (cqe->res != sizeof(ptr)) { 97 98 fprintf(stderr, "read: %d\n", cqe->res); 98 - return 1; 99 + return T_EXIT_FAIL; 99 100 } 100 101 break; 101 102 case 3: 102 103 if (cqe->res) { 103 104 fprintf(stderr, "nop: %d\n", cqe->res); 104 - return 1; 105 + return T_EXIT_FAIL; 105 106 } 106 107 break; 107 108 } 108 109 io_uring_cqe_seen(&ring, cqe); 109 110 } 110 111 111 - return 0; 112 + return T_EXIT_PASS; 112 113 }
+1 -1
vendor/liburing/test/exit-no-cleanup.c
··· 74 74 const uint64_t n = 0x42; 75 75 76 76 if (argc > 1) 77 - return 0; 77 + return T_EXIT_SKIP; 78 78 79 79 cpus = get_nprocs(); 80 80 res = pthread_barrier_init(&init_barrier, NULL, cpus);
+3 -3
vendor/liburing/test/fadvise.c
··· 73 73 if (ret == -EINVAL || ret == -EBADF) { 74 74 fprintf(stdout, "Fadvise not supported, skipping\n"); 75 75 unlink(".fadvise.tmp"); 76 - exit(0); 76 + exit(T_EXIT_SKIP); 77 77 } else if (ret) { 78 78 fprintf(stderr, "cqe->res=%d\n", cqe->res); 79 79 } ··· 194 194 if (fname != argv[1]) 195 195 unlink(fname); 196 196 io_uring_queue_exit(&ring); 197 - return 0; 197 + return T_EXIT_PASS; 198 198 err: 199 199 if (fname != argv[1]) 200 200 unlink(fname); 201 - return 1; 201 + return T_EXIT_FAIL; 202 202 }
+16 -9
vendor/liburing/test/fallocate.c
··· 14 14 #include <fcntl.h> 15 15 16 16 #include "liburing.h" 17 + #include "helpers.h" 17 18 18 19 static int no_fallocate; 19 20 ··· 66 67 if (cqe->res == -EINVAL) { 67 68 fprintf(stdout, "Fallocate not supported, skipping\n"); 68 69 no_fallocate = 1; 69 - goto out; 70 + goto skip; 70 71 } else if (cqe->res != -EFBIG) { 71 72 fprintf(stderr, "Expected -EFBIG: %d\n", cqe->res); 72 73 goto err; 73 74 } 74 75 io_uring_cqe_seen(ring, cqe); 75 - out: 76 76 return 0; 77 + skip: 78 + return T_EXIT_SKIP; 77 79 err: 78 80 return 1; 79 81 } ··· 116 118 if (cqe->res == -EINVAL) { 117 119 fprintf(stdout, "Fallocate not supported, skipping\n"); 118 120 no_fallocate = 1; 119 - goto out; 121 + goto skip; 120 122 } 121 123 if (cqe->res) { 122 124 fprintf(stderr, "cqe->res=%d\n", cqe->res); ··· 135 137 goto err; 136 138 } 137 139 138 - out: 139 140 return 0; 141 + skip: 142 + return T_EXIT_SKIP; 140 143 err: 141 144 return 1; 142 145 } ··· 219 222 int ret; 220 223 221 224 if (argc > 1) 222 - return 0; 225 + return T_EXIT_SKIP; 223 226 224 227 ret = io_uring_queue_init(8, &ring, 0); 225 228 if (ret) { 226 229 fprintf(stderr, "ring setup failed\n"); 227 - return 1; 230 + return T_EXIT_FAIL; 228 231 } 229 232 230 233 ret = test_fallocate(&ring); 231 234 if (ret) { 232 - fprintf(stderr, "test_fallocate failed\n"); 235 + if (ret != T_EXIT_SKIP) { 236 + fprintf(stderr, "test_fallocate failed\n"); 237 + } 233 238 return ret; 234 239 } 235 240 ··· 241 246 242 247 ret = test_fallocate_rlimit(&ring); 243 248 if (ret) { 244 - fprintf(stderr, "test_fallocate_rlimit failed\n"); 249 + if (ret != T_EXIT_SKIP) { 250 + fprintf(stderr, "test_fallocate_rlimit failed\n"); 251 + } 245 252 return ret; 246 253 } 247 254 248 - return 0; 255 + return T_EXIT_PASS; 249 256 }
+4 -3
vendor/liburing/test/fc2a85cb02ef.c
··· 16 16 #include <unistd.h> 17 17 18 18 #include "liburing.h" 19 + #include "helpers.h" 19 20 #include "../src/syscall.h" 20 21 21 22 static bool write_file(const char* file, const char* what, ...) ··· 83 84 int main(int argc, char *argv[]) 84 85 { 85 86 if (argc > 1) 86 - return 0; 87 + return T_EXIT_SKIP; 87 88 mmap((void *) 0x20000000ul, 0x1000000ul, 3ul, 0x32ul, -1, 0); 88 89 if (setup_fault()) { 89 90 printf("Test needs failslab/fail_futex/fail_page_alloc enabled, skipped\n"); 90 - return 0; 91 + return T_EXIT_SKIP; 91 92 } 92 93 intptr_t res = 0; 93 94 *(uint32_t*)0x20000000 = 0; ··· 127 128 *(uint32_t*)0x20000080 = r[1]; 128 129 inject_fault(1); 129 130 __sys_io_uring_register(r[0], 2ul, (const void *) 0x20000080ul, 1ul); 130 - return 0; 131 + return T_EXIT_PASS; 131 132 }
+187
vendor/liburing/test/fd-pass.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Description: run various fixed file fd passing tests 4 + * 5 + */ 6 + #include <errno.h> 7 + #include <stdio.h> 8 + #include <unistd.h> 9 + #include <stdlib.h> 10 + #include <string.h> 11 + #include <fcntl.h> 12 + 13 + #include "liburing.h" 14 + #include "helpers.h" 15 + 16 + #define FSIZE 128 17 + #define PAT 0x9a 18 + 19 + static int no_fd_pass; 20 + 21 + static int verify_fixed_read(struct io_uring *ring, int fixed_fd, int fail) 22 + { 23 + struct io_uring_sqe *sqe; 24 + struct io_uring_cqe *cqe; 25 + unsigned char buf[FSIZE]; 26 + int i; 27 + 28 + sqe = io_uring_get_sqe(ring); 29 + io_uring_prep_read(sqe, fixed_fd, buf, FSIZE, 0); 30 + sqe->flags |= IOSQE_FIXED_FILE; 31 + io_uring_submit(ring); 32 + 33 + io_uring_wait_cqe(ring, &cqe); 34 + if (cqe->res != FSIZE) { 35 + if (fail && cqe->res == -EBADF) 36 + return 0; 37 + fprintf(stderr, "Read: %d\n", cqe->res); 38 + return 1; 39 + } 40 + io_uring_cqe_seen(ring, cqe); 41 + 42 + for (i = 0; i < FSIZE; i++) { 43 + if (buf[i] != PAT) { 44 + fprintf(stderr, "got %x, wanted %x\n", buf[i], PAT); 45 + return 1; 46 + } 47 + } 48 + 49 + return 0; 50 + } 51 + 52 + static int test(const char *filename) 53 + { 54 + struct io_uring sring, dring; 55 + struct io_uring_sqe *sqe; 56 + struct io_uring_cqe *cqe; 57 + int ret; 58 + 59 + ret = io_uring_queue_init(8, &sring, 0); 60 + if (ret) { 61 + fprintf(stderr, "ring setup failed: %d\n", ret); 62 + return T_EXIT_FAIL; 63 + } 64 + ret = io_uring_queue_init(8, &dring, 0); 65 + if (ret) { 66 + fprintf(stderr, "ring setup failed: %d\n", ret); 67 + return T_EXIT_FAIL; 68 + } 69 + 70 + ret = io_uring_register_files_sparse(&sring, 8); 71 + if (ret) { 72 + if (ret == -EINVAL) 73 + return T_EXIT_SKIP; 74 + fprintf(stderr, "register files failed %d\n", ret); 75 + return T_EXIT_FAIL; 76 + } 77 + ret = io_uring_register_files_sparse(&dring, 8); 78 + if (ret) { 79 + fprintf(stderr, "register files failed %d\n", ret); 80 + return T_EXIT_FAIL; 81 + } 82 + 83 + /* open direct descriptor */ 84 + sqe = io_uring_get_sqe(&sring); 85 + io_uring_prep_openat_direct(sqe, AT_FDCWD, filename, 0, 0644, 0); 86 + io_uring_submit(&sring); 87 + ret = io_uring_wait_cqe(&sring, &cqe); 88 + if (ret) { 89 + fprintf(stderr, "wait cqe failed %d\n", ret); 90 + return T_EXIT_FAIL; 91 + } 92 + if (cqe->res) { 93 + fprintf(stderr, "cqe res %d\n", cqe->res); 94 + return T_EXIT_FAIL; 95 + } 96 + io_uring_cqe_seen(&sring, cqe); 97 + 98 + /* verify data is sane for source ring */ 99 + if (verify_fixed_read(&sring, 0, 0)) 100 + return T_EXIT_FAIL; 101 + 102 + /* send direct descriptor to destination ring */ 103 + sqe = io_uring_get_sqe(&sring); 104 + io_uring_prep_msg_ring(sqe, dring.ring_fd, 0, 0x89, 0); 105 + sqe->addr = 1; 106 + sqe->addr3 = 0; 107 + sqe->file_index = 1; 108 + io_uring_submit(&sring); 109 + 110 + ret = io_uring_wait_cqe(&sring, &cqe); 111 + if (ret) { 112 + fprintf(stderr, "wait cqe failed %d\n", ret); 113 + return T_EXIT_FAIL; 114 + } 115 + if (cqe->res) { 116 + if (cqe->res == -EINVAL && !no_fd_pass) { 117 + no_fd_pass = 1; 118 + return T_EXIT_SKIP; 119 + } 120 + fprintf(stderr, "msg_ring failed %d\n", cqe->res); 121 + return T_EXIT_FAIL; 122 + } 123 + io_uring_cqe_seen(&sring, cqe); 124 + 125 + /* get posted completion for the passing */ 126 + ret = io_uring_wait_cqe(&dring, &cqe); 127 + if (ret) { 128 + fprintf(stderr, "wait cqe failed %d\n", ret); 129 + return T_EXIT_FAIL; 130 + } 131 + if (cqe->user_data != 0x89) { 132 + fprintf(stderr, "bad user_data %ld\n", (long) cqe->res); 133 + return T_EXIT_FAIL; 134 + } 135 + io_uring_cqe_seen(&dring, cqe); 136 + 137 + /* now verify we can read the sane data from the destination ring */ 138 + if (verify_fixed_read(&dring, 0, 0)) 139 + return T_EXIT_FAIL; 140 + 141 + /* close descriptor in source ring */ 142 + sqe = io_uring_get_sqe(&sring); 143 + io_uring_prep_close_direct(sqe, 0); 144 + io_uring_submit(&sring); 145 + 146 + ret = io_uring_wait_cqe(&sring, &cqe); 147 + if (ret) { 148 + fprintf(stderr, "wait cqe failed %d\n", ret); 149 + return T_EXIT_FAIL; 150 + } 151 + if (cqe->res) { 152 + fprintf(stderr, "direct close failed %d\n", cqe->res); 153 + return T_EXIT_FAIL; 154 + } 155 + io_uring_cqe_seen(&sring, cqe); 156 + 157 + /* check that source ring fails after close */ 158 + if (verify_fixed_read(&sring, 0, 1)) 159 + return T_EXIT_FAIL; 160 + 161 + /* check we can still read from destination ring */ 162 + if (verify_fixed_read(&dring, 0, 0)) 163 + return T_EXIT_FAIL; 164 + 165 + return T_EXIT_PASS; 166 + } 167 + 168 + int main(int argc, char *argv[]) 169 + { 170 + char fname[80]; 171 + int ret; 172 + 173 + if (argc > 1) 174 + return T_EXIT_SKIP; 175 + 176 + sprintf(fname, ".fd-pass.%d", getpid()); 177 + t_create_file_pattern(fname, FSIZE, PAT); 178 + 179 + ret = test(fname); 180 + if (ret == T_EXIT_FAIL) { 181 + fprintf(stderr, "test failed\n"); 182 + ret = T_EXIT_FAIL; 183 + } 184 + 185 + unlink(fname); 186 + return ret; 187 + }
+211 -40
vendor/liburing/test/file-register.c
··· 9 9 #include <stdlib.h> 10 10 #include <string.h> 11 11 #include <fcntl.h> 12 + #include <limits.h> 12 13 #include <sys/resource.h> 13 14 14 15 #include "helpers.h" ··· 305 306 ret = io_uring_register_files(ring, files, 200); 306 307 if (ret) { 307 308 if (ret == -EBADF) { 308 - fprintf(stdout, "Sparse files not supported\n"); 309 + fprintf(stdout, "Sparse files not supported, skipping\n"); 309 310 no_update = 1; 310 311 goto done; 311 312 } ··· 830 831 return 0; 831 832 } 832 833 834 + static int file_update_alloc(struct io_uring *ring, int *fd) 835 + { 836 + struct io_uring_sqe *sqe; 837 + struct io_uring_cqe *cqe; 838 + int ret; 839 + 840 + sqe = io_uring_get_sqe(ring); 841 + io_uring_prep_files_update(sqe, fd, 1, IORING_FILE_INDEX_ALLOC); 842 + 843 + ret = io_uring_submit(ring); 844 + if (ret != 1) { 845 + fprintf(stderr, "%s: got %d, wanted 1\n", __FUNCTION__, ret); 846 + return -1; 847 + } 848 + 849 + ret = io_uring_wait_cqe(ring, &cqe); 850 + if (ret < 0) { 851 + fprintf(stderr, "%s: io_uring_wait_cqe=%d\n", __FUNCTION__, ret); 852 + return -1; 853 + } 854 + ret = cqe->res; 855 + io_uring_cqe_seen(ring, cqe); 856 + return ret; 857 + } 858 + 859 + static int test_out_of_range_file_ranges(struct io_uring *ring) 860 + { 861 + int ret; 862 + 863 + ret = io_uring_register_file_alloc_range(ring, 8, 3); 864 + if (ret != -EINVAL) { 865 + fprintf(stderr, "overlapping range %i\n", ret); 866 + return 1; 867 + } 868 + 869 + ret = io_uring_register_file_alloc_range(ring, 10, 1); 870 + if (ret != -EINVAL) { 871 + fprintf(stderr, "out of range index %i\n", ret); 872 + return 1; 873 + } 874 + 875 + ret = io_uring_register_file_alloc_range(ring, 7, ~1U); 876 + if (ret != -EOVERFLOW) { 877 + fprintf(stderr, "overflow %i\n", ret); 878 + return 1; 879 + } 880 + 881 + return 0; 882 + } 883 + 884 + static int test_overallocating_file_range(struct io_uring *ring, int fds[2]) 885 + { 886 + int roff = 7, rlen = 2; 887 + int ret, i, fd; 888 + 889 + ret = io_uring_register_file_alloc_range(ring, roff, rlen); 890 + if (ret) { 891 + fprintf(stderr, "io_uring_register_file_alloc_range %i\n", ret); 892 + return 1; 893 + } 894 + 895 + for (i = 0; i < rlen; i++) { 896 + fd = fds[0]; 897 + ret = file_update_alloc(ring, &fd); 898 + if (ret != 1) { 899 + fprintf(stderr, "file_update_alloc\n"); 900 + return 1; 901 + } 902 + 903 + if (fd < roff || fd >= roff + rlen) { 904 + fprintf(stderr, "invalid off result %i\n", fd); 905 + return 1; 906 + } 907 + } 908 + 909 + fd = fds[0]; 910 + ret = file_update_alloc(ring, &fd); 911 + if (ret != -ENFILE) { 912 + fprintf(stderr, "overallocated %i, off %i\n", ret, fd); 913 + return 1; 914 + } 915 + 916 + return 0; 917 + } 918 + 919 + static int test_zero_range_alloc(struct io_uring *ring, int fds[2]) 920 + { 921 + int ret, fd; 922 + 923 + ret = io_uring_register_file_alloc_range(ring, 7, 0); 924 + if (ret) { 925 + fprintf(stderr, "io_uring_register_file_alloc_range failed %i\n", ret); 926 + return 1; 927 + } 928 + 929 + fd = fds[0]; 930 + ret = file_update_alloc(ring, &fd); 931 + if (ret != -ENFILE) { 932 + fprintf(stderr, "zero alloc %i\n", ret); 933 + return 1; 934 + } 935 + return 0; 936 + } 937 + 938 + static int test_file_alloc_ranges(void) 939 + { 940 + struct io_uring ring; 941 + int ret, pipe_fds[2]; 942 + 943 + if (pipe(pipe_fds)) { 944 + fprintf(stderr, "pipes\n"); 945 + return 1; 946 + } 947 + ret = io_uring_queue_init(8, &ring, 0); 948 + if (ret) { 949 + fprintf(stderr, "queue_init: %d\n", ret); 950 + return 1; 951 + } 952 + 953 + ret = io_uring_register_files_sparse(&ring, 10); 954 + if (ret == -EINVAL) { 955 + not_supported: 956 + close(pipe_fds[0]); 957 + close(pipe_fds[1]); 958 + io_uring_queue_exit(&ring); 959 + printf("file alloc ranges are not supported, skip\n"); 960 + return 0; 961 + } else if (ret) { 962 + fprintf(stderr, "io_uring_register_files_sparse %i\n", ret); 963 + return ret; 964 + } 965 + 966 + ret = io_uring_register_file_alloc_range(&ring, 0, 1); 967 + if (ret) { 968 + if (ret == -EINVAL) 969 + goto not_supported; 970 + fprintf(stderr, "io_uring_register_file_alloc_range %i\n", ret); 971 + return 1; 972 + } 973 + 974 + ret = test_overallocating_file_range(&ring, pipe_fds); 975 + if (ret) { 976 + fprintf(stderr, "test_overallocating_file_range() failed\n"); 977 + return 1; 978 + } 979 + 980 + ret = test_out_of_range_file_ranges(&ring); 981 + if (ret) { 982 + fprintf(stderr, "test_out_of_range_file_ranges() failed\n"); 983 + return 1; 984 + } 985 + 986 + ret = test_zero_range_alloc(&ring, pipe_fds); 987 + if (ret) { 988 + fprintf(stderr, "test_zero_range_alloc() failed\n"); 989 + return 1; 990 + } 991 + 992 + close(pipe_fds[0]); 993 + close(pipe_fds[1]); 994 + io_uring_queue_exit(&ring); 995 + return 0; 996 + } 997 + 833 998 int main(int argc, char *argv[]) 834 999 { 835 1000 struct io_uring ring; 836 1001 int ret; 837 1002 838 1003 if (argc > 1) 839 - return 0; 1004 + return T_EXIT_SKIP; 840 1005 841 1006 ret = io_uring_queue_init(8, &ring, 0); 842 1007 if (ret) { 843 - printf("ring setup failed\n"); 844 - return 1; 1008 + fprintf(stderr, "ring setup failed\n"); 1009 + return T_EXIT_FAIL; 845 1010 } 846 1011 847 1012 ret = test_basic(&ring, 0); 848 1013 if (ret) { 849 - printf("test_basic failed\n"); 850 - return ret; 1014 + fprintf(stderr, "test_basic failed\n"); 1015 + return T_EXIT_FAIL; 851 1016 } 852 1017 853 1018 ret = test_basic(&ring, 1); 854 1019 if (ret) { 855 - printf("test_basic failed\n"); 856 - return ret; 1020 + fprintf(stderr, "test_basic failed\n"); 1021 + return T_EXIT_FAIL; 857 1022 } 858 1023 859 1024 ret = test_basic_many(&ring); 860 1025 if (ret) { 861 - printf("test_basic_many failed\n"); 862 - return ret; 1026 + fprintf(stderr, "test_basic_many failed\n"); 1027 + return T_EXIT_FAIL; 863 1028 } 864 1029 865 1030 ret = test_sparse(&ring); 866 1031 if (ret) { 867 - printf("test_sparse failed\n"); 868 - return ret; 1032 + fprintf(stderr, "test_sparse failed\n"); 1033 + return T_EXIT_FAIL; 869 1034 } 870 1035 871 1036 if (no_update) 872 - return 0; 1037 + return T_EXIT_SKIP; 873 1038 874 1039 ret = test_additions(&ring); 875 1040 if (ret) { 876 - printf("test_additions failed\n"); 877 - return ret; 1041 + fprintf(stderr, "test_additions failed\n"); 1042 + return T_EXIT_FAIL; 878 1043 } 879 1044 880 1045 ret = test_removals(&ring); 881 1046 if (ret) { 882 - printf("test_removals failed\n"); 883 - return ret; 1047 + fprintf(stderr, "test_removals failed\n"); 1048 + return T_EXIT_FAIL; 884 1049 } 885 1050 886 1051 ret = test_replace(&ring); 887 1052 if (ret) { 888 - printf("test_replace failed\n"); 889 - return ret; 1053 + fprintf(stderr, "test_replace failed\n"); 1054 + return T_EXIT_FAIL; 890 1055 } 891 1056 892 1057 ret = test_replace_all(&ring); 893 1058 if (ret) { 894 - printf("test_replace_all failed\n"); 895 - return ret; 1059 + fprintf(stderr, "test_replace_all failed\n"); 1060 + return T_EXIT_FAIL; 896 1061 } 897 1062 898 1063 ret = test_grow(&ring); 899 1064 if (ret) { 900 - printf("test_grow failed\n"); 901 - return ret; 1065 + fprintf(stderr, "test_grow failed\n"); 1066 + return T_EXIT_FAIL; 902 1067 } 903 1068 904 1069 ret = test_shrink(&ring); 905 1070 if (ret) { 906 - printf("test_shrink failed\n"); 907 - return ret; 1071 + fprintf(stderr, "test_shrink failed\n"); 1072 + return T_EXIT_FAIL; 908 1073 } 909 1074 910 1075 ret = test_zero(&ring); 911 1076 if (ret) { 912 - printf("test_zero failed\n"); 913 - return ret; 1077 + fprintf(stderr, "test_zero failed\n"); 1078 + return T_EXIT_FAIL; 914 1079 } 915 1080 916 1081 ret = test_huge(&ring); 917 1082 if (ret) { 918 - printf("test_huge failed\n"); 919 - return ret; 1083 + fprintf(stderr, "test_huge failed\n"); 1084 + return T_EXIT_FAIL; 920 1085 } 921 1086 922 1087 ret = test_skip(&ring); 923 1088 if (ret) { 924 - printf("test_skip failed\n"); 925 - return 1; 1089 + fprintf(stderr, "test_skip failed\n"); 1090 + return T_EXIT_FAIL; 926 1091 } 927 1092 928 1093 ret = test_sparse_updates(); 929 1094 if (ret) { 930 - printf("test_sparse_updates failed\n"); 931 - return ret; 1095 + fprintf(stderr, "test_sparse_updates failed\n"); 1096 + return T_EXIT_FAIL; 932 1097 } 933 1098 934 1099 ret = test_fixed_removal_ordering(); 935 1100 if (ret) { 936 - printf("test_fixed_removal_ordering failed\n"); 937 - return 1; 1101 + fprintf(stderr, "test_fixed_removal_ordering failed\n"); 1102 + return T_EXIT_FAIL; 938 1103 } 939 1104 940 1105 ret = test_mixed_af_unix(); 941 1106 if (ret) { 942 - printf("test_mixed_af_unix failed\n"); 943 - return 1; 1107 + fprintf(stderr, "test_mixed_af_unix failed\n"); 1108 + return T_EXIT_FAIL; 944 1109 } 945 1110 946 1111 ret = test_partial_register_fail(); 947 1112 if (ret) { 948 - printf("test_partial_register_fail failed\n"); 949 - return ret; 1113 + fprintf(stderr, "test_partial_register_fail failed\n"); 1114 + return T_EXIT_FAIL; 1115 + } 1116 + 1117 + ret = test_file_alloc_ranges(); 1118 + if (ret) { 1119 + fprintf(stderr, "test_partial_register_fail failed\n"); 1120 + return T_EXIT_FAIL; 950 1121 } 951 1122 952 - return 0; 1123 + return T_EXIT_PASS; 953 1124 }
+62 -4
vendor/liburing/test/file-update.c
··· 131 131 free(fds); 132 132 if (ret == -EINVAL) { 133 133 fprintf(stdout, "IORING_OP_FILES_UPDATE not supported, skipping\n"); 134 - return 0; 134 + return T_EXIT_SKIP; 135 135 } 136 136 return ret != 10; 137 137 } 138 138 139 + static int test_update_no_table(void) 140 + { 141 + int up_fd, fds[4] = {-1, 0, 1, 4}; 142 + struct io_uring_sqe *sqe; 143 + struct io_uring_cqe *cqe; 144 + struct io_uring ring; 145 + int ret; 146 + 147 + ret = t_create_ring(2, &ring, 0); 148 + if (ret == T_SETUP_SKIP) 149 + return T_EXIT_SKIP; 150 + else if (ret != T_SETUP_OK) 151 + return ret; 152 + 153 + ret = io_uring_register_files(&ring, fds, 4); 154 + /* ignore other failures */ 155 + if (ret && ret != -EBADF) { 156 + fprintf(stderr, "Failed registering file table: %d\n", ret); 157 + goto fail; 158 + } 159 + 160 + sqe = io_uring_get_sqe(&ring); 161 + up_fd = ring.ring_fd; 162 + io_uring_prep_files_update(sqe, &up_fd, 1, -1); //offset = -1 163 + ret = io_uring_submit(&ring); 164 + if (ret != 1) { 165 + fprintf(stderr, "Failed submit: %d\n", ret); 166 + goto fail; 167 + } 168 + 169 + ret = io_uring_wait_cqe(&ring, &cqe); 170 + if (ret) { 171 + fprintf(stderr, "Failed wait: %d\n", ret); 172 + goto fail; 173 + } 174 + ret = cqe->res; 175 + io_uring_cqe_seen(&ring, cqe); 176 + if (ret != -EMFILE && ret != -EINVAL && ret != -EOVERFLOW && 177 + ret != -ENXIO) { 178 + fprintf(stderr, "Bad cqe res: %d\n", ret); 179 + goto fail; 180 + } 181 + 182 + io_uring_queue_exit(&ring); 183 + return T_EXIT_PASS; 184 + fail: 185 + io_uring_queue_exit(&ring); 186 + return T_EXIT_FAIL; 187 + } 188 + 139 189 int main(int argc, char *argv[]) 140 190 { 141 191 struct io_uring r1, r2, r3; 142 192 int ret; 143 193 144 194 if (argc > 1) 145 - return 0; 195 + return T_EXIT_SKIP; 146 196 147 197 if (io_uring_queue_init(8, &r1, 0) || 148 198 io_uring_queue_init(8, &r2, 0) || ··· 165 215 166 216 ret = test_sqe_update(&r1); 167 217 if (ret) { 168 - fprintf(stderr, "test_sqe_update failed\n"); 218 + if (ret != T_EXIT_SKIP) 219 + fprintf(stderr, "test_sqe_update failed\n"); 169 220 return ret; 170 221 } 171 222 172 - return 0; 223 + ret = test_update_no_table(); 224 + if (ret) { 225 + if (ret != T_EXIT_SKIP) 226 + fprintf(stderr, "test_sqe_update failed\n"); 227 + return ret; 228 + } 229 + 230 + return T_EXIT_PASS; 173 231 }
+6 -2
vendor/liburing/test/file-verify.c
··· 430 430 fprintf(stderr, "bad read %d, read %d\n", cqe->res, i); 431 431 goto err; 432 432 } 433 + if (cqe->res < CHUNK_SIZE) { 434 + fprintf(stderr, "short read %d, read %d\n", cqe->res, i); 435 + goto err; 436 + } 433 437 if (cqe->flags & IORING_CQE_F_BUFFER) 434 438 index = cqe->flags >> 16; 435 439 else ··· 621 625 622 626 if (buf == fname) 623 627 unlink(fname); 624 - return 0; 628 + return T_EXIT_PASS; 625 629 err: 626 630 if (buf == fname) 627 631 unlink(fname); 628 - return 1; 632 + return T_EXIT_FAIL; 629 633 }
+11 -25
vendor/liburing/test/files-exit-hang-poll.c
··· 15 15 #include <unistd.h> 16 16 #include <poll.h> 17 17 #include "liburing.h" 18 + #include "helpers.h" 18 19 19 20 #define BACKLOG 512 20 - 21 - #define PORT 9100 22 21 23 22 static struct io_uring ring; 24 23 ··· 63 62 struct io_uring_cqe *cqe; 64 63 int ret, sock_listen_fd; 65 64 const int val = 1; 66 - int i; 67 65 68 66 if (argc > 1) 69 - return 0; 67 + return T_EXIT_SKIP; 70 68 71 69 sock_listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 72 70 if (sock_listen_fd < 0) { 73 71 perror("socket"); 74 - return 1; 72 + return T_EXIT_FAIL; 75 73 } 76 74 77 75 setsockopt(sock_listen_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); ··· 80 78 serv_addr.sin_family = AF_INET; 81 79 serv_addr.sin_addr.s_addr = INADDR_ANY; 82 80 83 - for (i = 0; i < 100; i++) { 84 - serv_addr.sin_port = htons(PORT + i); 85 - 86 - ret = bind(sock_listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); 87 - if (!ret) 88 - break; 89 - if (errno != EADDRINUSE) { 90 - fprintf(stderr, "bind: %s\n", strerror(errno)); 91 - return 1; 92 - } 93 - if (i == 99) { 94 - printf("Gave up on finding a port, skipping\n"); 95 - goto out; 96 - } 81 + if (t_bind_ephemeral_port(sock_listen_fd, &serv_addr)) { 82 + perror("bind"); 83 + return T_EXIT_FAIL; 97 84 } 98 85 99 86 if (listen(sock_listen_fd, BACKLOG) < 0) { 100 87 perror("Error listening on socket\n"); 101 - return 1; 88 + return T_EXIT_FAIL; 102 89 } 103 90 104 91 if (setup_io_uring()) 105 - return 1; 92 + return T_EXIT_FAIL; 106 93 107 94 add_poll(&ring, sock_listen_fd); 108 95 add_accept(&ring, sock_listen_fd); ··· 110 97 ret = io_uring_submit(&ring); 111 98 if (ret != 2) { 112 99 fprintf(stderr, "submit=%d\n", ret); 113 - return 1; 100 + return T_EXIT_FAIL; 114 101 } 115 102 116 103 signal(SIGALRM, alarm_sig); ··· 119 106 ret = io_uring_wait_cqe(&ring, &cqe); 120 107 if (ret) { 121 108 fprintf(stderr, "wait_cqe=%d\n", ret); 122 - return 1; 109 + return T_EXIT_FAIL; 123 110 } 124 111 125 - out: 126 112 io_uring_queue_exit(&ring); 127 - return 0; 113 + return T_EXIT_PASS; 128 114 }
+13 -10
vendor/liburing/test/files-exit-hang-timeout.c
··· 15 15 #include <unistd.h> 16 16 #include <poll.h> 17 17 #include "liburing.h" 18 + #include "helpers.h" 18 19 19 20 #define BACKLOG 512 20 21 ··· 72 73 int i; 73 74 74 75 if (argc > 1) 75 - return 0; 76 + return T_EXIT_SKIP; 76 77 77 78 sock_listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); 78 79 if (sock_listen_fd < 0) { 79 80 perror("socket"); 80 - return 1; 81 + return T_EXIT_FAIL; 81 82 } 82 83 83 84 setsockopt(sock_listen_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); ··· 94 95 break; 95 96 if (errno != EADDRINUSE) { 96 97 fprintf(stderr, "bind: %s\n", strerror(errno)); 97 - return 1; 98 + return T_EXIT_FAIL; 98 99 } 99 100 if (i == 99) { 100 101 printf("Gave up on finding a port, skipping\n"); 101 - goto out; 102 + goto skip; 102 103 } 103 104 } 104 105 105 106 if (listen(sock_listen_fd, BACKLOG) < 0) { 106 107 perror("Error listening on socket\n"); 107 - return 1; 108 + return T_EXIT_FAIL; 108 109 } 109 110 110 111 if (setup_io_uring()) 111 - return 1; 112 + return T_EXIT_FAIL; 112 113 113 114 add_timeout(&ring, sock_listen_fd); 114 115 add_accept(&ring, sock_listen_fd); ··· 116 117 ret = io_uring_submit(&ring); 117 118 if (ret != 2) { 118 119 fprintf(stderr, "submit=%d\n", ret); 119 - return 1; 120 + return T_EXIT_FAIL; 120 121 } 121 122 122 123 signal(SIGALRM, alarm_sig); ··· 125 126 ret = io_uring_wait_cqe(&ring, &cqe); 126 127 if (ret) { 127 128 fprintf(stderr, "wait_cqe=%d\n", ret); 128 - return 1; 129 + return T_EXIT_FAIL; 129 130 } 130 131 131 - out: 132 + io_uring_queue_exit(&ring); 133 + return T_EXIT_PASS; 134 + skip: 132 135 io_uring_queue_exit(&ring); 133 - return 0; 136 + return T_EXIT_SKIP; 134 137 }
+5 -5
vendor/liburing/test/fixed-buf-iter.c
··· 96 96 int ret; 97 97 98 98 if (argc > 1) 99 - return 0; 99 + return T_EXIT_SKIP; 100 100 101 101 ret = t_create_ring(8, &ring, 0); 102 102 if (ret == T_SETUP_SKIP) 103 - return 0; 103 + return T_EXIT_SKIP; 104 104 else if (ret < 0) 105 - return 1; 105 + return T_EXIT_FAIL; 106 106 107 107 ret = test(&ring); 108 108 if (ret) { 109 109 fprintf(stderr, "Test failed\n"); 110 - return 1; 110 + return T_EXIT_FAIL; 111 111 } 112 112 113 113 io_uring_queue_exit(&ring); 114 - return 0; 114 + return T_EXIT_PASS; 115 115 }
+10 -10
vendor/liburing/test/fixed-link.c
··· 19 19 int i, fd, ret; 20 20 21 21 if (argc > 1) 22 - return 0; 22 + return T_EXIT_SKIP; 23 23 24 24 fd = open("/dev/zero", O_RDONLY); 25 25 if (fd < 0) { 26 26 fprintf(stderr, "Failed to open /dev/zero\n"); 27 - return 1; 27 + return T_EXIT_FAIL; 28 28 } 29 29 30 30 if (io_uring_queue_init(32, &ring, 0) < 0) { 31 - fprintf(stderr, "Faild to init io_uring\n"); 31 + fprintf(stderr, "Failed to init io_uring\n"); 32 32 close(fd); 33 - return 1; 33 + return T_EXIT_FAIL; 34 34 } 35 35 36 36 for (i = 0; i < IOVECS_LEN; ++i) { ··· 41 41 ret = io_uring_register_buffers(&ring, iovecs, IOVECS_LEN); 42 42 if (ret) { 43 43 fprintf(stderr, "Failed to register buffers\n"); 44 - return 1; 44 + return T_EXIT_FAIL; 45 45 } 46 46 47 47 for (i = 0; i < IOVECS_LEN; ++i) { ··· 58 58 ret = io_uring_submit_and_wait(&ring, IOVECS_LEN); 59 59 if (ret < 0) { 60 60 fprintf(stderr, "Failed to submit IO\n"); 61 - return 1; 61 + return T_EXIT_FAIL; 62 62 } else if (ret < 2) { 63 63 fprintf(stderr, "Submitted %d, wanted %d\n", ret, IOVECS_LEN); 64 - return 1; 64 + return T_EXIT_FAIL; 65 65 } 66 66 67 67 for (i = 0; i < IOVECS_LEN; i++) { ··· 70 70 ret = io_uring_wait_cqe(&ring, &cqe); 71 71 if (ret) { 72 72 fprintf(stderr, "wait_cqe=%d\n", ret); 73 - return 1; 73 + return T_EXIT_FAIL; 74 74 } 75 75 if (cqe->res != iovecs[i].iov_len) { 76 76 fprintf(stderr, "read: wanted %ld, got %d\n", 77 77 (long) iovecs[i].iov_len, cqe->res); 78 - return 1; 78 + return T_EXIT_FAIL; 79 79 } 80 80 io_uring_cqe_seen(&ring, cqe); 81 81 } ··· 86 86 for (i = 0; i < IOVECS_LEN; ++i) 87 87 free(iovecs[i].iov_base); 88 88 89 - return 0; 89 + return T_EXIT_PASS; 90 90 }
+6 -6
vendor/liburing/test/fixed-reuse.c
··· 124 124 int ret, files[MAX_FILES]; 125 125 126 126 if (argc > 1) 127 - return 0; 127 + return T_EXIT_SKIP; 128 128 129 129 ret = io_uring_queue_init_params(8, &ring, &p); 130 130 if (ret) { 131 131 fprintf(stderr, "ring setup failed: %d\n", ret); 132 - return 1; 132 + return T_EXIT_FAIL; 133 133 } 134 134 if (!(p.features & IORING_FEAT_CQE_SKIP)) 135 - return 0; 135 + return T_EXIT_SKIP; 136 136 137 137 memset(files, -1, sizeof(files)); 138 138 ret = io_uring_register_files(&ring, files, ARRAY_SIZE(files)); 139 139 if (ret) { 140 140 fprintf(stderr, "Failed registering files\n"); 141 - return 1; 141 + return T_EXIT_FAIL; 142 142 } 143 143 144 144 t_create_file_pattern(FNAME1, 4096, PAT1); ··· 152 152 153 153 unlink(FNAME1); 154 154 unlink(FNAME2); 155 - return 0; 155 + return T_EXIT_PASS; 156 156 err: 157 157 unlink(FNAME1); 158 158 unlink(FNAME2); 159 - return 1; 159 + return T_EXIT_FAIL; 160 160 }
+6 -3
vendor/liburing/test/fpos.c
··· 52 52 unsigned char buff[QUEUE_SIZE * blocksize]; 53 53 unsigned char reordered[QUEUE_SIZE * blocksize]; 54 54 55 + memset(buff, 0, QUEUE_SIZE * blocksize); 56 + memset(reordered, 0, QUEUE_SIZE * blocksize); 57 + 55 58 create_file(".test_fpos_read", FILE_SIZE); 56 59 fd = open(".test_fpos_read", O_RDONLY); 57 60 unlink(".test_fpos_read"); ··· 225 228 int ret; 226 229 227 230 if (argc > 1) 228 - return 0; 231 + return T_EXIT_SKIP; 229 232 230 233 ret = io_uring_queue_init(QUEUE_SIZE, &ring, 0); 231 234 if (ret) { 232 235 fprintf(stderr, "ring setup failed\n"); 233 - return 1; 236 + return T_EXIT_FAIL; 234 237 } 235 238 236 239 for (int test = 0; test < 8; test++) { ··· 248 251 return -1; 249 252 } 250 253 } 251 - return 0; 254 + return T_EXIT_PASS; 252 255 }
+3 -3
vendor/liburing/test/fsync.c
··· 193 193 int ret; 194 194 195 195 if (argc > 1) 196 - return 0; 196 + return T_EXIT_SKIP; 197 197 198 198 ret = io_uring_queue_init(8, &ring, 0); 199 199 if (ret) { 200 200 fprintf(stderr, "ring setup failed\n"); 201 - return 1; 201 + return T_EXIT_FAIL; 202 202 203 203 } 204 204 ··· 220 220 return ret; 221 221 } 222 222 223 - return 0; 223 + return T_EXIT_PASS; 224 224 }
+10 -6
vendor/liburing/test/hardlink.c
··· 10 10 #include <unistd.h> 11 11 12 12 #include "liburing.h" 13 + #include "helpers.h" 13 14 14 15 15 16 static int do_linkat(struct io_uring *ring, const char *oldname, const char *newname) ··· 74 75 struct io_uring ring; 75 76 76 77 if (argc > 1) 77 - return 0; 78 + return T_EXIT_SKIP; 78 79 79 80 ret = io_uring_queue_init(8, &ring, 0); 80 81 if (ret) { ··· 97 98 if (ret < 0) { 98 99 if (ret == -EBADF || ret == -EINVAL) { 99 100 fprintf(stdout, "linkat not supported, skipping\n"); 100 - goto out; 101 + goto skip; 101 102 } 102 103 fprintf(stderr, "linkat: %s\n", strerror(-ret)); 103 104 goto err1; ··· 120 121 goto err2; 121 122 } 122 123 123 - out: 124 + unlinkat(AT_FDCWD, linkname, 0); 125 + unlinkat(AT_FDCWD, target, 0); 126 + io_uring_queue_exit(&ring); 127 + return T_EXIT_PASS; 128 + skip: 124 129 unlinkat(AT_FDCWD, linkname, 0); 125 130 unlinkat(AT_FDCWD, target, 0); 126 131 io_uring_queue_exit(&ring); 127 - return 0; 132 + return T_EXIT_SKIP; 128 133 err2: 129 134 unlinkat(AT_FDCWD, linkname, 0); 130 135 err1: 131 136 unlinkat(AT_FDCWD, target, 0); 132 137 err: 133 138 io_uring_queue_exit(&ring); 134 - return 1; 139 + return T_EXIT_FAIL; 135 140 } 136 -
+125 -2
vendor/liburing/test/helpers.c
··· 10 10 #include <unistd.h> 11 11 #include <sys/types.h> 12 12 13 + #include <arpa/inet.h> 14 + #include <netinet/ip.h> 15 + #include <netinet/tcp.h> 16 + 13 17 #include "helpers.h" 14 18 #include "liburing.h" 15 19 ··· 25 29 } 26 30 27 31 /* 32 + * Helper for binding socket to an ephemeral port. 33 + * The port number to be bound is returned in @addr->sin_port. 34 + */ 35 + int t_bind_ephemeral_port(int fd, struct sockaddr_in *addr) 36 + { 37 + socklen_t addrlen; 38 + 39 + addr->sin_port = 0; 40 + if (bind(fd, (struct sockaddr *)addr, sizeof(*addr))) 41 + return -errno; 42 + 43 + addrlen = sizeof(*addr); 44 + assert(!getsockname(fd, (struct sockaddr *)addr, &addrlen)); 45 + assert(addr->sin_port != 0); 46 + return 0; 47 + } 48 + 49 + /* 28 50 * Helper for allocating size bytes aligned on a boundary. 29 51 */ 30 52 void t_posix_memalign(void **memptr, size_t alignment, size_t size) ··· 53 75 { 54 76 ssize_t ret; 55 77 char *buf; 56 - int fd; 78 + int fd; 57 79 58 80 buf = t_malloc(size); 59 81 memset(buf, pattern, size); ··· 90 112 vecs = t_malloc(buf_num * sizeof(struct iovec)); 91 113 for (i = 0; i < buf_num; i++) { 92 114 t_posix_memalign(&vecs[i].iov_base, buf_size, buf_size); 93 - vecs[i].iov_len = buf_size; 115 + vecs[i].iov_len = buf_size; 94 116 } 95 117 return vecs; 96 118 } ··· 143 165 fprintf(stderr, "buffer register failed: %s\n", strerror(-ret)); 144 166 return ret; 145 167 } 168 + 169 + int t_create_socket_pair(int fd[2], bool stream) 170 + { 171 + int ret; 172 + int type = stream ? SOCK_STREAM : SOCK_DGRAM; 173 + int val; 174 + struct sockaddr_in serv_addr; 175 + struct sockaddr *paddr; 176 + size_t paddrlen; 177 + 178 + type |= SOCK_CLOEXEC; 179 + fd[0] = socket(AF_INET, type, 0); 180 + if (fd[0] < 0) 181 + return errno; 182 + fd[1] = socket(AF_INET, type, 0); 183 + if (fd[1] < 0) { 184 + ret = errno; 185 + close(fd[0]); 186 + return ret; 187 + } 188 + 189 + val = 1; 190 + if (setsockopt(fd[0], SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))) 191 + goto errno_cleanup; 192 + 193 + memset(&serv_addr, 0, sizeof(serv_addr)); 194 + serv_addr.sin_family = AF_INET; 195 + serv_addr.sin_port = 0; 196 + inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); 197 + 198 + paddr = (struct sockaddr *)&serv_addr; 199 + paddrlen = sizeof(serv_addr); 200 + 201 + if (bind(fd[0], paddr, paddrlen)) { 202 + fprintf(stderr, "bind failed\n"); 203 + goto errno_cleanup; 204 + } 205 + 206 + if (stream && listen(fd[0], 16)) { 207 + fprintf(stderr, "listen failed\n"); 208 + goto errno_cleanup; 209 + } 210 + 211 + if (getsockname(fd[0], (struct sockaddr *)&serv_addr, 212 + (socklen_t *)&paddrlen)) { 213 + fprintf(stderr, "getsockname failed\n"); 214 + goto errno_cleanup; 215 + } 216 + inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); 217 + 218 + if (connect(fd[1], (struct sockaddr *)&serv_addr, paddrlen)) { 219 + fprintf(stderr, "connect failed\n"); 220 + goto errno_cleanup; 221 + } 222 + 223 + if (!stream) { 224 + /* connect the other udp side */ 225 + if (getsockname(fd[1], (struct sockaddr *)&serv_addr, 226 + (socklen_t *)&paddrlen)) { 227 + fprintf(stderr, "getsockname failed\n"); 228 + goto errno_cleanup; 229 + } 230 + inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); 231 + 232 + if (connect(fd[0], (struct sockaddr *)&serv_addr, paddrlen)) { 233 + fprintf(stderr, "connect failed\n"); 234 + goto errno_cleanup; 235 + } 236 + return 0; 237 + } 238 + 239 + /* for stream case we must accept and cleanup the listen socket */ 240 + 241 + ret = accept(fd[0], NULL, NULL); 242 + if (ret < 0) 243 + goto errno_cleanup; 244 + 245 + close(fd[0]); 246 + fd[0] = ret; 247 + 248 + return 0; 249 + 250 + errno_cleanup: 251 + ret = errno; 252 + close(fd[0]); 253 + close(fd[1]); 254 + return ret; 255 + } 256 + 257 + bool t_probe_defer_taskrun(void) 258 + { 259 + struct io_uring ring; 260 + int ret; 261 + 262 + ret = io_uring_queue_init(1, &ring, IORING_SETUP_SINGLE_ISSUER | 263 + IORING_SETUP_DEFER_TASKRUN); 264 + if (ret < 0) 265 + return false; 266 + io_uring_queue_exit(&ring); 267 + return true; 268 + }
+21
vendor/liburing/test/helpers.h
··· 10 10 #endif 11 11 12 12 #include "liburing.h" 13 + #include <arpa/inet.h> 13 14 14 15 enum t_setup_ret { 15 16 T_SETUP_OK = 0, 16 17 T_SETUP_SKIP, 17 18 }; 19 + 20 + enum t_test_result { 21 + T_EXIT_PASS = 0, 22 + T_EXIT_FAIL = 1, 23 + T_EXIT_SKIP = 77, 24 + }; 25 + 26 + /* 27 + * Helper for binding socket to an ephemeral port. 28 + * The port number to be bound is returned in @addr->sin_port. 29 + */ 30 + int t_bind_ephemeral_port(int fd, struct sockaddr_in *addr); 31 + 18 32 19 33 /* 20 34 * Helper for allocating memory in tests. ··· 53 67 struct iovec *t_create_buffers(size_t buf_num, size_t buf_size); 54 68 55 69 /* 70 + * Helper for creating connected socket pairs 71 + */ 72 + int t_create_socket_pair(int fd[2], bool stream); 73 + 74 + /* 56 75 * Helper for setting up a ring and checking for user privs 57 76 */ 58 77 enum t_setup_ret t_create_ring_params(int depth, struct io_uring *ring, ··· 63 82 enum t_setup_ret t_register_buffers(struct io_uring *ring, 64 83 const struct iovec *iovecs, 65 84 unsigned nr_iovecs); 85 + 86 + bool t_probe_defer_taskrun(void); 66 87 67 88 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 68 89
+13 -8
vendor/liburing/test/io-cancel.c
··· 365 365 exit(0); 366 366 } else { 367 367 int wstatus; 368 + pid_t childpid; 368 369 369 - if (waitpid(p, &wstatus, 0) == (pid_t)-1) { 370 + do { 371 + childpid = waitpid(p, &wstatus, 0); 372 + } while (childpid == (pid_t)-1 && errno == EINTR); 373 + 374 + if (childpid == (pid_t)-1) { 370 375 perror("waitpid()"); 371 376 return 1; 372 377 } ··· 503 508 int i, ret; 504 509 505 510 if (argc > 1) 506 - return 0; 511 + return T_EXIT_SKIP; 507 512 508 513 if (test_dont_cancel_another_ring()) { 509 514 fprintf(stderr, "test_dont_cancel_another_ring() failed\n"); 510 - return 1; 515 + return T_EXIT_FAIL; 511 516 } 512 517 513 518 if (test_cancel_req_across_fork()) { 514 519 fprintf(stderr, "test_cancel_req_across_fork() failed\n"); 515 - return 1; 520 + return T_EXIT_FAIL; 516 521 } 517 522 518 523 if (test_cancel_inflight_exit()) { 519 524 fprintf(stderr, "test_cancel_inflight_exit() failed\n"); 520 - return 1; 525 + return T_EXIT_FAIL; 521 526 } 522 527 523 528 if (test_sqpoll_cancel_iowq_requests()) { 524 529 fprintf(stderr, "test_sqpoll_cancel_iowq_requests() failed\n"); 525 - return 1; 530 + return T_EXIT_FAIL; 526 531 } 527 532 528 533 t_create_file(fname, FILE_SIZE); ··· 543 548 } 544 549 545 550 unlink(fname); 546 - return 0; 551 + return T_EXIT_PASS; 547 552 err: 548 553 unlink(fname); 549 - return 1; 554 + return T_EXIT_FAIL; 550 555 }
+26 -26
vendor/liburing/test/io_uring_enter.c
··· 38 38 { 39 39 int ret; 40 40 41 - ret = __sys_io_uring_enter(fd, to_submit, min_complete, flags, sig); 42 - if (ret != -1) { 43 - fprintf(stderr, "expected %s, but call succeeded\n", strerror(error)); 41 + ret = io_uring_enter(fd, to_submit, min_complete, flags, sig); 42 + if (ret >= 0) { 43 + fprintf(stderr, "expected %s, but call succeeded\n", strerror(-error)); 44 44 return 1; 45 45 } 46 46 47 - if (errno != error) { 48 - fprintf(stderr, "expected %d, got %d\n", error, errno); 47 + if (ret != error) { 48 + fprintf(stderr, "expected %d, got %d\n", error, ret); 49 49 return 1; 50 50 } 51 51 ··· 54 54 55 55 static int try_io_uring_enter(int fd, unsigned int to_submit, 56 56 unsigned int min_complete, unsigned int flags, 57 - sigset_t *sig, int expect, int error) 57 + sigset_t *sig, int expect) 58 58 { 59 59 int ret; 60 60 61 - if (expect == -1) 62 - return expect_fail(fd, to_submit, min_complete, 63 - flags, sig, error); 61 + if (expect < 0) 62 + return expect_fail(fd, to_submit, min_complete, flags, sig, 63 + expect); 64 64 65 - ret = __sys_io_uring_enter(fd, to_submit, min_complete, flags, sig); 65 + ret = io_uring_enter(fd, to_submit, min_complete, flags, sig); 66 66 if (ret != expect) { 67 - fprintf(stderr, "Expected %d, got %d\n", expect, errno); 67 + fprintf(stderr, "Expected %d, got %d\n", expect, ret); 68 68 return 1; 69 69 } 70 70 ··· 185 185 unsigned completed, dropped; 186 186 187 187 if (argc > 1) 188 - return 0; 188 + return T_EXIT_SKIP; 189 189 190 190 ret = io_uring_queue_init(IORING_MAX_ENTRIES, &ring, 0); 191 191 if (ret == -ENOMEM) 192 192 ret = io_uring_queue_init(IORING_MAX_ENTRIES_FALLBACK, &ring, 0); 193 193 if (ret < 0) { 194 194 perror("io_uring_queue_init"); 195 - exit(1); 195 + exit(T_EXIT_FAIL); 196 196 } 197 - mask = *sq->kring_mask; 197 + mask = sq->ring_mask; 198 198 199 199 /* invalid flags */ 200 - status |= try_io_uring_enter(ring.ring_fd, 1, 0, ~0U, NULL, -1, EINVAL); 200 + status |= try_io_uring_enter(ring.ring_fd, 1, 0, ~0U, NULL, -EINVAL); 201 201 202 202 /* invalid fd, EBADF */ 203 - status |= try_io_uring_enter(-1, 0, 0, 0, NULL, -1, EBADF); 203 + status |= try_io_uring_enter(-1, 0, 0, 0, NULL, -EBADF); 204 204 205 205 /* valid, non-ring fd, EOPNOTSUPP */ 206 - status |= try_io_uring_enter(0, 0, 0, 0, NULL, -1, EOPNOTSUPP); 206 + status |= try_io_uring_enter(0, 0, 0, 0, NULL, -EOPNOTSUPP); 207 207 208 208 /* to_submit: 0, flags: 0; should get back 0. */ 209 - status |= try_io_uring_enter(ring.ring_fd, 0, 0, 0, NULL, 0, 0); 209 + status |= try_io_uring_enter(ring.ring_fd, 0, 0, 0, NULL, 0); 210 210 211 211 /* fill the sq ring */ 212 - sq_entries = *ring.sq.kring_entries; 212 + sq_entries = ring.sq.ring_entries; 213 213 submit_io(&ring, sq_entries); 214 - ret = __sys_io_uring_enter(ring.ring_fd, 0, sq_entries, 215 - IORING_ENTER_GETEVENTS, NULL); 214 + ret = io_uring_enter(ring.ring_fd, 0, sq_entries, 215 + IORING_ENTER_GETEVENTS, NULL); 216 216 if (ret < 0) { 217 - perror("io_uring_enter"); 217 + fprintf(stderr, "io_uring_enter: %s\n", strerror(-ret)); 218 218 status = 1; 219 219 } else { 220 220 /* ··· 235 235 * Add an invalid index to the submission queue. This should 236 236 * result in the dropped counter increasing. 237 237 */ 238 - index = *sq->kring_entries + 1; // invalid index 238 + index = sq->ring_entries + 1; // invalid index 239 239 dropped = *sq->kdropped; 240 240 ktail = *sq->ktail; 241 241 sq->array[ktail & mask] = index; ··· 246 246 */ 247 247 io_uring_smp_store_release(sq->ktail, ktail); 248 248 249 - ret = __sys_io_uring_enter(ring.ring_fd, 1, 0, 0, NULL); 249 + ret = io_uring_enter(ring.ring_fd, 1, 0, 0, NULL); 250 250 /* now check to see if our sqe was dropped */ 251 251 if (*sq->kdropped == dropped) { 252 252 fprintf(stderr, "dropped counter did not increase\n"); ··· 254 254 } 255 255 256 256 if (!status) 257 - return 0; 257 + return T_EXIT_PASS; 258 258 259 259 fprintf(stderr, "FAIL\n"); 260 - return -1; 260 + return T_EXIT_FAIL; 261 261 }
+451
vendor/liburing/test/io_uring_passthrough.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Description: basic read/write tests for io_uring passthrough commands 4 + */ 5 + #include <errno.h> 6 + #include <stdio.h> 7 + #include <unistd.h> 8 + #include <stdlib.h> 9 + #include <string.h> 10 + 11 + #include "helpers.h" 12 + #include "liburing.h" 13 + #include "../src/syscall.h" 14 + #include "nvme.h" 15 + 16 + #define FILE_SIZE (256 * 1024) 17 + #define BS 8192 18 + #define BUFFERS (FILE_SIZE / BS) 19 + 20 + static struct iovec *vecs; 21 + 22 + /* 23 + * Each offset in the file has the ((test_case / 2) * FILE_SIZE) 24 + * + (offset / sizeof(int)) stored for every 25 + * sizeof(int) address. 26 + */ 27 + static int verify_buf(int tc, void *buf, off_t off) 28 + { 29 + int i, u_in_buf = BS / sizeof(unsigned int); 30 + unsigned int *ptr; 31 + 32 + off /= sizeof(unsigned int); 33 + off += (tc / 2) * FILE_SIZE; 34 + ptr = buf; 35 + for (i = 0; i < u_in_buf; i++) { 36 + if (off != *ptr) { 37 + fprintf(stderr, "Found %u, wanted %lu\n", *ptr, off); 38 + return 1; 39 + } 40 + ptr++; 41 + off++; 42 + } 43 + 44 + return 0; 45 + } 46 + 47 + static int fill_pattern(int tc) 48 + { 49 + unsigned int val, *ptr; 50 + int i, j; 51 + int u_in_buf = BS / sizeof(val); 52 + 53 + val = (tc / 2) * FILE_SIZE; 54 + for (i = 0; i < BUFFERS; i++) { 55 + ptr = vecs[i].iov_base; 56 + for (j = 0; j < u_in_buf; j++) { 57 + *ptr = val; 58 + val++; 59 + ptr++; 60 + } 61 + } 62 + 63 + return 0; 64 + } 65 + 66 + static int __test_io(const char *file, struct io_uring *ring, int tc, int read, 67 + int sqthread, int fixed, int nonvec) 68 + { 69 + struct io_uring_sqe *sqe; 70 + struct io_uring_cqe *cqe; 71 + struct nvme_uring_cmd *cmd; 72 + int open_flags; 73 + int do_fixed; 74 + int i, ret, fd = -1; 75 + off_t offset; 76 + __u64 slba; 77 + __u32 nlb; 78 + 79 + if (read) 80 + open_flags = O_RDONLY; 81 + else 82 + open_flags = O_WRONLY; 83 + 84 + if (fixed) { 85 + ret = t_register_buffers(ring, vecs, BUFFERS); 86 + if (ret == T_SETUP_SKIP) 87 + return 0; 88 + if (ret != T_SETUP_OK) { 89 + fprintf(stderr, "buffer reg failed: %d\n", ret); 90 + goto err; 91 + } 92 + } 93 + 94 + fd = open(file, open_flags); 95 + if (fd < 0) { 96 + perror("file open"); 97 + goto err; 98 + } 99 + 100 + if (sqthread) { 101 + ret = io_uring_register_files(ring, &fd, 1); 102 + if (ret) { 103 + fprintf(stderr, "file reg failed: %d\n", ret); 104 + goto err; 105 + } 106 + } 107 + 108 + if (!read) 109 + fill_pattern(tc); 110 + 111 + offset = 0; 112 + for (i = 0; i < BUFFERS; i++) { 113 + sqe = io_uring_get_sqe(ring); 114 + if (!sqe) { 115 + fprintf(stderr, "sqe get failed\n"); 116 + goto err; 117 + } 118 + if (read) { 119 + int use_fd = fd; 120 + 121 + do_fixed = fixed; 122 + 123 + if (sqthread) 124 + use_fd = 0; 125 + if (fixed && (i & 1)) 126 + do_fixed = 0; 127 + if (do_fixed) { 128 + io_uring_prep_read_fixed(sqe, use_fd, vecs[i].iov_base, 129 + vecs[i].iov_len, 130 + offset, i); 131 + sqe->cmd_op = NVME_URING_CMD_IO; 132 + } else if (nonvec) { 133 + io_uring_prep_read(sqe, use_fd, vecs[i].iov_base, 134 + vecs[i].iov_len, offset); 135 + sqe->cmd_op = NVME_URING_CMD_IO; 136 + } else { 137 + io_uring_prep_readv(sqe, use_fd, &vecs[i], 1, 138 + offset); 139 + sqe->cmd_op = NVME_URING_CMD_IO_VEC; 140 + } 141 + } else { 142 + int use_fd = fd; 143 + 144 + do_fixed = fixed; 145 + 146 + if (sqthread) 147 + use_fd = 0; 148 + if (fixed && (i & 1)) 149 + do_fixed = 0; 150 + if (do_fixed) { 151 + io_uring_prep_write_fixed(sqe, use_fd, vecs[i].iov_base, 152 + vecs[i].iov_len, 153 + offset, i); 154 + sqe->cmd_op = NVME_URING_CMD_IO; 155 + } else if (nonvec) { 156 + io_uring_prep_write(sqe, use_fd, vecs[i].iov_base, 157 + vecs[i].iov_len, offset); 158 + sqe->cmd_op = NVME_URING_CMD_IO; 159 + } else { 160 + io_uring_prep_writev(sqe, use_fd, &vecs[i], 1, 161 + offset); 162 + sqe->cmd_op = NVME_URING_CMD_IO_VEC; 163 + } 164 + } 165 + sqe->opcode = IORING_OP_URING_CMD; 166 + sqe->user_data = ((uint64_t)offset << 32) | i; 167 + if (sqthread) 168 + sqe->flags |= IOSQE_FIXED_FILE; 169 + 170 + cmd = (struct nvme_uring_cmd *)sqe->cmd; 171 + memset(cmd, 0, sizeof(struct nvme_uring_cmd)); 172 + 173 + cmd->opcode = read ? nvme_cmd_read : nvme_cmd_write; 174 + 175 + slba = offset >> lba_shift; 176 + nlb = (BS >> lba_shift) - 1; 177 + 178 + /* cdw10 and cdw11 represent starting lba */ 179 + cmd->cdw10 = slba & 0xffffffff; 180 + cmd->cdw11 = slba >> 32; 181 + /* cdw12 represent number of lba's for read/write */ 182 + cmd->cdw12 = nlb; 183 + if (do_fixed || nonvec) { 184 + cmd->addr = (__u64)(uintptr_t)vecs[i].iov_base; 185 + cmd->data_len = vecs[i].iov_len; 186 + } else { 187 + cmd->addr = (__u64)(uintptr_t)&vecs[i]; 188 + cmd->data_len = 1; 189 + } 190 + cmd->nsid = nsid; 191 + 192 + offset += BS; 193 + } 194 + 195 + ret = io_uring_submit(ring); 196 + if (ret != BUFFERS) { 197 + fprintf(stderr, "submit got %d, wanted %d\n", ret, BUFFERS); 198 + goto err; 199 + } 200 + 201 + for (i = 0; i < BUFFERS; i++) { 202 + ret = io_uring_wait_cqe(ring, &cqe); 203 + if (ret) { 204 + fprintf(stderr, "wait_cqe=%d\n", ret); 205 + goto err; 206 + } 207 + if (cqe->res != 0) { 208 + fprintf(stderr, "cqe res %d, wanted 0\n", cqe->res); 209 + goto err; 210 + } 211 + io_uring_cqe_seen(ring, cqe); 212 + if (read) { 213 + int index = cqe->user_data & 0xffffffff; 214 + void *buf = vecs[index].iov_base; 215 + off_t voff = cqe->user_data >> 32; 216 + 217 + if (verify_buf(tc, buf, voff)) 218 + goto err; 219 + } 220 + } 221 + 222 + if (fixed) { 223 + ret = io_uring_unregister_buffers(ring); 224 + if (ret) { 225 + fprintf(stderr, "buffer unreg failed: %d\n", ret); 226 + goto err; 227 + } 228 + } 229 + if (sqthread) { 230 + ret = io_uring_unregister_files(ring); 231 + if (ret) { 232 + fprintf(stderr, "file unreg failed: %d\n", ret); 233 + goto err; 234 + } 235 + } 236 + 237 + close(fd); 238 + return 0; 239 + err: 240 + if (fd != -1) 241 + close(fd); 242 + return 1; 243 + } 244 + 245 + static int test_io(const char *file, int tc, int read, int sqthread, 246 + int fixed, int nonvec) 247 + { 248 + struct io_uring ring; 249 + int ret, ring_flags = 0; 250 + 251 + ring_flags |= IORING_SETUP_SQE128; 252 + ring_flags |= IORING_SETUP_CQE32; 253 + 254 + if (sqthread) 255 + ring_flags |= IORING_SETUP_SQPOLL; 256 + 257 + ret = t_create_ring(64, &ring, ring_flags); 258 + if (ret == T_SETUP_SKIP) 259 + return 0; 260 + if (ret != T_SETUP_OK) { 261 + fprintf(stderr, "ring create failed: %d\n", ret); 262 + return 1; 263 + } 264 + 265 + ret = __test_io(file, &ring, tc, read, sqthread, fixed, nonvec); 266 + io_uring_queue_exit(&ring); 267 + 268 + return ret; 269 + } 270 + 271 + extern unsigned __io_uring_flush_sq(struct io_uring *ring); 272 + 273 + /* 274 + * Send a passthrough command that nvme will fail during submission. 275 + * This comes handy for testing error handling. 276 + */ 277 + static int test_invalid_passthru_submit(const char *file) 278 + { 279 + struct io_uring ring; 280 + int fd, ret, ring_flags, open_flags; 281 + struct io_uring_cqe *cqe; 282 + struct io_uring_sqe *sqe; 283 + struct nvme_uring_cmd *cmd; 284 + 285 + ring_flags = IORING_SETUP_IOPOLL | IORING_SETUP_SQE128; 286 + ring_flags |= IORING_SETUP_CQE32; 287 + 288 + ret = t_create_ring(1, &ring, ring_flags); 289 + if (ret != T_SETUP_OK) { 290 + fprintf(stderr, "ring create failed: %d\n", ret); 291 + return 1; 292 + } 293 + 294 + open_flags = O_RDONLY; 295 + fd = open(file, open_flags); 296 + if (fd < 0) { 297 + perror("file open"); 298 + goto err; 299 + } 300 + 301 + sqe = io_uring_get_sqe(&ring); 302 + io_uring_prep_read(sqe, fd, vecs[0].iov_base, vecs[0].iov_len, 0); 303 + sqe->cmd_op = NVME_URING_CMD_IO; 304 + sqe->opcode = IORING_OP_URING_CMD; 305 + sqe->user_data = 1; 306 + cmd = (struct nvme_uring_cmd *)sqe->cmd; 307 + memset(cmd, 0, sizeof(struct nvme_uring_cmd)); 308 + cmd->opcode = nvme_cmd_read; 309 + cmd->addr = (__u64)(uintptr_t)&vecs[0].iov_base; 310 + cmd->data_len = vecs[0].iov_len; 311 + /* populate wrong nsid to force failure */ 312 + cmd->nsid = nsid + 1; 313 + 314 + ret = io_uring_submit(&ring); 315 + if (ret != 1) { 316 + fprintf(stderr, "submit got %d, wanted %d\n", ret, 1); 317 + goto err; 318 + } 319 + ret = io_uring_wait_cqe(&ring, &cqe); 320 + if (ret) { 321 + fprintf(stderr, "wait_cqe=%d\n", ret); 322 + goto err; 323 + } 324 + if (cqe->res == 0) { 325 + fprintf(stderr, "cqe res %d, wanted failure\n", cqe->res); 326 + goto err; 327 + } 328 + io_uring_cqe_seen(&ring, cqe); 329 + close(fd); 330 + io_uring_queue_exit(&ring); 331 + return 0; 332 + err: 333 + if (fd != -1) 334 + close(fd); 335 + io_uring_queue_exit(&ring); 336 + return 1; 337 + } 338 + 339 + /* 340 + * if we are polling io_uring_submit needs to always enter the 341 + * kernel to fetch events 342 + */ 343 + static int test_io_uring_submit_enters(const char *file) 344 + { 345 + struct io_uring ring; 346 + int fd, i, ret, ring_flags, open_flags; 347 + unsigned head; 348 + struct io_uring_cqe *cqe; 349 + 350 + ring_flags = IORING_SETUP_IOPOLL; 351 + ring_flags |= IORING_SETUP_SQE128; 352 + ring_flags |= IORING_SETUP_CQE32; 353 + 354 + ret = io_uring_queue_init(64, &ring, ring_flags); 355 + if (ret) { 356 + fprintf(stderr, "ring create failed: %d\n", ret); 357 + return 1; 358 + } 359 + 360 + open_flags = O_WRONLY; 361 + fd = open(file, open_flags); 362 + if (fd < 0) { 363 + perror("file open"); 364 + goto err; 365 + } 366 + 367 + for (i = 0; i < BUFFERS; i++) { 368 + struct io_uring_sqe *sqe; 369 + off_t offset = BS * (rand() % BUFFERS); 370 + 371 + sqe = io_uring_get_sqe(&ring); 372 + io_uring_prep_writev(sqe, fd, &vecs[i], 1, offset); 373 + sqe->user_data = 1; 374 + } 375 + 376 + /* submit manually to avoid adding IORING_ENTER_GETEVENTS */ 377 + ret = __sys_io_uring_enter(ring.ring_fd, __io_uring_flush_sq(&ring), 0, 378 + 0, NULL); 379 + if (ret < 0) 380 + goto err; 381 + 382 + for (i = 0; i < 500; i++) { 383 + ret = io_uring_submit(&ring); 384 + if (ret != 0) { 385 + fprintf(stderr, "still had %d sqes to submit\n", ret); 386 + goto err; 387 + } 388 + 389 + io_uring_for_each_cqe(&ring, head, cqe) { 390 + if (cqe->res == -EOPNOTSUPP) 391 + fprintf(stdout, "Device doesn't support polled IO\n"); 392 + goto ok; 393 + } 394 + usleep(10000); 395 + } 396 + err: 397 + ret = 1; 398 + if (fd != -1) 399 + close(fd); 400 + 401 + ok: 402 + io_uring_queue_exit(&ring); 403 + return ret; 404 + } 405 + 406 + int main(int argc, char *argv[]) 407 + { 408 + int i, ret; 409 + char *fname; 410 + 411 + if (argc < 2) 412 + return T_EXIT_SKIP; 413 + 414 + fname = argv[1]; 415 + ret = nvme_get_info(fname); 416 + 417 + if (ret) 418 + return T_EXIT_SKIP; 419 + 420 + vecs = t_create_buffers(BUFFERS, BS); 421 + 422 + for (i = 0; i < 16; i++) { 423 + int read = (i & 1) != 0; 424 + int sqthread = (i & 2) != 0; 425 + int fixed = (i & 4) != 0; 426 + int nonvec = (i & 8) != 0; 427 + 428 + ret = test_io(fname, i, read, sqthread, fixed, nonvec); 429 + if (ret) { 430 + fprintf(stderr, "test_io failed %d/%d/%d/%d\n", 431 + read, sqthread, fixed, nonvec); 432 + goto err; 433 + } 434 + } 435 + 436 + ret = test_io_uring_submit_enters(fname); 437 + if (ret) { 438 + fprintf(stderr, "test_io_uring_submit_enters failed\n"); 439 + goto err; 440 + } 441 + 442 + ret = test_invalid_passthru_submit(fname); 443 + if (ret) { 444 + fprintf(stderr, "test_invalid_passthru_submit failed\n"); 445 + goto err; 446 + } 447 + 448 + return T_EXIT_PASS; 449 + err: 450 + return T_EXIT_FAIL; 451 + }
+36 -161
vendor/liburing/test/io_uring_register.c
··· 31 31 static rlim_t mlock_limit; 32 32 static int devnull; 33 33 34 - #if !defined(CONFIG_HAVE_MEMFD_CREATE) 35 - #include <sys/syscall.h> 36 - #include <linux/memfd.h> 37 - 38 - static int memfd_create(const char *name, unsigned int flags) 39 - { 40 - return (int)syscall(SYS_memfd_create, name, flags); 41 - } 42 - #endif 43 - 44 - 45 34 static int expect_fail(int fd, unsigned int opcode, void *arg, 46 35 unsigned int nr_args, int error) 47 36 { 48 37 int ret; 49 38 50 - ret = __sys_io_uring_register(fd, opcode, arg, nr_args); 51 - if (ret != -1) { 39 + ret = io_uring_register(fd, opcode, arg, nr_args); 40 + if (ret >= 0) { 52 41 int ret2 = 0; 53 42 54 43 fprintf(stderr, "expected %s, but call succeeded\n", strerror(error)); 55 44 if (opcode == IORING_REGISTER_BUFFERS) { 56 - ret2 = __sys_io_uring_register(fd, 57 - IORING_UNREGISTER_BUFFERS, 0, 0); 45 + ret2 = io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 46 + 0, 0); 58 47 } else if (opcode == IORING_REGISTER_FILES) { 59 - ret2 = __sys_io_uring_register(fd, 60 - IORING_UNREGISTER_FILES, 0, 0); 48 + ret2 = io_uring_register(fd, IORING_UNREGISTER_FILES, 0, 49 + 0); 61 50 } 62 51 if (ret2) { 63 52 fprintf(stderr, "internal error: failed to unregister\n"); ··· 66 55 return 1; 67 56 } 68 57 69 - if (errno != error) { 70 - fprintf(stderr, "expected %d, got %d\n", error, errno); 58 + if (ret != error) { 59 + fprintf(stderr, "expected %d, got %d\n", error, ret); 71 60 return 1; 72 61 } 73 62 return 0; ··· 77 66 { 78 67 int fd; 79 68 80 - fd = __sys_io_uring_setup(entries, p); 69 + fd = io_uring_setup(entries, p); 81 70 if (fd < 0) { 82 71 perror("io_uring_setup"); 83 72 exit(1); ··· 197 186 */ 198 187 nr_fds = UINT_MAX; 199 188 while (nr_fds) { 200 - ret = __sys_io_uring_register(uring_fd, IORING_REGISTER_FILES, 201 - fd_as, nr_fds); 189 + ret = io_uring_register(uring_fd, IORING_REGISTER_FILES, fd_as, 190 + nr_fds); 202 191 if (ret != 0) { 203 192 nr_fds /= 2; 204 193 continue; 205 194 } 206 195 status = 0; 207 - ret = __sys_io_uring_register(uring_fd, IORING_UNREGISTER_FILES, 208 - 0, 0); 196 + ret = io_uring_register(uring_fd, IORING_UNREGISTER_FILES, 0, 0); 209 197 if (ret < 0) { 210 198 ret = errno; 211 199 errno = ret; ··· 241 229 iov.iov_base = buf; 242 230 243 231 while (iov.iov_len) { 244 - ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1); 232 + ret = io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1); 245 233 if (ret < 0) { 246 234 if (errno == ENOMEM) { 247 235 iov.iov_len /= 2; ··· 255 243 free(buf); 256 244 return 1; 257 245 } 258 - ret = __sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 259 - NULL, 0); 246 + ret = io_uring_register(fd, IORING_UNREGISTER_BUFFERS, NULL, 0); 260 247 if (ret != 0) { 261 248 fprintf(stderr, "error: unregister failed with %d\n", errno); 262 249 free(buf); ··· 290 277 iovs[i].iov_len = pagesize; 291 278 } 292 279 293 - status |= expect_fail(fd, IORING_REGISTER_BUFFERS, iovs, nr, EINVAL); 280 + status |= expect_fail(fd, IORING_REGISTER_BUFFERS, iovs, nr, -EINVAL); 294 281 295 282 /* reduce to UIO_MAXIOV */ 296 283 nr = UIO_MAXIOV; 297 - ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, iovs, nr); 284 + ret = io_uring_register(fd, IORING_REGISTER_BUFFERS, iovs, nr); 298 285 if (ret && (errno == ENOMEM || errno == EPERM) && geteuid()) { 299 286 fprintf(stderr, "can't register large iovec for regular users, skip\n"); 300 287 } else if (ret != 0) { 301 288 fprintf(stderr, "expected success, got %d\n", errno); 302 289 status = 1; 303 290 } else { 304 - __sys_io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 0, 0); 291 + io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 0, 0); 305 292 } 306 293 free(buf); 307 294 free(iovs); ··· 321 308 /* NULL pointer for base */ 322 309 iov.iov_base = 0; 323 310 iov.iov_len = 4096; 324 - status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EFAULT); 311 + status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT); 325 312 326 313 /* valid base, 0 length */ 327 314 iov.iov_base = &buf; 328 315 iov.iov_len = 0; 329 - status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EFAULT); 316 + status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT); 330 317 331 318 /* valid base, length exceeds size */ 332 319 /* this requires an unampped page directly after buf */ ··· 337 324 assert(ret == 0); 338 325 iov.iov_base = buf; 339 326 iov.iov_len = 2 * pagesize; 340 - status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EFAULT); 327 + status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EFAULT); 341 328 munmap(buf, pagesize); 342 329 343 330 /* huge page */ ··· 355 342 */ 356 343 iov.iov_base = buf; 357 344 iov.iov_len = 2*1024*1024; 358 - ret = __sys_io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1); 345 + ret = io_uring_register(fd, IORING_REGISTER_BUFFERS, &iov, 1); 359 346 if (ret < 0) { 360 - if (errno == ENOMEM) 347 + if (ret == -ENOMEM) 361 348 printf("Unable to test registering of a huge " 362 349 "page. Try increasing the " 363 350 "RLIMIT_MEMLOCK resource limit by at " 364 351 "least 2MB."); 365 352 else { 366 - fprintf(stderr, "expected success, got %d\n", errno); 353 + fprintf(stderr, "expected success, got %d\n", ret); 367 354 status = 1; 368 355 } 369 356 } else { 370 - ret = __sys_io_uring_register(fd, 371 - IORING_UNREGISTER_BUFFERS, 0, 0); 357 + ret = io_uring_register(fd, IORING_UNREGISTER_BUFFERS, 358 + 0, 0); 372 359 if (ret < 0) { 373 - perror("io_uring_unregister"); 360 + fprintf(stderr, "io_uring_unregister: %s\n", 361 + strerror(-ret)); 374 362 status = 1; 375 363 } 376 364 } ··· 384 372 status = 1; 385 373 iov.iov_base = buf; 386 374 iov.iov_len = 2*1024*1024; 387 - status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, EOPNOTSUPP); 375 + status |= expect_fail(fd, IORING_REGISTER_BUFFERS, &iov, 1, -EOPNOTSUPP); 388 376 munmap(buf, 2*1024*1024); 389 377 390 378 /* bump up against the soft limit and make sure we get EFAULT ··· 412 400 413 401 ret = io_uring_submit(ring); 414 402 if (ret != 1) { 415 - fprintf(stderr, "failed to submit poll sqe: %d.\n", errno); 403 + fprintf(stderr, "failed to submit poll sqe: %d.\n", ret); 416 404 return 1; 417 405 } 418 406 ··· 454 442 * fail, because the kernel does not allow registering of the 455 443 * ring_fd. 456 444 */ 457 - status |= expect_fail(fd, IORING_REGISTER_FILES, &fd, 1, EBADF); 445 + status |= expect_fail(fd, IORING_REGISTER_FILES, &fd, 1, -EBADF); 458 446 459 447 /* tear down queue */ 460 448 io_uring_queue_exit(&ring); ··· 462 450 return status; 463 451 } 464 452 465 - static int test_shmem(void) 466 - { 467 - const char pattern = 0xEA; 468 - const int len = 4096; 469 - struct io_uring_sqe *sqe; 470 - struct io_uring_cqe *cqe; 471 - struct io_uring ring; 472 - struct iovec iov; 473 - int memfd, ret, i; 474 - char *mem; 475 - int pipefd[2] = {-1, -1}; 476 - 477 - ret = io_uring_queue_init(8, &ring, 0); 478 - if (ret) 479 - return 1; 480 - 481 - if (pipe(pipefd)) { 482 - perror("pipe"); 483 - return 1; 484 - } 485 - memfd = memfd_create("uring-shmem-test", 0); 486 - if (memfd < 0) { 487 - fprintf(stderr, "memfd_create() failed %i\n", -errno); 488 - return 1; 489 - } 490 - if (ftruncate(memfd, len)) { 491 - fprintf(stderr, "can't truncate memfd\n"); 492 - return 1; 493 - } 494 - mem = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, 0); 495 - if (!mem) { 496 - fprintf(stderr, "mmap failed\n"); 497 - return 1; 498 - } 499 - for (i = 0; i < len; i++) 500 - mem[i] = pattern; 501 - 502 - iov.iov_base = mem; 503 - iov.iov_len = len; 504 - ret = io_uring_register_buffers(&ring, &iov, 1); 505 - if (ret) { 506 - if (ret == -EOPNOTSUPP) { 507 - fprintf(stdout, "memfd registration isn't supported, " 508 - "skip\n"); 509 - goto out; 510 - } 511 - 512 - fprintf(stderr, "buffer reg failed: %d\n", ret); 513 - return 1; 514 - } 515 - 516 - /* check that we can read and write from/to shmem reg buffer */ 517 - sqe = io_uring_get_sqe(&ring); 518 - io_uring_prep_write_fixed(sqe, pipefd[1], mem, 512, 0, 0); 519 - sqe->user_data = 1; 520 - 521 - ret = io_uring_submit(&ring); 522 - if (ret != 1) { 523 - fprintf(stderr, "submit write failed\n"); 524 - return 1; 525 - } 526 - ret = io_uring_wait_cqe(&ring, &cqe); 527 - if (ret < 0 || cqe->user_data != 1 || cqe->res != 512) { 528 - fprintf(stderr, "reading from shmem failed\n"); 529 - return 1; 530 - } 531 - io_uring_cqe_seen(&ring, cqe); 532 - 533 - /* clean it, should be populated with the pattern back from the pipe */ 534 - memset(mem, 0, 512); 535 - sqe = io_uring_get_sqe(&ring); 536 - io_uring_prep_read_fixed(sqe, pipefd[0], mem, 512, 0, 0); 537 - sqe->user_data = 2; 538 - 539 - ret = io_uring_submit(&ring); 540 - if (ret != 1) { 541 - fprintf(stderr, "submit write failed\n"); 542 - return 1; 543 - } 544 - ret = io_uring_wait_cqe(&ring, &cqe); 545 - if (ret < 0 || cqe->user_data != 2 || cqe->res != 512) { 546 - fprintf(stderr, "reading from shmem failed\n"); 547 - return 1; 548 - } 549 - io_uring_cqe_seen(&ring, cqe); 550 - 551 - for (i = 0; i < 512; i++) { 552 - if (mem[i] != pattern) { 553 - fprintf(stderr, "data integrity fail\n"); 554 - return 1; 555 - } 556 - } 557 - 558 - ret = io_uring_unregister_buffers(&ring); 559 - if (ret) { 560 - fprintf(stderr, "buffer unreg failed: %d\n", ret); 561 - return 1; 562 - } 563 - out: 564 - io_uring_queue_exit(&ring); 565 - close(pipefd[0]); 566 - close(pipefd[1]); 567 - munmap(mem, len); 568 - close(memfd); 569 - return 0; 570 - } 571 - 572 453 int main(int argc, char **argv) 573 454 { 574 455 int fd, ret; ··· 577 458 struct rlimit rlim; 578 459 579 460 if (argc > 1) 580 - return 0; 461 + return T_EXIT_SKIP; 581 462 582 463 /* setup globals */ 583 464 pagesize = getpagesize(); 584 465 ret = getrlimit(RLIMIT_MEMLOCK, &rlim); 585 466 if (ret < 0) { 586 467 perror("getrlimit"); 587 - return 1; 468 + return T_EXIT_PASS; 588 469 } 589 470 mlock_limit = rlim.rlim_cur; 590 471 devnull = open("/dev/null", O_RDWR); 591 472 if (devnull < 0) { 592 473 perror("open /dev/null"); 593 - exit(1); 474 + exit(T_EXIT_FAIL); 594 475 } 595 476 596 477 /* invalid fd */ 597 - status |= expect_fail(-1, 0, NULL, 0, EBADF); 478 + status |= expect_fail(-1, 0, NULL, 0, -EBADF); 598 479 /* valid fd that is not an io_uring fd */ 599 - status |= expect_fail(devnull, 0, NULL, 0, EOPNOTSUPP); 480 + status |= expect_fail(devnull, 0, NULL, 0, -EOPNOTSUPP); 600 481 601 482 /* invalid opcode */ 602 483 memset(&p, 0, sizeof(p)); 603 484 fd = new_io_uring(1, &p); 604 - ret = expect_fail(fd, ~0U, NULL, 0, EINVAL); 485 + ret = expect_fail(fd, ~0U, NULL, 0, -EINVAL); 605 486 if (ret) { 606 487 /* if this succeeds, tear down the io_uring instance 607 488 * and start clean for the next test. */ ··· 620 501 621 502 if (status) 622 503 fprintf(stderr, "FAIL\n"); 623 - 624 - ret = test_shmem(); 625 - if (ret) { 626 - fprintf(stderr, "test_shmem() failed\n"); 627 - status |= 1; 628 - } 629 504 630 505 return status; 631 506 }
+19 -18
vendor/liburing/test/io_uring_setup.c
··· 15 15 #include <errno.h> 16 16 #include <sys/sysinfo.h> 17 17 #include "liburing.h" 18 + #include "helpers.h" 18 19 19 20 #include "../syscall.h" 20 21 ··· 97 98 /* bogus: setup returns a valid fd on success... expect can't predict the 98 99 fd we'll get, so this really only takes 1 parameter: error */ 99 100 int 100 - try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect, int error) 101 + try_io_uring_setup(unsigned entries, struct io_uring_params *p, int expect) 101 102 { 102 - int ret, err; 103 + int ret; 103 104 104 - ret = __sys_io_uring_setup(entries, p); 105 + ret = io_uring_setup(entries, p); 105 106 if (ret != expect) { 106 107 fprintf(stderr, "expected %d, got %d\n", expect, ret); 107 108 /* if we got a valid uring, close it */ ··· 109 110 close(ret); 110 111 return 1; 111 112 } 112 - err = errno; 113 - if (expect == -1 && error != err) { 114 - if (err == EPERM && geteuid() != 0) { 113 + 114 + if (expect < 0 && expect != ret) { 115 + if (ret == -EPERM && geteuid() != 0) { 115 116 printf("Needs root, not flagging as an error\n"); 116 117 return 0; 117 118 } 118 - fprintf(stderr, "expected errno %d, got %d\n", error, err); 119 + fprintf(stderr, "expected errno %d, got %d\n", expect, ret); 119 120 return 1; 120 121 } 121 122 ··· 130 131 struct io_uring_params p; 131 132 132 133 if (argc > 1) 133 - return 0; 134 + return T_EXIT_SKIP; 134 135 135 136 memset(&p, 0, sizeof(p)); 136 - status |= try_io_uring_setup(0, &p, -1, EINVAL); 137 - status |= try_io_uring_setup(1, NULL, -1, EFAULT); 137 + status |= try_io_uring_setup(0, &p, -EINVAL); 138 + status |= try_io_uring_setup(1, NULL, -EFAULT); 138 139 139 140 /* resv array is non-zero */ 140 141 memset(&p, 0, sizeof(p)); 141 142 p.resv[0] = p.resv[1] = p.resv[2] = 1; 142 - status |= try_io_uring_setup(1, &p, -1, EINVAL); 143 + status |= try_io_uring_setup(1, &p, -EINVAL); 143 144 144 145 /* invalid flags */ 145 146 memset(&p, 0, sizeof(p)); 146 147 p.flags = ~0U; 147 - status |= try_io_uring_setup(1, &p, -1, EINVAL); 148 + status |= try_io_uring_setup(1, &p, -EINVAL); 148 149 149 150 /* IORING_SETUP_SQ_AFF set but not IORING_SETUP_SQPOLL */ 150 151 memset(&p, 0, sizeof(p)); 151 152 p.flags = IORING_SETUP_SQ_AFF; 152 - status |= try_io_uring_setup(1, &p, -1, EINVAL); 153 + status |= try_io_uring_setup(1, &p, -EINVAL); 153 154 154 155 /* attempt to bind to invalid cpu */ 155 156 memset(&p, 0, sizeof(p)); 156 157 p.flags = IORING_SETUP_SQPOLL | IORING_SETUP_SQ_AFF; 157 158 p.sq_thread_cpu = get_nprocs_conf(); 158 - status |= try_io_uring_setup(1, &p, -1, EINVAL); 159 + status |= try_io_uring_setup(1, &p, -EINVAL); 159 160 160 161 /* I think we can limit a process to a set of cpus. I assume 161 162 * we shouldn't be able to setup a kernel thread outside of that. ··· 163 164 164 165 /* read/write on io_uring_fd */ 165 166 memset(&p, 0, sizeof(p)); 166 - fd = __sys_io_uring_setup(1, &p); 167 + fd = io_uring_setup(1, &p); 167 168 if (fd < 0) { 168 169 fprintf(stderr, "io_uring_setup failed with %d, expected success\n", 169 - errno); 170 + -fd); 170 171 status = 1; 171 172 } else { 172 173 char buf[4096]; ··· 179 180 } 180 181 181 182 if (!status) 182 - return 0; 183 + return T_EXIT_PASS; 183 184 184 185 fprintf(stderr, "FAIL\n"); 185 - return -1; 186 + return T_EXIT_FAIL; 186 187 }
+85
vendor/liburing/test/iopoll-leak.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Description: test a mem leak with IOPOLL 4 + */ 5 + #include <errno.h> 6 + #include <stdio.h> 7 + #include <unistd.h> 8 + #include <stdlib.h> 9 + #include <string.h> 10 + #include <fcntl.h> 11 + #include <sys/types.h> 12 + #include <sys/wait.h> 13 + #include "helpers.h" 14 + #include "liburing.h" 15 + 16 + #define FILE_SIZE (128 * 1024) 17 + #define BS 4096 18 + #define BUFFERS (FILE_SIZE / BS) 19 + 20 + static int do_iopoll(const char *fname) 21 + { 22 + struct io_uring_sqe *sqe; 23 + struct io_uring ring; 24 + struct iovec *iov; 25 + int fd; 26 + 27 + fd = open(fname, O_RDONLY | O_DIRECT); 28 + if (fd < 0) { 29 + perror("open"); 30 + return T_EXIT_SKIP; 31 + } 32 + 33 + iov = t_create_buffers(1, 4096); 34 + 35 + t_create_ring(2, &ring, IORING_SETUP_IOPOLL); 36 + 37 + sqe = io_uring_get_sqe(&ring); 38 + io_uring_prep_read(sqe, fd, iov->iov_base, iov->iov_len, 0); 39 + io_uring_submit(&ring); 40 + 41 + close(fd); 42 + return T_EXIT_PASS; 43 + } 44 + 45 + static int test(const char *fname) 46 + { 47 + if (fork()) { 48 + int stat; 49 + 50 + wait(&stat); 51 + return WEXITSTATUS(stat); 52 + } else { 53 + int ret; 54 + 55 + ret = do_iopoll(fname); 56 + exit(ret); 57 + } 58 + } 59 + 60 + int main(int argc, char *argv[]) 61 + { 62 + char buf[256]; 63 + char *fname; 64 + int i, ret; 65 + 66 + if (argc > 1) { 67 + fname = argv[1]; 68 + } else { 69 + srand((unsigned)time(NULL)); 70 + snprintf(buf, sizeof(buf), ".iopoll-leak-%u-%u", 71 + (unsigned)rand(), (unsigned)getpid()); 72 + fname = buf; 73 + t_create_file(fname, FILE_SIZE); 74 + } 75 + 76 + for (i = 0; i < 16; i++) { 77 + ret = test(fname); 78 + if (ret == T_EXIT_SKIP || ret == T_EXIT_FAIL) 79 + break; 80 + } 81 + 82 + if (fname != argv[1]) 83 + unlink(fname); 84 + return ret; 85 + }
+16 -9
vendor/liburing/test/iopoll.c
··· 201 201 return 1; 202 202 } 203 203 204 - extern int __io_uring_flush_sq(struct io_uring *ring); 204 + extern unsigned __io_uring_flush_sq(struct io_uring *ring); 205 205 206 206 /* 207 207 * if we are polling io_uring_submit needs to always enter the ··· 274 274 } 275 275 276 276 static int test_io(const char *file, int write, int sqthread, int fixed, 277 - int buf_select) 277 + int buf_select, int defer) 278 278 { 279 279 struct io_uring ring; 280 280 int ret, ring_flags = IORING_SETUP_IOPOLL; 281 281 282 282 if (no_iopoll) 283 283 return 0; 284 + 285 + if (defer) 286 + ring_flags |= IORING_SETUP_SINGLE_ISSUER | 287 + IORING_SETUP_DEFER_TASKRUN; 284 288 285 289 ret = t_create_ring(64, &ring, ring_flags); 286 290 if (ret == T_SETUP_SKIP) ··· 323 327 char *fname; 324 328 325 329 if (probe_buf_select()) 326 - return 1; 330 + return T_EXIT_FAIL; 327 331 328 332 if (argc > 1) { 329 333 fname = argv[1]; ··· 337 341 338 342 vecs = t_create_buffers(BUFFERS, BS); 339 343 340 - nr = 16; 344 + nr = 32; 341 345 if (no_buf_select) 342 346 nr = 8; 347 + else if (!t_probe_defer_taskrun()) 348 + nr = 16; 343 349 for (i = 0; i < nr; i++) { 344 350 int write = (i & 1) != 0; 345 351 int sqthread = (i & 2) != 0; 346 352 int fixed = (i & 4) != 0; 347 353 int buf_select = (i & 8) != 0; 354 + int defer = (i & 16) != 0; 348 355 349 - ret = test_io(fname, write, sqthread, fixed, buf_select); 356 + ret = test_io(fname, write, sqthread, fixed, buf_select, defer); 350 357 if (ret) { 351 - fprintf(stderr, "test_io failed %d/%d/%d/%d\n", 352 - write, sqthread, fixed, buf_select); 358 + fprintf(stderr, "test_io failed %d/%d/%d/%d/%d\n", 359 + write, sqthread, fixed, buf_select, defer); 353 360 goto err; 354 361 } 355 362 if (no_iopoll) ··· 364 371 365 372 if (fname != argv[1]) 366 373 unlink(fname); 367 - return 0; 374 + return T_EXIT_PASS; 368 375 err: 369 376 if (fname != argv[1]) 370 377 unlink(fname); 371 - return 1; 378 + return T_EXIT_FAIL; 372 379 }
+3 -1
vendor/liburing/test/lfs-openat-write.c
··· 14 14 #include <sys/resource.h> 15 15 #include <unistd.h> 16 16 17 + #include "helpers.h" 18 + 17 19 static const int RSIZE = 2; 18 20 static const int OPEN_FLAGS = O_RDWR | O_CREAT; 19 21 static const mode_t OPEN_MODE = S_IRUSR | S_IWUSR; ··· 100 102 int dfd, ret; 101 103 102 104 if (argc > 1) 103 - return 0; 105 + return T_EXIT_SKIP; 104 106 105 107 dfd = open("/tmp", O_RDONLY | O_DIRECTORY); 106 108 if (dfd < 0)
+5 -4
vendor/liburing/test/link.c
··· 11 11 #include <fcntl.h> 12 12 13 13 #include "liburing.h" 14 + #include "helpers.h" 14 15 15 16 static int no_hardlink; 16 17 ··· 435 436 int ret; 436 437 437 438 if (argc > 1) 438 - return 0; 439 + return T_EXIT_SKIP; 439 440 440 441 ret = io_uring_queue_init(8, &ring, 0); 441 442 if (ret) { 442 443 printf("ring setup failed\n"); 443 - return 1; 444 + return T_EXIT_FAIL; 444 445 445 446 } 446 447 447 448 ret = io_uring_queue_init(8, &poll_ring, IORING_SETUP_IOPOLL); 448 449 if (ret) { 449 450 printf("poll_ring setup failed\n"); 450 - return 1; 451 + return T_EXIT_FAIL; 451 452 } 452 453 453 454 ret = test_single_link(&ring); ··· 492 493 return ret; 493 494 } 494 495 495 - return 0; 496 + return T_EXIT_PASS; 496 497 }
+2 -2
vendor/liburing/test/madvise.c
··· 187 187 if (fname != argv[1]) 188 188 unlink(fname); 189 189 io_uring_queue_exit(&ring); 190 - return 0; 190 + return T_EXIT_PASS; 191 191 err: 192 192 if (fname != argv[1]) 193 193 unlink(fname); 194 - return 1; 194 + return T_EXIT_FAIL; 195 195 }
+9 -5
vendor/liburing/test/mkdir.c
··· 10 10 #include <unistd.h> 11 11 12 12 #include "liburing.h" 13 + #include "helpers.h" 13 14 14 15 static int do_mkdirat(struct io_uring *ring, const char *fn) 15 16 { ··· 59 60 struct io_uring ring; 60 61 61 62 if (argc > 1) 62 - return 0; 63 + return T_EXIT_SKIP; 63 64 64 65 ret = io_uring_queue_init(8, &ring, 0); 65 66 if (ret) { ··· 71 72 if (ret < 0) { 72 73 if (ret == -EBADF || ret == -EINVAL) { 73 74 fprintf(stdout, "mkdirat not supported, skipping\n"); 74 - goto out; 75 + goto skip; 75 76 } 76 77 fprintf(stderr, "mkdirat: %s\n", strerror(-ret)); 77 78 goto err; ··· 96 97 goto err1; 97 98 } 98 99 99 - out: 100 100 unlinkat(AT_FDCWD, fn, AT_REMOVEDIR); 101 101 io_uring_queue_exit(&ring); 102 - return 0; 102 + return T_EXIT_PASS; 103 + skip: 104 + unlinkat(AT_FDCWD, fn, AT_REMOVEDIR); 105 + io_uring_queue_exit(&ring); 106 + return T_EXIT_SKIP; 103 107 err1: 104 108 unlinkat(AT_FDCWD, fn, AT_REMOVEDIR); 105 109 err: 106 110 io_uring_queue_exit(&ring); 107 - return 1; 111 + return T_EXIT_FAIL; 108 112 }
+36 -12
vendor/liburing/test/msg-ring.c
··· 12 12 #include <pthread.h> 13 13 14 14 #include "liburing.h" 15 + #include "helpers.h" 15 16 16 17 static int no_msg; 17 18 ··· 138 139 return 1; 139 140 } 140 141 141 - static int test_invalid(struct io_uring *ring) 142 + static int test_invalid(struct io_uring *ring, bool fixed) 142 143 { 143 144 struct io_uring_cqe *cqe; 144 145 struct io_uring_sqe *sqe; 145 - int ret; 146 + int ret, fd = 1; 146 147 147 148 sqe = io_uring_get_sqe(ring); 148 149 if (!sqe) { 149 150 fprintf(stderr, "get sqe failed\n"); 150 - goto err; 151 + return 1; 151 152 } 152 153 153 - io_uring_prep_msg_ring(sqe, 1, 0, 0x8989, 0); 154 + if (fixed) { 155 + ret = io_uring_register_files(ring, &fd, 1); 156 + if (ret) { 157 + fprintf(stderr, "file register %d\n", ret); 158 + return 1; 159 + } 160 + io_uring_prep_msg_ring(sqe, 0, 0, 0x8989, 0); 161 + sqe->flags |= IOSQE_FIXED_FILE; 162 + } else { 163 + io_uring_prep_msg_ring(sqe, 1, 0, 0x8989, 0); 164 + } 165 + 154 166 sqe->user_data = 1; 155 167 156 168 ret = io_uring_submit(ring); ··· 170 182 } 171 183 172 184 io_uring_cqe_seen(ring, cqe); 185 + if (fixed) 186 + io_uring_unregister_files(ring); 173 187 return 0; 174 188 err: 189 + if (fixed) 190 + io_uring_unregister_files(ring); 175 191 return 1; 176 192 } 177 193 ··· 180 196 struct io_uring ring, ring2, pring; 181 197 pthread_t thread; 182 198 void *tret; 183 - int ret; 199 + int ret, i; 184 200 185 201 if (argc > 1) 186 - return 0; 202 + return T_EXIT_SKIP; 187 203 188 204 ret = io_uring_queue_init(8, &ring, 0); 189 205 if (ret) { 190 206 fprintf(stderr, "ring setup failed: %d\n", ret); 191 - return 1; 207 + return T_EXIT_FAIL; 192 208 } 193 209 ret = io_uring_queue_init(8, &ring2, 0); 194 210 if (ret) { 195 211 fprintf(stderr, "ring setup failed: %d\n", ret); 196 - return 1; 212 + return T_EXIT_FAIL; 197 213 } 198 214 ret = io_uring_queue_init(8, &pring, IORING_SETUP_IOPOLL); 199 215 if (ret) { 200 216 fprintf(stderr, "ring setup failed: %d\n", ret); 201 - return 1; 217 + return T_EXIT_FAIL; 202 218 } 203 219 204 220 ret = test_own(&ring); ··· 208 224 } 209 225 if (no_msg) { 210 226 fprintf(stdout, "Skipped\n"); 211 - return 0; 227 + return T_EXIT_SKIP; 212 228 } 213 229 ret = test_own(&pring); 214 230 if (ret) { ··· 216 232 return ret; 217 233 } 218 234 219 - ret = test_invalid(&ring); 235 + ret = test_invalid(&ring, 0); 220 236 if (ret) { 221 237 fprintf(stderr, "test_invalid failed\n"); 222 238 return ret; 239 + } 240 + 241 + for (i = 0; i < 2; i++) { 242 + ret = test_invalid(&ring, 1); 243 + if (ret) { 244 + fprintf(stderr, "test_invalid fixed failed\n"); 245 + return ret; 246 + } 223 247 } 224 248 225 249 pthread_create(&thread, NULL, wait_cqe_fn, &ring2); ··· 232 256 233 257 pthread_join(thread, &tret); 234 258 235 - return 0; 259 + return T_EXIT_PASS; 236 260 }
+49 -10
vendor/liburing/test/multicqes_drain.c
··· 17 17 #include <poll.h> 18 18 19 19 #include "liburing.h" 20 + #include "helpers.h" 20 21 21 22 enum { 22 23 multi, ··· 116 117 /* 117 118 * avoid below case: 118 119 * sqe0(multishot, link)->sqe1(nop, link)->sqe2(nop)->sqe3(cancel_sqe0) 119 - * sqe3 may excute before sqe0 so that sqe0 isn't cancelled 120 + * sqe3 may execute before sqe0 so that sqe0 isn't cancelled 120 121 */ 121 122 if (sqe_op == multi) 122 123 flags &= ~IOSQE_IO_LINK; ··· 232 233 233 234 if (trigger_event(pipes[i])) 234 235 goto err; 236 + 237 + io_uring_get_events(ring); 235 238 } 236 239 sleep(1); 237 240 i = 0; ··· 245 248 * compl_bits is a bit map to record completions. 246 249 * eg. sqe[0], sqe[1], sqe[2] fully completed 247 250 * then compl_bits is 000...00111b 248 - * 251 + * 249 252 */ 250 253 unsigned long long compl_bits = 0; 251 254 for (j = 0; j < i; j++) { ··· 294 297 io_uring_prep_poll_add(sqe[1], pipe2[0], POLLIN); 295 298 sqe[1]->user_data = 1; 296 299 297 - ret = io_uring_submit(ring); 300 + /* This test relies on multishot poll to trigger events continually. 301 + * however with IORING_SETUP_DEFER_TASKRUN this will only happen when 302 + * triggered with a get_events. Hence we sprinkle get_events whenever 303 + * there might be work to process in order to get the same result 304 + */ 305 + ret = io_uring_submit_and_get_events(ring); 298 306 if (ret < 0) { 299 307 printf("sqe submit failed\n"); 300 308 goto err; ··· 306 314 for (i = 0; i < 2; i++) { 307 315 if (trigger_event(pipe1)) 308 316 goto err; 317 + io_uring_get_events(ring); 309 318 } 310 319 if (trigger_event(pipe2)) 311 320 goto err; 321 + io_uring_get_events(ring); 312 322 313 323 for (i = 0; i < 2; i++) { 314 324 sqe[i] = io_uring_get_sqe(ring); ··· 354 364 return 1; 355 365 } 356 366 357 - int main(int argc, char *argv[]) 367 + static int test(bool defer_taskrun) 358 368 { 359 369 struct io_uring ring; 360 370 int i, ret; 371 + unsigned int flags = 0; 361 372 362 - if (argc > 1) 363 - return 0; 373 + if (defer_taskrun) 374 + flags = IORING_SETUP_SINGLE_ISSUER | 375 + IORING_SETUP_DEFER_TASKRUN; 364 376 365 - ret = io_uring_queue_init(1024, &ring, 0); 377 + ret = io_uring_queue_init(1024, &ring, flags); 366 378 if (ret) { 367 379 printf("ring setup failed\n"); 368 - return 1; 380 + return T_EXIT_FAIL; 369 381 } 370 382 371 383 for (i = 0; i < 5; i++) { 372 384 ret = test_simple_drain(&ring); 373 385 if (ret) { 374 386 fprintf(stderr, "test_simple_drain failed\n"); 375 - break; 387 + return T_EXIT_FAIL; 376 388 } 377 389 } 378 390 ··· 380 392 ret = test_generic_drain(&ring); 381 393 if (ret) { 382 394 fprintf(stderr, "test_generic_drain failed\n"); 383 - break; 395 + return T_EXIT_FAIL; 396 + } 397 + } 398 + 399 + io_uring_queue_exit(&ring); 400 + 401 + return T_EXIT_PASS; 402 + } 403 + 404 + int main(int argc, char *argv[]) 405 + { 406 + int ret; 407 + 408 + if (argc > 1) 409 + return T_EXIT_SKIP; 410 + 411 + ret = test(false); 412 + if (ret != T_EXIT_PASS) { 413 + fprintf(stderr, "%s: test(false) failed\n", argv[0]); 414 + return ret; 415 + } 416 + 417 + if (t_probe_defer_taskrun()) { 418 + ret = test(true); 419 + if (ret != T_EXIT_PASS) { 420 + fprintf(stderr, "%s: test(true) failed\n", argv[0]); 421 + return ret; 384 422 } 385 423 } 424 + 386 425 return ret; 387 426 }
+60
vendor/liburing/test/nolibc.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Test liburing nolibc functionality. 4 + * 5 + * Currently, supported architectures are: 6 + * 1) x86 7 + * 2) x86-64 8 + * 3) aarch64 9 + * 10 + */ 11 + #include "helpers.h" 12 + 13 + #if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) 14 + 15 + /* 16 + * This arch doesn't support nolibc. 17 + */ 18 + int main(void) 19 + { 20 + return T_EXIT_SKIP; 21 + } 22 + 23 + #else /* #if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) */ 24 + 25 + #ifndef CONFIG_NOLIBC 26 + #define CONFIG_NOLIBC 27 + #endif 28 + 29 + #include <stdio.h> 30 + #include <unistd.h> 31 + #include "../src/lib.h" 32 + 33 + static int test_get_page_size(void) 34 + { 35 + long a, b; 36 + 37 + a = sysconf(_SC_PAGESIZE); 38 + b = get_page_size(); 39 + if (a != b) { 40 + fprintf(stderr, "get_page_size() fails, %ld != %ld", a, b); 41 + return -1; 42 + } 43 + return 0; 44 + } 45 + 46 + int main(int argc, char *argv[]) 47 + { 48 + int ret; 49 + 50 + if (argc > 1) 51 + return T_EXIT_SKIP; 52 + 53 + ret = test_get_page_size(); 54 + if (ret) 55 + return T_EXIT_FAIL; 56 + 57 + return T_EXIT_PASS; 58 + } 59 + 60 + #endif /* #if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) */
+168
vendor/liburing/test/nvme.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Description: Helpers for NVMe uring passthrough commands 4 + */ 5 + #ifndef LIBURING_NVME_H 6 + #define LIBURING_NVME_H 7 + 8 + #ifdef __cplusplus 9 + extern "C" { 10 + #endif 11 + 12 + #include <sys/ioctl.h> 13 + #include <linux/nvme_ioctl.h> 14 + 15 + /* 16 + * If the uapi headers installed on the system lacks nvme uring command 17 + * support, use the local version to prevent compilation issues. 18 + */ 19 + #ifndef CONFIG_HAVE_NVME_URING 20 + struct nvme_uring_cmd { 21 + __u8 opcode; 22 + __u8 flags; 23 + __u16 rsvd1; 24 + __u32 nsid; 25 + __u32 cdw2; 26 + __u32 cdw3; 27 + __u64 metadata; 28 + __u64 addr; 29 + __u32 metadata_len; 30 + __u32 data_len; 31 + __u32 cdw10; 32 + __u32 cdw11; 33 + __u32 cdw12; 34 + __u32 cdw13; 35 + __u32 cdw14; 36 + __u32 cdw15; 37 + __u32 timeout_ms; 38 + __u32 rsvd2; 39 + }; 40 + 41 + #define NVME_URING_CMD_IO _IOWR('N', 0x80, struct nvme_uring_cmd) 42 + #define NVME_URING_CMD_IO_VEC _IOWR('N', 0x81, struct nvme_uring_cmd) 43 + #endif /* CONFIG_HAVE_NVME_URING */ 44 + 45 + #define NVME_DEFAULT_IOCTL_TIMEOUT 0 46 + #define NVME_IDENTIFY_DATA_SIZE 4096 47 + #define NVME_IDENTIFY_CSI_SHIFT 24 48 + #define NVME_IDENTIFY_CNS_NS 0 49 + #define NVME_CSI_NVM 0 50 + 51 + enum nvme_admin_opcode { 52 + nvme_admin_identify = 0x06, 53 + }; 54 + 55 + enum nvme_io_opcode { 56 + nvme_cmd_write = 0x01, 57 + nvme_cmd_read = 0x02, 58 + }; 59 + 60 + int nsid; 61 + __u32 lba_shift; 62 + 63 + struct nvme_lbaf { 64 + __le16 ms; 65 + __u8 ds; 66 + __u8 rp; 67 + }; 68 + 69 + struct nvme_id_ns { 70 + __le64 nsze; 71 + __le64 ncap; 72 + __le64 nuse; 73 + __u8 nsfeat; 74 + __u8 nlbaf; 75 + __u8 flbas; 76 + __u8 mc; 77 + __u8 dpc; 78 + __u8 dps; 79 + __u8 nmic; 80 + __u8 rescap; 81 + __u8 fpi; 82 + __u8 dlfeat; 83 + __le16 nawun; 84 + __le16 nawupf; 85 + __le16 nacwu; 86 + __le16 nabsn; 87 + __le16 nabo; 88 + __le16 nabspf; 89 + __le16 noiob; 90 + __u8 nvmcap[16]; 91 + __le16 npwg; 92 + __le16 npwa; 93 + __le16 npdg; 94 + __le16 npda; 95 + __le16 nows; 96 + __le16 mssrl; 97 + __le32 mcl; 98 + __u8 msrc; 99 + __u8 rsvd81[11]; 100 + __le32 anagrpid; 101 + __u8 rsvd96[3]; 102 + __u8 nsattr; 103 + __le16 nvmsetid; 104 + __le16 endgid; 105 + __u8 nguid[16]; 106 + __u8 eui64[8]; 107 + struct nvme_lbaf lbaf[16]; 108 + __u8 rsvd192[192]; 109 + __u8 vs[3712]; 110 + }; 111 + 112 + static inline int ilog2(uint32_t i) 113 + { 114 + int log = -1; 115 + 116 + while (i) { 117 + i >>= 1; 118 + log++; 119 + } 120 + return log; 121 + } 122 + 123 + int nvme_get_info(const char *file) 124 + { 125 + struct nvme_id_ns ns; 126 + int fd, err; 127 + __u32 lba_size; 128 + 129 + fd = open(file, O_RDONLY); 130 + if (fd < 0) { 131 + perror("file open"); 132 + return -errno; 133 + } 134 + 135 + nsid = ioctl(fd, NVME_IOCTL_ID); 136 + if (nsid < 0) { 137 + close(fd); 138 + return -errno; 139 + } 140 + 141 + struct nvme_passthru_cmd cmd = { 142 + .opcode = nvme_admin_identify, 143 + .nsid = nsid, 144 + .addr = (__u64)(uintptr_t)&ns, 145 + .data_len = NVME_IDENTIFY_DATA_SIZE, 146 + .cdw10 = NVME_IDENTIFY_CNS_NS, 147 + .cdw11 = NVME_CSI_NVM << NVME_IDENTIFY_CSI_SHIFT, 148 + .timeout_ms = NVME_DEFAULT_IOCTL_TIMEOUT, 149 + }; 150 + 151 + err = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); 152 + if (err) { 153 + close(fd); 154 + return err; 155 + } 156 + 157 + lba_size = 1 << ns.lbaf[(ns.flbas & 0x0f)].ds; 158 + lba_shift = ilog2(lba_size); 159 + 160 + close(fd); 161 + return 0; 162 + } 163 + 164 + #ifdef __cplusplus 165 + } 166 + #endif 167 + 168 + #endif
+1 -1
vendor/liburing/test/open-direct-pick.c
··· 158 158 return 0; 159 159 } 160 160 161 - path = "/tmp/.open.close"; 161 + path = "/tmp/.open.direct.pick"; 162 162 t_create_file(path, 4096); 163 163 164 164 ret = test_openat(&ring, path);
+9 -18
vendor/liburing/test/poll-link.c
··· 13 13 #include <poll.h> 14 14 #include <arpa/inet.h> 15 15 16 + #include "helpers.h" 16 17 #include "liburing.h" 17 18 18 19 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; ··· 50 51 51 52 static void *send_thread(void *arg) 52 53 { 54 + struct sockaddr_in addr; 53 55 struct data *data = arg; 56 + int s0; 54 57 55 58 wait_for_var(&recv_thread_ready); 56 59 57 - int s0 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 60 + s0 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 58 61 assert(s0 != -1); 59 - 60 - struct sockaddr_in addr; 61 62 62 63 addr.sin_family = AF_INET; 63 64 addr.sin_port = data->port; ··· 72 73 73 74 void *recv_thread(void *arg) 74 75 { 76 + struct sockaddr_in addr = { }; 75 77 struct data *data = arg; 76 78 struct io_uring_sqe *sqe; 77 79 struct io_uring ring; ··· 89 91 ret = setsockopt(s0, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 90 92 assert(ret != -1); 91 93 92 - struct sockaddr_in addr; 93 - 94 94 addr.sin_family = AF_INET; 95 95 data->addr = inet_addr("127.0.0.1"); 96 96 addr.sin_addr.s_addr = data->addr; 97 97 98 - i = 0; 99 - do { 100 - data->port = htons(1025 + (rand() % 64510)); 101 - addr.sin_port = data->port; 102 - 103 - if (bind(s0, (struct sockaddr*)&addr, sizeof(addr)) != -1) 104 - break; 105 - } while (++i < 100); 106 - 107 - if (i >= 100) { 108 - fprintf(stderr, "Can't find good port, skipped\n"); 98 + if (t_bind_ephemeral_port(s0, &addr)) { 99 + perror("bind"); 109 100 data->stop = 1; 110 101 signal_var(&recv_thread_ready); 111 - goto out; 102 + goto err; 112 103 } 104 + data->port = addr.sin_port; 113 105 114 106 ret = listen(s0, 128); 115 107 assert(ret != -1); ··· 158 150 io_uring_cqe_seen(&ring, cqe); 159 151 } 160 152 161 - out: 162 153 signal_var(&recv_thread_done); 163 154 close(s0); 164 155 io_uring_queue_exit(&ring);
+162
vendor/liburing/test/poll-mshot-overflow.c
··· 1 + // SPDX-License-Identifier: MIT 2 + 3 + #include <errno.h> 4 + #include <stdio.h> 5 + #include <unistd.h> 6 + #include <stdlib.h> 7 + #include <string.h> 8 + #include <signal.h> 9 + #include <poll.h> 10 + #include <sys/wait.h> 11 + 12 + #include "liburing.h" 13 + #include "helpers.h" 14 + 15 + int check_final_cqe(struct io_uring *ring) 16 + { 17 + struct io_uring_cqe *cqe; 18 + int count = 0; 19 + bool signalled_no_more = false; 20 + 21 + while (!io_uring_peek_cqe(ring, &cqe)) { 22 + if (cqe->user_data == 1) { 23 + count++; 24 + if (signalled_no_more) { 25 + fprintf(stderr, "signalled no more!\n"); 26 + return T_EXIT_FAIL; 27 + } 28 + if (!(cqe->flags & IORING_CQE_F_MORE)) 29 + signalled_no_more = true; 30 + } else if (cqe->user_data != 3) { 31 + fprintf(stderr, "%d: got unexpected %d\n", count, (int)cqe->user_data); 32 + return T_EXIT_FAIL; 33 + } 34 + io_uring_cqe_seen(ring, cqe); 35 + } 36 + 37 + if (!count) { 38 + fprintf(stderr, "no cqe\n"); 39 + return T_EXIT_FAIL; 40 + } 41 + 42 + return T_EXIT_PASS; 43 + } 44 + 45 + static int test(bool defer_taskrun) 46 + { 47 + struct io_uring_cqe *cqe; 48 + struct io_uring_sqe *sqe; 49 + struct io_uring ring; 50 + int pipe1[2]; 51 + int ret, i; 52 + 53 + if (pipe(pipe1) != 0) { 54 + perror("pipe"); 55 + return T_EXIT_FAIL; 56 + } 57 + 58 + struct io_uring_params params = { 59 + /* cheat using SINGLE_ISSUER existence to know if this behaviour 60 + * is updated 61 + */ 62 + .flags = IORING_SETUP_CQSIZE | IORING_SETUP_SINGLE_ISSUER, 63 + .cq_entries = 2 64 + }; 65 + 66 + if (defer_taskrun) 67 + params.flags |= IORING_SETUP_SINGLE_ISSUER | 68 + IORING_SETUP_DEFER_TASKRUN; 69 + 70 + ret = io_uring_queue_init_params(2, &ring, &params); 71 + if (ret) 72 + return T_EXIT_SKIP; 73 + 74 + sqe = io_uring_get_sqe(&ring); 75 + if (!sqe) { 76 + fprintf(stderr, "get sqe failed\n"); 77 + return T_EXIT_FAIL; 78 + } 79 + io_uring_prep_poll_multishot(sqe, pipe1[0], POLLIN); 80 + io_uring_sqe_set_data64(sqe, 1); 81 + 82 + if (io_uring_cq_ready(&ring)) { 83 + fprintf(stderr, "unexpected cqe\n"); 84 + return T_EXIT_FAIL; 85 + } 86 + 87 + for (i = 0; i < 2; i++) { 88 + sqe = io_uring_get_sqe(&ring); 89 + io_uring_prep_nop(sqe); 90 + io_uring_sqe_set_data64(sqe, 2); 91 + io_uring_submit(&ring); 92 + } 93 + 94 + do { 95 + errno = 0; 96 + ret = write(pipe1[1], "foo", 3); 97 + } while (ret == -1 && errno == EINTR); 98 + 99 + if (ret <= 0) { 100 + fprintf(stderr, "write failed: %d\n", errno); 101 + return T_EXIT_FAIL; 102 + } 103 + 104 + /* should have 2 cqe + 1 overflow now, so take out two cqes */ 105 + for (i = 0; i < 2; i++) { 106 + if (io_uring_peek_cqe(&ring, &cqe)) { 107 + fprintf(stderr, "unexpectedly no cqe\n"); 108 + return T_EXIT_FAIL; 109 + } 110 + if (cqe->user_data != 2) { 111 + fprintf(stderr, "unexpected user_data\n"); 112 + return T_EXIT_FAIL; 113 + } 114 + io_uring_cqe_seen(&ring, cqe); 115 + } 116 + 117 + /* make sure everything is processed */ 118 + io_uring_get_events(&ring); 119 + 120 + /* now remove the poll */ 121 + sqe = io_uring_get_sqe(&ring); 122 + io_uring_prep_poll_remove(sqe, 1); 123 + io_uring_sqe_set_data64(sqe, 3); 124 + ret = io_uring_submit(&ring); 125 + 126 + if (ret != 1) { 127 + fprintf(stderr, "bad poll remove\n"); 128 + return T_EXIT_FAIL; 129 + } 130 + 131 + ret = check_final_cqe(&ring); 132 + 133 + close(pipe1[0]); 134 + close(pipe1[1]); 135 + io_uring_queue_exit(&ring); 136 + 137 + return ret; 138 + } 139 + 140 + int main(int argc, char *argv[]) 141 + { 142 + int ret; 143 + 144 + if (argc > 1) 145 + return T_EXIT_SKIP; 146 + 147 + ret = test(false); 148 + if (ret != T_EXIT_PASS) { 149 + fprintf(stderr, "%s: test(false) failed\n", argv[0]); 150 + return ret; 151 + } 152 + 153 + if (t_probe_defer_taskrun()) { 154 + ret = test(true); 155 + if (ret != T_EXIT_PASS) { 156 + fprintf(stderr, "%s: test(true) failed\n", argv[0]); 157 + return ret; 158 + } 159 + } 160 + 161 + return ret; 162 + }
+83 -33
vendor/liburing/test/poll-mshot-update.c
··· 75 75 return 0; 76 76 } 77 77 78 + static int submit_arm_poll(struct io_uring *ring, int off) 79 + { 80 + int ret; 81 + 82 + ret = arm_poll(ring, off); 83 + if (ret) 84 + return ret; 85 + 86 + ret = io_uring_submit(ring); 87 + if (ret < 0) 88 + return ret; 89 + return ret == 1 ? 0 : -1; 90 + } 91 + 78 92 static int reap_polls(struct io_uring *ring) 79 93 { 80 94 struct io_uring_cqe *cqe; ··· 106 120 off = cqe->user_data; 107 121 if (off == 0x12345678) 108 122 goto seen; 123 + if (!(cqe->flags & IORING_CQE_F_MORE)) { 124 + /* need to re-arm poll */ 125 + ret = submit_arm_poll(ring, off); 126 + if (ret) 127 + break; 128 + if (cqe->res <= 0) { 129 + /* retry this one */ 130 + i--; 131 + goto seen; 132 + } 133 + } 134 + 109 135 ret = read(p[off].fd[0], &c, 1); 110 136 if (ret != 1) { 111 137 if (ret == -1 && errno == EAGAIN) ··· 187 213 return 0; 188 214 } 189 215 190 - int main(int argc, char *argv[]) 216 + static int run(int cqe) 191 217 { 192 218 struct io_uring ring; 193 219 struct io_uring_params params = { }; 194 - struct rlimit rlim; 195 220 pthread_t thread; 196 221 int i, j, ret; 197 222 198 - if (argc > 1) 199 - return 0; 200 - 201 - ret = has_poll_update(); 202 - if (ret < 0) { 203 - fprintf(stderr, "poll update check failed %i\n", ret); 204 - return -1; 205 - } else if (!ret) { 206 - fprintf(stderr, "no poll update, skip\n"); 207 - return 0; 208 - } 209 - 210 - if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 211 - perror("getrlimit"); 212 - goto err_noring; 213 - } 214 - 215 - if (rlim.rlim_cur < (2 * NFILES + 5)) { 216 - rlim.rlim_cur = (2 * NFILES + 5); 217 - rlim.rlim_max = rlim.rlim_cur; 218 - if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { 219 - if (errno == EPERM) 220 - goto err_nofail; 221 - perror("setrlimit"); 222 - goto err_noring; 223 - } 224 - } 225 - 226 223 for (i = 0; i < NFILES; i++) { 227 224 if (pipe(p[i].fd) < 0) { 228 225 perror("pipe"); 229 - goto err_noring; 226 + return 1; 230 227 } 231 228 fcntl(p[i].fd[0], F_SETFL, O_NONBLOCK); 232 229 } 233 230 234 231 params.flags = IORING_SETUP_CQSIZE; 235 - params.cq_entries = 4096; 232 + params.cq_entries = cqe; 236 233 ret = io_uring_queue_init_params(RING_SIZE, &ring, &params); 237 234 if (ret) { 238 235 if (ret == -EINVAL) { ··· 260 257 } 261 258 262 259 io_uring_queue_exit(&ring); 260 + for (i = 0; i < NFILES; i++) { 261 + close(p[i].fd[0]); 262 + close(p[i].fd[1]); 263 + } 263 264 return 0; 264 265 err: 265 266 io_uring_queue_exit(&ring); 266 - err_noring: 267 + return 1; 268 + } 269 + 270 + int main(int argc, char *argv[]) 271 + { 272 + struct rlimit rlim; 273 + int ret; 274 + 275 + if (argc > 1) 276 + return 0; 277 + 278 + ret = has_poll_update(); 279 + if (ret < 0) { 280 + fprintf(stderr, "poll update check failed %i\n", ret); 281 + return -1; 282 + } else if (!ret) { 283 + fprintf(stderr, "no poll update, skip\n"); 284 + return 0; 285 + } 286 + 287 + if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 288 + perror("getrlimit"); 289 + goto err; 290 + } 291 + 292 + if (rlim.rlim_cur < (2 * NFILES + 5)) { 293 + rlim.rlim_cur = (2 * NFILES + 5); 294 + rlim.rlim_max = rlim.rlim_cur; 295 + if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { 296 + if (errno == EPERM) 297 + goto err_nofail; 298 + perror("setrlimit"); 299 + goto err; 300 + } 301 + } 302 + 303 + ret = run(1024); 304 + if (ret) { 305 + fprintf(stderr, "run(1024) failed\n"); 306 + goto err; 307 + } 308 + 309 + ret = run(8192); 310 + if (ret) { 311 + fprintf(stderr, "run(8192) failed\n"); 312 + goto err; 313 + } 314 + 315 + return 0; 316 + err: 267 317 fprintf(stderr, "poll-many failed\n"); 268 318 return 1; 269 319 err_nofail:
+83 -1
vendor/liburing/test/read-write.c
··· 462 462 return 0; 463 463 } 464 464 465 + static int test_buf_select_pipe(void) 466 + { 467 + struct io_uring_sqe *sqe; 468 + struct io_uring_cqe *cqe; 469 + struct io_uring ring; 470 + int ret, i; 471 + int fds[2]; 472 + 473 + if (no_buf_select) 474 + return 0; 475 + 476 + ret = io_uring_queue_init(64, &ring, 0); 477 + if (ret) { 478 + fprintf(stderr, "ring create failed: %d\n", ret); 479 + return 1; 480 + } 481 + 482 + ret = provide_buffers_iovec(&ring, 0); 483 + if (ret) { 484 + fprintf(stderr, "provide buffers failed: %d\n", ret); 485 + return 1; 486 + } 487 + 488 + ret = pipe(fds); 489 + if (ret) { 490 + fprintf(stderr, "pipe failed: %d\n", ret); 491 + return 1; 492 + } 493 + 494 + for (i = 0; i < 5; i++) { 495 + sqe = io_uring_get_sqe(&ring); 496 + io_uring_prep_read(sqe, fds[0], NULL, 1 /* max read 1 per go */, -1); 497 + sqe->flags |= IOSQE_BUFFER_SELECT; 498 + sqe->buf_group = 0; 499 + } 500 + io_uring_submit(&ring); 501 + 502 + ret = write(fds[1], "01234", 5); 503 + if (ret != 5) { 504 + fprintf(stderr, "pipe write failed %d\n", ret); 505 + return 1; 506 + } 507 + 508 + for (i = 0; i < 5; i++) { 509 + const char *buff; 510 + 511 + if (io_uring_wait_cqe(&ring, &cqe)) { 512 + fprintf(stderr, "bad wait %d\n", i); 513 + return 1; 514 + } 515 + if (cqe->res != 1) { 516 + fprintf(stderr, "expected read %d\n", cqe->res); 517 + return 1; 518 + } 519 + if (!(cqe->flags & IORING_CQE_F_BUFFER)) { 520 + fprintf(stderr, "no buffer %d\n", cqe->res); 521 + return 1; 522 + } 523 + buff = vecs[cqe->flags >> 16].iov_base; 524 + if (*buff != '0' + i) { 525 + fprintf(stderr, "%d: expected %c, got %c\n", i, '0' + i, *buff); 526 + return 1; 527 + } 528 + io_uring_cqe_seen(&ring, cqe); 529 + } 530 + 531 + 532 + close(fds[0]); 533 + close(fds[1]); 534 + io_uring_queue_exit(&ring); 535 + return 0; 536 + } 537 + 465 538 static int test_buf_select(const char *filename, int nonvec) 466 539 { 467 540 struct io_uring_probe *p; ··· 686 759 goto err; 687 760 } 688 761 io_uring_prep_writev(sqe, fd, &vecs[i], 1, off); 762 + io_uring_sqe_set_data64(sqe, i); 689 763 off += BS; 690 764 } 691 765 ··· 701 775 fprintf(stderr, "wait_cqe=%d\n", ret); 702 776 goto err; 703 777 } 704 - if (i < 16) { 778 + if (cqe->user_data < 16) { 705 779 if (cqe->res != BS) { 706 780 fprintf(stderr, "bad write: %d\n", cqe->res); 707 781 goto err; ··· 746 820 t_create_file(fname, FILE_SIZE); 747 821 } 748 822 823 + signal(SIGXFSZ, SIG_IGN); 824 + 749 825 vecs = t_create_buffers(BUFFERS, BS); 750 826 751 827 /* if we don't have nonvec read, skip testing that */ ··· 788 864 ret = test_buf_select_short(fname, 0); 789 865 if (ret) { 790 866 fprintf(stderr, "test_buf_select_short vec failed\n"); 867 + goto err; 868 + } 869 + 870 + ret = test_buf_select_pipe(); 871 + if (ret) { 872 + fprintf(stderr, "test_buf_select_pipe failed\n"); 791 873 goto err; 792 874 } 793 875
+10 -12
vendor/liburing/test/recv-msgall-stream.c
··· 3 3 * Test MSG_WAITALL for recv/recvmsg and include normal sync versions just 4 4 * for comparison. 5 5 */ 6 + #include <assert.h> 6 7 #include <errno.h> 7 8 #include <stdio.h> 8 9 #include <stdlib.h> ··· 19 20 20 21 #define MAX_MSG 128 21 22 22 - static int port = 31200; 23 - 24 23 struct recv_data { 25 24 pthread_mutex_t mutex; 26 25 int use_recvmsg; 27 26 int use_sync; 28 - int port; 27 + __be16 port; 29 28 }; 30 29 31 30 static int get_conn_sock(struct recv_data *rd, int *sockout) ··· 36 35 memset(&saddr, 0, sizeof(saddr)); 37 36 saddr.sin_family = AF_INET; 38 37 saddr.sin_addr.s_addr = htonl(INADDR_ANY); 39 - saddr.sin_port = htons(rd->port); 40 38 41 39 sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); 42 40 if (sockfd < 0) { ··· 48 46 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 49 47 setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); 50 48 51 - ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); 52 - if (ret < 0) { 49 + if (t_bind_ephemeral_port(sockfd, &saddr)) { 53 50 perror("bind"); 54 51 goto err; 55 52 } 53 + rd->port = saddr.sin_port; 56 54 57 55 ret = listen(sockfd, 16); 58 56 if (ret < 0) { ··· 279 277 for (i = 0; i < MAX_MSG; i++) 280 278 buf[i] = i; 281 279 282 - memset(&saddr, 0, sizeof(saddr)); 283 - saddr.sin_family = AF_INET; 284 - saddr.sin_port = htons(rd->port); 285 - inet_pton(AF_INET, "127.0.0.1", &saddr.sin_addr); 286 - 287 280 sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); 288 281 if (sockfd < 0) { 289 282 perror("socket"); ··· 291 284 } 292 285 293 286 pthread_mutex_lock(&rd->mutex); 287 + assert(rd->port != 0); 288 + memset(&saddr, 0, sizeof(saddr)); 289 + saddr.sin_family = AF_INET; 290 + saddr.sin_port = rd->port; 291 + inet_pton(AF_INET, "127.0.0.1", &saddr.sin_addr); 294 292 295 293 ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); 296 294 if (ret < 0) { ··· 351 349 pthread_mutex_lock(&rd.mutex); 352 350 rd.use_recvmsg = use_recvmsg; 353 351 rd.use_sync = use_sync; 354 - rd.port = port++; 352 + rd.port = 0; 355 353 356 354 ret = pthread_create(&recv_thread, NULL, recv_fn, &rd); 357 355 if (ret) {
+4 -6
vendor/liburing/test/recv-msgall.c
··· 16 16 #include "helpers.h" 17 17 18 18 #define MAX_MSG 128 19 - 20 - #define PORT 10201 21 19 #define HOST "127.0.0.1" 20 + static __be16 bind_port; 22 21 23 22 static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock, 24 23 int use_recvmsg) ··· 31 30 memset(&saddr, 0, sizeof(saddr)); 32 31 saddr.sin_family = AF_INET; 33 32 saddr.sin_addr.s_addr = htonl(INADDR_ANY); 34 - saddr.sin_port = htons(PORT); 35 33 36 34 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 37 35 if (sockfd < 0) { ··· 42 40 val = 1; 43 41 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 44 42 45 - ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); 46 - if (ret < 0) { 43 + if (t_bind_ephemeral_port(sockfd, &saddr)) { 47 44 perror("bind"); 48 45 goto err; 49 46 } 47 + bind_port = saddr.sin_port; 50 48 51 49 sqe = io_uring_get_sqe(ring); 52 50 if (!use_recvmsg) { ··· 165 163 166 164 memset(&saddr, 0, sizeof(saddr)); 167 165 saddr.sin_family = AF_INET; 168 - saddr.sin_port = htons(PORT); 166 + saddr.sin_port = bind_port; 169 167 inet_pton(AF_INET, HOST, &saddr.sin_addr); 170 168 171 169 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+505
vendor/liburing/test/recv-multishot.c
··· 1 + // SPDX-License-Identifier: MIT 2 + 3 + #include <errno.h> 4 + #include <stdio.h> 5 + #include <stdlib.h> 6 + #include <string.h> 7 + #include <unistd.h> 8 + #include <arpa/inet.h> 9 + #include <sys/types.h> 10 + #include <sys/socket.h> 11 + #include <pthread.h> 12 + 13 + #include "liburing.h" 14 + #include "helpers.h" 15 + 16 + #define ENORECVMULTISHOT 9999 17 + 18 + enum early_error_t { 19 + ERROR_NONE = 0, 20 + ERROR_NOT_ENOUGH_BUFFERS, 21 + ERROR_EARLY_CLOSE_SENDER, 22 + ERROR_EARLY_CLOSE_RECEIVER, 23 + ERROR_EARLY_OVERFLOW, 24 + ERROR_EARLY_LAST 25 + }; 26 + 27 + struct args { 28 + bool stream; 29 + bool wait_each; 30 + bool recvmsg; 31 + enum early_error_t early_error; 32 + bool defer; 33 + }; 34 + 35 + static int check_sockaddr(struct sockaddr_in *in) 36 + { 37 + struct in_addr expected; 38 + 39 + inet_pton(AF_INET, "127.0.0.1", &expected); 40 + if (in->sin_family != AF_INET) { 41 + fprintf(stderr, "bad family %d\n", (int)htons(in->sin_family)); 42 + return -1; 43 + } 44 + if (memcmp(&expected, &in->sin_addr, sizeof(in->sin_addr))) { 45 + char buff[256]; 46 + const char *addr = inet_ntop(AF_INET, &in->sin_addr, buff, sizeof(buff)); 47 + 48 + fprintf(stderr, "unexpected address %s\n", addr ? addr : "INVALID"); 49 + return -1; 50 + } 51 + return 0; 52 + } 53 + 54 + static int test(struct args *args) 55 + { 56 + int const N = 8; 57 + int const N_BUFFS = N * 64; 58 + int const N_CQE_OVERFLOW = 4; 59 + int const min_cqes = 2; 60 + int const NAME_LEN = sizeof(struct sockaddr_storage); 61 + int const CONTROL_LEN = CMSG_ALIGN(sizeof(struct sockaddr_storage)) 62 + + sizeof(struct cmsghdr); 63 + struct io_uring ring; 64 + struct io_uring_cqe *cqe; 65 + struct io_uring_sqe *sqe; 66 + int fds[2], ret, i, j; 67 + int total_sent_bytes = 0, total_recv_bytes = 0, total_dropped_bytes = 0; 68 + int send_buff[256]; 69 + int *sent_buffs[N_BUFFS]; 70 + int *recv_buffs[N_BUFFS]; 71 + int *at; 72 + struct io_uring_cqe recv_cqe[N_BUFFS]; 73 + int recv_cqes = 0; 74 + bool early_error = false; 75 + bool early_error_started = false; 76 + struct __kernel_timespec timeout = { 77 + .tv_sec = 1, 78 + }; 79 + struct msghdr msg; 80 + struct io_uring_params params = { }; 81 + int n_sqe = 32; 82 + 83 + memset(recv_buffs, 0, sizeof(recv_buffs)); 84 + 85 + if (args->defer) 86 + params.flags |= IORING_SETUP_SINGLE_ISSUER | 87 + IORING_SETUP_DEFER_TASKRUN; 88 + 89 + if (args->early_error == ERROR_EARLY_OVERFLOW) { 90 + params.flags |= IORING_SETUP_CQSIZE; 91 + params.cq_entries = N_CQE_OVERFLOW; 92 + n_sqe = N_CQE_OVERFLOW; 93 + } 94 + 95 + ret = io_uring_queue_init_params(n_sqe, &ring, &params); 96 + if (ret) { 97 + fprintf(stderr, "queue init failed: %d\n", ret); 98 + return ret; 99 + } 100 + 101 + ret = t_create_socket_pair(fds, args->stream); 102 + if (ret) { 103 + fprintf(stderr, "t_create_socket_pair failed: %d\n", ret); 104 + return ret; 105 + } 106 + 107 + if (!args->stream) { 108 + bool val = true; 109 + 110 + /* force some cmsgs to come back to us */ 111 + ret = setsockopt(fds[0], IPPROTO_IP, IP_RECVORIGDSTADDR, &val, 112 + sizeof(val)); 113 + if (ret) { 114 + fprintf(stderr, "setsockopt failed %d\n", errno); 115 + goto cleanup; 116 + } 117 + } 118 + 119 + for (i = 0; i < ARRAY_SIZE(send_buff); i++) 120 + send_buff[i] = i; 121 + 122 + for (i = 0; i < ARRAY_SIZE(recv_buffs); i++) { 123 + /* prepare some different sized buffers */ 124 + int buffer_size = (i % 2 == 0 && (args->stream || args->recvmsg)) ? 1 : N; 125 + 126 + buffer_size *= sizeof(int); 127 + if (args->recvmsg) { 128 + buffer_size += 129 + sizeof(struct io_uring_recvmsg_out) + 130 + NAME_LEN + 131 + CONTROL_LEN; 132 + } 133 + 134 + recv_buffs[i] = malloc(buffer_size); 135 + 136 + if (i > 2 && args->early_error == ERROR_NOT_ENOUGH_BUFFERS) 137 + continue; 138 + 139 + sqe = io_uring_get_sqe(&ring); 140 + io_uring_prep_provide_buffers(sqe, recv_buffs[i], 141 + buffer_size, 1, 7, i); 142 + io_uring_sqe_set_data64(sqe, 0x999); 143 + memset(recv_buffs[i], 0xcc, buffer_size); 144 + if (io_uring_submit_and_wait_timeout(&ring, &cqe, 1, &timeout, NULL) < 0) { 145 + fprintf(stderr, "provide buffers failed: %d\n", ret); 146 + ret = -1; 147 + goto cleanup; 148 + } 149 + io_uring_cqe_seen(&ring, cqe); 150 + } 151 + 152 + sqe = io_uring_get_sqe(&ring); 153 + if (args->recvmsg) { 154 + unsigned int flags = 0; 155 + 156 + if (!args->stream) 157 + flags |= MSG_TRUNC; 158 + 159 + memset(&msg, 0, sizeof(msg)); 160 + msg.msg_namelen = NAME_LEN; 161 + msg.msg_controllen = CONTROL_LEN; 162 + io_uring_prep_recvmsg_multishot(sqe, fds[0], &msg, flags); 163 + } else { 164 + io_uring_prep_recv_multishot(sqe, fds[0], NULL, 0, 0); 165 + } 166 + sqe->flags |= IOSQE_BUFFER_SELECT; 167 + sqe->buf_group = 7; 168 + io_uring_sqe_set_data64(sqe, 1234); 169 + io_uring_submit(&ring); 170 + 171 + at = &send_buff[0]; 172 + total_sent_bytes = 0; 173 + for (i = 0; i < N; i++) { 174 + int to_send = sizeof(*at) * (i+1); 175 + 176 + total_sent_bytes += to_send; 177 + sent_buffs[i] = at; 178 + if (send(fds[1], at, to_send, 0) != to_send) { 179 + if (early_error_started) 180 + break; 181 + fprintf(stderr, "send failed %d\n", errno); 182 + ret = -1; 183 + goto cleanup; 184 + } 185 + 186 + if (i == 2) { 187 + if (args->early_error == ERROR_EARLY_CLOSE_RECEIVER) { 188 + /* allow previous sends to complete */ 189 + usleep(1000); 190 + io_uring_get_events(&ring); 191 + 192 + sqe = io_uring_get_sqe(&ring); 193 + io_uring_prep_recv(sqe, fds[0], NULL, 0, 0); 194 + io_uring_prep_cancel64(sqe, 1234, 0); 195 + io_uring_sqe_set_data64(sqe, 0x888); 196 + sqe->flags |= IOSQE_CQE_SKIP_SUCCESS; 197 + io_uring_submit(&ring); 198 + early_error_started = true; 199 + 200 + /* allow the cancel to complete */ 201 + usleep(1000); 202 + io_uring_get_events(&ring); 203 + } 204 + if (args->early_error == ERROR_EARLY_CLOSE_SENDER) { 205 + early_error_started = true; 206 + shutdown(fds[1], SHUT_RDWR); 207 + close(fds[1]); 208 + } 209 + } 210 + at += (i+1); 211 + 212 + if (args->wait_each) { 213 + ret = io_uring_wait_cqes(&ring, &cqe, 1, &timeout, NULL); 214 + if (ret) { 215 + fprintf(stderr, "wait_each failed: %d\n", ret); 216 + ret = -1; 217 + goto cleanup; 218 + } 219 + while (io_uring_peek_cqe(&ring, &cqe) == 0) { 220 + recv_cqe[recv_cqes++] = *cqe; 221 + if (cqe->flags & IORING_CQE_F_MORE) { 222 + io_uring_cqe_seen(&ring, cqe); 223 + } else { 224 + early_error = true; 225 + io_uring_cqe_seen(&ring, cqe); 226 + } 227 + } 228 + if (early_error) 229 + break; 230 + } 231 + } 232 + 233 + close(fds[1]); 234 + 235 + /* allow sends to finish */ 236 + usleep(1000); 237 + 238 + if ((args->stream && !early_error) || recv_cqes < min_cqes) { 239 + ret = io_uring_wait_cqes(&ring, &cqe, 1, &timeout, NULL); 240 + if (ret && ret != -ETIME) { 241 + fprintf(stderr, "wait final failed: %d\n", ret); 242 + ret = -1; 243 + goto cleanup; 244 + } 245 + } 246 + 247 + while (io_uring_peek_cqe(&ring, &cqe) == 0) { 248 + recv_cqe[recv_cqes++] = *cqe; 249 + io_uring_cqe_seen(&ring, cqe); 250 + } 251 + 252 + ret = -1; 253 + at = &send_buff[0]; 254 + if (recv_cqes < min_cqes) { 255 + if (recv_cqes > 0 && recv_cqe[0].res == -EINVAL) { 256 + return -ENORECVMULTISHOT; 257 + } 258 + /* some kernels apparently don't check ->ioprio, skip */ 259 + ret = -ENORECVMULTISHOT; 260 + goto cleanup; 261 + } 262 + for (i = 0; i < recv_cqes; i++) { 263 + cqe = &recv_cqe[i]; 264 + 265 + bool const is_last = i == recv_cqes - 1; 266 + 267 + bool const should_be_last = 268 + (cqe->res <= 0) || 269 + (args->stream && is_last) || 270 + (args->early_error == ERROR_EARLY_OVERFLOW && 271 + !args->wait_each && i == N_CQE_OVERFLOW); 272 + int *this_recv; 273 + int orig_payload_size = cqe->res; 274 + 275 + 276 + if (should_be_last) { 277 + int used_res = cqe->res; 278 + 279 + if (!is_last) { 280 + fprintf(stderr, "not last cqe had error %d\n", i); 281 + goto cleanup; 282 + } 283 + 284 + switch (args->early_error) { 285 + case ERROR_NOT_ENOUGH_BUFFERS: 286 + if (cqe->res != -ENOBUFS) { 287 + fprintf(stderr, 288 + "ERROR_NOT_ENOUGH_BUFFERS: res %d\n", cqe->res); 289 + goto cleanup; 290 + } 291 + break; 292 + case ERROR_EARLY_OVERFLOW: 293 + if (cqe->res < 0) { 294 + fprintf(stderr, 295 + "ERROR_EARLY_OVERFLOW: res %d\n", cqe->res); 296 + goto cleanup; 297 + } 298 + break; 299 + case ERROR_EARLY_CLOSE_RECEIVER: 300 + if (cqe->res != -ECANCELED) { 301 + fprintf(stderr, 302 + "ERROR_EARLY_CLOSE_RECEIVER: res %d\n", cqe->res); 303 + goto cleanup; 304 + } 305 + break; 306 + case ERROR_NONE: 307 + case ERROR_EARLY_CLOSE_SENDER: 308 + if (args->recvmsg && (cqe->flags & IORING_CQE_F_BUFFER)) { 309 + void *buff = recv_buffs[cqe->flags >> 16]; 310 + struct io_uring_recvmsg_out *o = 311 + io_uring_recvmsg_validate(buff, cqe->res, &msg); 312 + 313 + if (!o) { 314 + fprintf(stderr, "invalid buff\n"); 315 + goto cleanup; 316 + } 317 + if (o->payloadlen != 0) { 318 + fprintf(stderr, "expected 0 payloadlen, got %u\n", 319 + o->payloadlen); 320 + goto cleanup; 321 + } 322 + used_res = 0; 323 + } else if (cqe->res != 0) { 324 + fprintf(stderr, "early error: res %d\n", cqe->res); 325 + goto cleanup; 326 + } 327 + break; 328 + case ERROR_EARLY_LAST: 329 + fprintf(stderr, "bad error_early\n"); 330 + goto cleanup; 331 + }; 332 + 333 + if (cqe->res <= 0 && cqe->flags & IORING_CQE_F_BUFFER) { 334 + fprintf(stderr, "final BUFFER flag set\n"); 335 + goto cleanup; 336 + } 337 + 338 + if (cqe->flags & IORING_CQE_F_MORE) { 339 + fprintf(stderr, "final MORE flag set\n"); 340 + goto cleanup; 341 + } 342 + 343 + if (used_res <= 0) 344 + continue; 345 + } else { 346 + if (!(cqe->flags & IORING_CQE_F_MORE)) { 347 + fprintf(stderr, "MORE flag not set\n"); 348 + goto cleanup; 349 + } 350 + } 351 + 352 + if (!(cqe->flags & IORING_CQE_F_BUFFER)) { 353 + fprintf(stderr, "BUFFER flag not set\n"); 354 + goto cleanup; 355 + } 356 + 357 + this_recv = recv_buffs[cqe->flags >> 16]; 358 + 359 + if (args->recvmsg) { 360 + struct io_uring_recvmsg_out *o = io_uring_recvmsg_validate( 361 + this_recv, cqe->res, &msg); 362 + 363 + if (!o) { 364 + fprintf(stderr, "bad recvmsg\n"); 365 + goto cleanup; 366 + } 367 + orig_payload_size = o->payloadlen; 368 + 369 + if (!args->stream) { 370 + orig_payload_size = o->payloadlen; 371 + 372 + struct cmsghdr *cmsg; 373 + 374 + if (o->namelen < sizeof(struct sockaddr_in)) { 375 + fprintf(stderr, "bad addr len %d", 376 + o->namelen); 377 + goto cleanup; 378 + } 379 + if (check_sockaddr((struct sockaddr_in *)io_uring_recvmsg_name(o))) 380 + goto cleanup; 381 + 382 + cmsg = io_uring_recvmsg_cmsg_firsthdr(o, &msg); 383 + if (!cmsg || 384 + cmsg->cmsg_level != IPPROTO_IP || 385 + cmsg->cmsg_type != IP_RECVORIGDSTADDR) { 386 + fprintf(stderr, "bad cmsg"); 387 + goto cleanup; 388 + } 389 + if (check_sockaddr((struct sockaddr_in *)CMSG_DATA(cmsg))) 390 + goto cleanup; 391 + cmsg = io_uring_recvmsg_cmsg_nexthdr(o, &msg, cmsg); 392 + if (cmsg) { 393 + fprintf(stderr, "unexpected extra cmsg\n"); 394 + goto cleanup; 395 + } 396 + 397 + } 398 + 399 + this_recv = (int *)io_uring_recvmsg_payload(o, &msg); 400 + cqe->res = io_uring_recvmsg_payload_length(o, cqe->res, &msg); 401 + if (o->payloadlen != cqe->res) { 402 + if (!(o->flags & MSG_TRUNC)) { 403 + fprintf(stderr, "expected truncated flag\n"); 404 + goto cleanup; 405 + } 406 + total_dropped_bytes += (o->payloadlen - cqe->res); 407 + } 408 + } 409 + 410 + total_recv_bytes += cqe->res; 411 + 412 + if (cqe->res % 4 != 0) { 413 + /* 414 + * doesn't seem to happen in practice, would need some 415 + * work to remove this requirement 416 + */ 417 + fprintf(stderr, "unexpectedly aligned buffer cqe->res=%d\n", cqe->res); 418 + goto cleanup; 419 + } 420 + 421 + /* 422 + * for tcp: check buffer arrived in order 423 + * for udp: based on size validate data based on size 424 + */ 425 + if (!args->stream) { 426 + int sent_idx = orig_payload_size / sizeof(*at) - 1; 427 + 428 + if (sent_idx < 0 || sent_idx > N) { 429 + fprintf(stderr, "Bad sent idx: %d\n", sent_idx); 430 + goto cleanup; 431 + } 432 + at = sent_buffs[sent_idx]; 433 + } 434 + for (j = 0; j < cqe->res / 4; j++) { 435 + int sent = *at++; 436 + int recv = *this_recv++; 437 + 438 + if (sent != recv) { 439 + fprintf(stderr, "recv=%d sent=%d\n", recv, sent); 440 + goto cleanup; 441 + } 442 + } 443 + } 444 + 445 + if (args->early_error == ERROR_NONE && 446 + total_recv_bytes + total_dropped_bytes < total_sent_bytes) { 447 + fprintf(stderr, 448 + "missing recv: recv=%d dropped=%d sent=%d\n", 449 + total_recv_bytes, total_sent_bytes, total_dropped_bytes); 450 + goto cleanup; 451 + } 452 + 453 + ret = 0; 454 + cleanup: 455 + for (i = 0; i < ARRAY_SIZE(recv_buffs); i++) 456 + free(recv_buffs[i]); 457 + close(fds[0]); 458 + close(fds[1]); 459 + io_uring_queue_exit(&ring); 460 + 461 + return ret; 462 + } 463 + 464 + int main(int argc, char *argv[]) 465 + { 466 + int ret; 467 + int loop; 468 + int early_error = 0; 469 + bool has_defer; 470 + 471 + if (argc > 1) 472 + return T_EXIT_SKIP; 473 + 474 + has_defer = t_probe_defer_taskrun(); 475 + 476 + for (loop = 0; loop < 16; loop++) { 477 + struct args a = { 478 + .stream = loop & 0x01, 479 + .wait_each = loop & 0x2, 480 + .recvmsg = loop & 0x04, 481 + .defer = loop & 0x08, 482 + }; 483 + if (a.defer && !has_defer) 484 + continue; 485 + for (early_error = 0; early_error < ERROR_EARLY_LAST; early_error++) { 486 + a.early_error = (enum early_error_t)early_error; 487 + ret = test(&a); 488 + if (ret) { 489 + if (ret == -ENORECVMULTISHOT) { 490 + if (loop == 0) 491 + return T_EXIT_SKIP; 492 + fprintf(stderr, 493 + "ENORECVMULTISHOT received but loop>0\n"); 494 + } 495 + fprintf(stderr, 496 + "test stream=%d wait_each=%d recvmsg=%d early_error=%d " 497 + " defer=%d failed\n", 498 + a.stream, a.wait_each, a.recvmsg, a.early_error, a.defer); 499 + return T_EXIT_FAIL; 500 + } 501 + } 502 + } 503 + 504 + return T_EXIT_PASS; 505 + }
+13
vendor/liburing/test/ring-leak.c
··· 135 135 return 0; 136 136 } 137 137 138 + static void trigger_unix_gc(void) 139 + { 140 + int fd; 141 + 142 + fd = socket(AF_UNIX, SOCK_DGRAM, 0); 143 + if (fd < 0) 144 + perror("socket dgram"); 145 + else 146 + close(fd); 147 + } 148 + 138 149 static int test_scm_cycles(bool update) 139 150 { 140 151 char buffer[128]; ··· 192 203 193 204 /* should unregister files and close the write fd */ 194 205 io_uring_queue_exit(&ring); 206 + 207 + trigger_unix_gc(); 195 208 196 209 /* 197 210 * We're trying to wait for the ring to "really" exit, that will be
+12 -7
vendor/liburing/test/ringbuf-read.c
··· 156 156 ret = write(fd, buf, BUF_SIZE); 157 157 if (ret != BUF_SIZE) { 158 158 fprintf(stderr, "bad file prep write\n"); 159 + close(fd); 159 160 goto err; 160 161 } 161 162 } ··· 164 165 ret = test(fname, 1, 0); 165 166 if (ret) { 166 167 fprintf(stderr, "dio test failed\n"); 167 - return ret; 168 + goto err; 168 169 } 169 170 if (no_buf_ring) 170 - return 0; 171 + goto pass; 171 172 172 173 ret = test(fname, 0, 0); 173 174 if (ret) { 174 175 fprintf(stderr, "buffered test failed\n"); 175 - return ret; 176 + goto err; 176 177 } 177 178 178 179 ret = test(fname, 1, 1); 179 180 if (ret) { 180 181 fprintf(stderr, "dio async test failed\n"); 181 - return ret; 182 + goto err; 182 183 } 183 184 184 185 ret = test(fname, 0, 1); 185 186 if (ret) { 186 187 fprintf(stderr, "buffered async test failed\n"); 187 - return ret; 188 + goto err; 188 189 } 189 190 190 - return 0; 191 + pass: 192 + ret = T_EXIT_PASS; 193 + goto out; 191 194 err: 195 + ret = T_EXIT_FAIL; 196 + out: 192 197 if (do_unlink) 193 198 unlink(fname); 194 - return 1; 199 + return ret; 195 200 }
+24 -12
vendor/liburing/test/rsrc_tags.c
··· 40 40 const void *arg, const __u64 *tags) 41 41 { 42 42 struct io_uring_rsrc_register reg; 43 - int ret, reg_type; 43 + int reg_type; 44 44 45 45 memset(&reg, 0, sizeof(reg)); 46 46 reg.nr = nr; ··· 51 51 if (type != TEST_IORING_RSRC_FILE) 52 52 reg_type = IORING_REGISTER_BUFFERS2; 53 53 54 - ret = __sys_io_uring_register(ring->ring_fd, reg_type, 55 - &reg, sizeof(reg)); 56 - return ret ? -errno : 0; 54 + return __sys_io_uring_register(ring->ring_fd, reg_type, &reg, 55 + sizeof(reg)); 57 56 } 58 57 59 58 /* ··· 64 63 const void *arg, const __u64 *tags) 65 64 { 66 65 struct io_uring_rsrc_update2 up; 67 - int ret, up_type; 66 + int up_type; 68 67 69 68 memset(&up, 0, sizeof(up)); 70 69 up.offset = off; ··· 75 74 up_type = IORING_REGISTER_FILES_UPDATE2; 76 75 if (type != TEST_IORING_RSRC_FILE) 77 76 up_type = IORING_REGISTER_BUFFERS_UPDATE; 78 - ret = __sys_io_uring_register(ring->ring_fd, up_type, 79 - &up, sizeof(up)); 80 - return ret < 0 ? -errno : ret; 77 + return __sys_io_uring_register(ring->ring_fd, up_type, &up, sizeof(up)); 81 78 } 82 79 83 80 static bool has_rsrc_update(void) ··· 185 182 return 1; 186 183 } 187 184 188 - /* test that CQE is not emmited before we're done with a buffer */ 185 + /* test that CQE is not emitted before we're done with a buffer */ 189 186 sqe = io_uring_get_sqe(&ring); 190 187 io_uring_prep_read_fixed(sqe, pipes[0], tmp_buf, 10, 0, 0); 191 188 sqe->user_data = 100; ··· 350 347 ret = io_uring_register_files_update(&ring, off, &fd, 1); 351 348 assert(ret == 1); 352 349 ret = io_uring_wait_cqe(&ring, &cqe); 353 - assert(!ret && cqe->user_data == tags[off]); 350 + if (ret) { 351 + fprintf(stderr, "io_uring wait ret=%d\n", ret); 352 + return 1; 353 + } 354 + if (cqe->user_data != tags[off]) { 355 + fprintf(stderr, "data %lx != %lx\n", 356 + (unsigned long) cqe->user_data, 357 + (unsigned long) tags[off]); 358 + return 1; 359 + } 354 360 io_uring_cqe_seen(&ring, cqe); 355 361 356 362 /* remove removed file, shouldn't emit old tag */ ··· 404 410 405 411 int main(int argc, char *argv[]) 406 412 { 407 - int ring_flags[] = {0, IORING_SETUP_IOPOLL, IORING_SETUP_SQPOLL}; 413 + int ring_flags[] = {0, IORING_SETUP_IOPOLL, IORING_SETUP_SQPOLL, 414 + IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN}; 408 415 int i, ret; 409 416 410 417 if (argc > 1) ··· 426 433 } 427 434 428 435 for (i = 0; i < sizeof(ring_flags) / sizeof(ring_flags[0]); i++) { 429 - ret = test_files(ring_flags[i]); 436 + int flag = ring_flags[i]; 437 + 438 + if (flag & IORING_SETUP_DEFER_TASKRUN && !t_probe_defer_taskrun()) 439 + continue; 440 + 441 + ret = test_files(flag); 430 442 if (ret) { 431 443 printf("test_tag failed, type %i\n", i); 432 444 return ret;
+17 -19
vendor/liburing/test/runtests.sh
··· 1 1 #!/usr/bin/env bash 2 2 3 3 TESTS=("$@") 4 - RET=0 5 4 TIMEOUT=60 6 5 DMESG_FILTER="cat" 7 6 TEST_DIR=$(dirname "$0") 8 - FAILED="" 9 - SKIPPED="" 10 - TIMED_OUT="" 7 + FAILED=() 8 + SKIPPED=() 9 + TIMED_OUT=() 11 10 TEST_FILES="" 12 11 declare -A TEST_MAP 13 12 ··· 94 93 # shellcheck disable=SC2181 95 94 if [ $? -eq 0 ]; then 96 95 echo "Test skipped" 97 - SKIPPED="$SKIPPED <$test_string>" 96 + SKIPPED+=("<$test_string>") 98 97 return 99 98 fi 100 99 ··· 111 110 # Check test status 112 111 if [ "$status" -eq 124 ]; then 113 112 echo "Test $test_name timed out (may not be a failure)" 114 - TIMED_OUT="$TIMED_OUT <$test_string>" 113 + TIMED_OUT+=("<$test_string>") 114 + elif [ "$status" -eq 77 ]; then 115 + echo "Skipped" 116 + SKIPPED+=("<$test_string>") 115 117 elif [ "$status" -ne 0 ]; then 116 118 echo "Test $test_name failed with ret $status" 117 - FAILED="$FAILED <$test_string>" 118 - RET=1 119 + FAILED+=("<$test_string>") 119 120 elif ! _check_dmesg "$dmesg_marker" "$test_name"; then 120 121 echo "Test $test_name failed dmesg check" 121 - FAILED="$FAILED <$test_string>" 122 - RET=1 122 + FAILED+=("<$test_string>") 123 123 else 124 124 if [ -f "output/$out_name" ]; then 125 125 T_PREV=$(cat "output/$out_name") ··· 153 153 fi 154 154 done 155 155 156 - if [ -n "$SKIPPED" ]; then 157 - echo "Tests skipped: $SKIPPED" 156 + if [ "${#TIMED_OUT[*]}" -ne 0 ]; then 157 + echo "Tests timed out (${#TIMED_OUT[*]}): ${TIMED_OUT[*]}" 158 158 fi 159 159 160 - if [ -n "$TIMED_OUT" ]; then 161 - echo "Tests timed out: $TIMED_OUT" 162 - fi 163 - 164 - if [ "${RET}" -ne 0 ]; then 165 - echo "Tests failed: $FAILED" 166 - exit $RET 160 + if [ "${#FAILED[*]}" -ne 0 ]; then 161 + echo "Tests failed (${#FAILED[*]}): ${FAILED[*]}" 162 + exit 1 163 + elif [ "${#SKIPPED[*]}" -ne 0 ] && [ -n "$TEST_GNU_EXITCODE" ]; then 164 + exit 77 167 165 else 168 166 echo "All tests passed" 169 167 exit 0
+1 -1
vendor/liburing/test/rw_merge_test.c
··· 79 79 assert(ret == 1); 80 80 81 81 /* 82 - * Read may stuck because of bug there request was be incorrecly 82 + * Read may stuck because of bug there request was be incorrectly 83 83 * merged with <REQ1> request 84 84 */ 85 85 ret = io_uring_wait_cqe_timeout(&ring, &cqe, &ts);
+684
vendor/liburing/test/send-zerocopy.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + #include <stdio.h> 3 + #include <stdlib.h> 4 + #include <stdint.h> 5 + #include <assert.h> 6 + #include <errno.h> 7 + #include <error.h> 8 + #include <limits.h> 9 + #include <fcntl.h> 10 + #include <unistd.h> 11 + #include <stdbool.h> 12 + #include <string.h> 13 + 14 + #include <arpa/inet.h> 15 + #include <linux/errqueue.h> 16 + #include <linux/if_packet.h> 17 + #include <linux/ipv6.h> 18 + #include <linux/socket.h> 19 + #include <linux/sockios.h> 20 + #include <net/ethernet.h> 21 + #include <net/if.h> 22 + #include <netinet/ip.h> 23 + #include <netinet/in.h> 24 + #include <netinet/ip6.h> 25 + #include <netinet/tcp.h> 26 + #include <netinet/udp.h> 27 + #include <sys/socket.h> 28 + #include <sys/time.h> 29 + #include <sys/resource.h> 30 + #include <sys/un.h> 31 + #include <sys/ioctl.h> 32 + #include <sys/socket.h> 33 + #include <sys/stat.h> 34 + #include <sys/time.h> 35 + #include <sys/types.h> 36 + #include <sys/wait.h> 37 + 38 + #include "liburing.h" 39 + #include "helpers.h" 40 + 41 + #define MAX_MSG 128 42 + 43 + #define PORT 10200 44 + #define HOST "127.0.0.1" 45 + #define HOSTV6 "::1" 46 + 47 + #define CORK_REQS 5 48 + #define RX_TAG 10000 49 + #define BUFFER_OFFSET 41 50 + 51 + #ifndef ARRAY_SIZE 52 + #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 53 + #endif 54 + 55 + enum { 56 + BUF_T_NORMAL, 57 + BUF_T_SMALL, 58 + BUF_T_NONALIGNED, 59 + BUF_T_LARGE, 60 + }; 61 + 62 + static char *tx_buffer, *rx_buffer; 63 + static struct iovec buffers_iov[4]; 64 + static bool has_sendmsg; 65 + 66 + static bool check_cq_empty(struct io_uring *ring) 67 + { 68 + struct io_uring_cqe *cqe = NULL; 69 + int ret; 70 + 71 + ret = io_uring_peek_cqe(ring, &cqe); /* nothing should be there */ 72 + return ret == -EAGAIN; 73 + } 74 + 75 + static int test_basic_send(struct io_uring *ring, int sock_tx, int sock_rx) 76 + { 77 + struct io_uring_sqe *sqe; 78 + struct io_uring_cqe *cqe; 79 + int msg_flags = 0; 80 + unsigned zc_flags = 0; 81 + int payload_size = 100; 82 + int ret; 83 + 84 + sqe = io_uring_get_sqe(ring); 85 + io_uring_prep_send_zc(sqe, sock_tx, tx_buffer, payload_size, 86 + msg_flags, zc_flags); 87 + sqe->user_data = 1; 88 + 89 + ret = io_uring_submit(ring); 90 + assert(ret == 1); 91 + 92 + ret = io_uring_wait_cqe(ring, &cqe); 93 + assert(!ret && cqe->user_data == 1); 94 + if (cqe->res == -EINVAL) { 95 + assert(!(cqe->flags & IORING_CQE_F_MORE)); 96 + return T_EXIT_SKIP; 97 + } else if (cqe->res != payload_size) { 98 + fprintf(stderr, "send failed %i\n", cqe->res); 99 + return T_EXIT_FAIL; 100 + } 101 + 102 + assert(cqe->flags & IORING_CQE_F_MORE); 103 + io_uring_cqe_seen(ring, cqe); 104 + 105 + ret = io_uring_wait_cqe(ring, &cqe); 106 + assert(!ret); 107 + assert(cqe->user_data == 1); 108 + assert(cqe->flags & IORING_CQE_F_NOTIF); 109 + assert(!(cqe->flags & IORING_CQE_F_MORE)); 110 + io_uring_cqe_seen(ring, cqe); 111 + assert(check_cq_empty(ring)); 112 + 113 + ret = recv(sock_rx, rx_buffer, payload_size, MSG_TRUNC); 114 + assert(ret == payload_size); 115 + return T_EXIT_PASS; 116 + } 117 + 118 + static int test_send_faults(struct io_uring *ring, int sock_tx, int sock_rx) 119 + { 120 + struct io_uring_sqe *sqe; 121 + struct io_uring_cqe *cqe; 122 + int msg_flags = 0; 123 + unsigned zc_flags = 0; 124 + int payload_size = 100; 125 + int ret, i, nr_cqes = 2; 126 + 127 + sqe = io_uring_get_sqe(ring); 128 + io_uring_prep_send_zc(sqe, sock_tx, (void *)1UL, payload_size, 129 + msg_flags, zc_flags); 130 + sqe->user_data = 1; 131 + 132 + sqe = io_uring_get_sqe(ring); 133 + io_uring_prep_send_zc(sqe, sock_tx, tx_buffer, payload_size, 134 + msg_flags, zc_flags); 135 + sqe->user_data = 2; 136 + io_uring_prep_send_set_addr(sqe, (const struct sockaddr *)1UL, 137 + sizeof(struct sockaddr_in6)); 138 + 139 + ret = io_uring_submit(ring); 140 + assert(ret == 2); 141 + 142 + for (i = 0; i < nr_cqes; i++) { 143 + ret = io_uring_wait_cqe(ring, &cqe); 144 + assert(!ret); 145 + assert(cqe->user_data <= 2); 146 + 147 + if (!(cqe->flags & IORING_CQE_F_NOTIF)) { 148 + assert(cqe->res == -EFAULT); 149 + if (cqe->flags & IORING_CQE_F_MORE) 150 + nr_cqes++; 151 + } 152 + io_uring_cqe_seen(ring, cqe); 153 + } 154 + assert(check_cq_empty(ring)); 155 + return T_EXIT_PASS; 156 + } 157 + 158 + static int create_socketpair_ip(struct sockaddr_storage *addr, 159 + int *sock_client, int *sock_server, 160 + bool ipv6, bool client_connect, 161 + bool msg_zc, bool tcp) 162 + { 163 + int family, addr_size; 164 + int ret, val; 165 + int listen_sock = -1; 166 + int sock; 167 + 168 + memset(addr, 0, sizeof(*addr)); 169 + if (ipv6) { 170 + struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr; 171 + 172 + family = AF_INET6; 173 + saddr->sin6_family = family; 174 + saddr->sin6_port = htons(PORT); 175 + addr_size = sizeof(*saddr); 176 + } else { 177 + struct sockaddr_in *saddr = (struct sockaddr_in *)addr; 178 + 179 + family = AF_INET; 180 + saddr->sin_family = family; 181 + saddr->sin_port = htons(PORT); 182 + saddr->sin_addr.s_addr = htonl(INADDR_ANY); 183 + addr_size = sizeof(*saddr); 184 + } 185 + 186 + /* server sock setup */ 187 + if (tcp) { 188 + sock = listen_sock = socket(family, SOCK_STREAM, IPPROTO_TCP); 189 + } else { 190 + sock = *sock_server = socket(family, SOCK_DGRAM, 0); 191 + } 192 + if (sock < 0) { 193 + perror("socket"); 194 + return 1; 195 + } 196 + val = 1; 197 + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 198 + val = 1; 199 + setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); 200 + 201 + ret = bind(sock, (struct sockaddr *)addr, addr_size); 202 + if (ret < 0) { 203 + perror("bind"); 204 + return 1; 205 + } 206 + if (tcp) { 207 + ret = listen(sock, 128); 208 + assert(ret != -1); 209 + } 210 + 211 + if (ipv6) { 212 + struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr; 213 + 214 + inet_pton(AF_INET6, HOSTV6, &(saddr->sin6_addr)); 215 + } else { 216 + struct sockaddr_in *saddr = (struct sockaddr_in *)addr; 217 + 218 + inet_pton(AF_INET, HOST, &saddr->sin_addr); 219 + } 220 + 221 + /* client sock setup */ 222 + if (tcp) { 223 + *sock_client = socket(family, SOCK_STREAM, IPPROTO_TCP); 224 + assert(client_connect); 225 + } else { 226 + *sock_client = socket(family, SOCK_DGRAM, 0); 227 + } 228 + if (*sock_client < 0) { 229 + perror("socket"); 230 + return 1; 231 + } 232 + if (client_connect) { 233 + ret = connect(*sock_client, (struct sockaddr *)addr, addr_size); 234 + if (ret < 0) { 235 + perror("connect"); 236 + return 1; 237 + } 238 + } 239 + if (msg_zc) { 240 + val = 1; 241 + if (setsockopt(*sock_client, SOL_SOCKET, SO_ZEROCOPY, &val, sizeof(val))) { 242 + perror("setsockopt zc"); 243 + return 1; 244 + } 245 + } 246 + if (tcp) { 247 + *sock_server = accept(listen_sock, NULL, NULL); 248 + if (!*sock_server) { 249 + fprintf(stderr, "can't accept\n"); 250 + return 1; 251 + } 252 + close(listen_sock); 253 + } 254 + return 0; 255 + } 256 + 257 + static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_server, 258 + bool fixed_buf, struct sockaddr_storage *addr, 259 + bool cork, bool mix_register, 260 + int buf_idx, bool force_async, bool use_sendmsg) 261 + { 262 + struct iovec iov[CORK_REQS]; 263 + struct msghdr msghdr[CORK_REQS]; 264 + const unsigned zc_flags = 0; 265 + struct io_uring_sqe *sqe; 266 + struct io_uring_cqe *cqe; 267 + int nr_reqs = cork ? CORK_REQS : 1; 268 + int i, ret, nr_cqes, addr_len = 0; 269 + size_t send_size = buffers_iov[buf_idx].iov_len; 270 + size_t chunk_size = send_size / nr_reqs; 271 + size_t chunk_size_last = send_size - chunk_size * (nr_reqs - 1); 272 + char *buf = buffers_iov[buf_idx].iov_base; 273 + 274 + if (addr) { 275 + sa_family_t fam = ((struct sockaddr_in *)addr)->sin_family; 276 + 277 + addr_len = (fam == AF_INET) ? sizeof(struct sockaddr_in) : 278 + sizeof(struct sockaddr_in6); 279 + } 280 + 281 + memset(rx_buffer, 0, send_size); 282 + 283 + for (i = 0; i < nr_reqs; i++) { 284 + bool real_fixed_buf = fixed_buf; 285 + size_t cur_size = chunk_size; 286 + int msg_flags = MSG_WAITALL; 287 + 288 + if (mix_register) 289 + real_fixed_buf = rand() & 1; 290 + 291 + if (cork && i != nr_reqs - 1) 292 + msg_flags |= MSG_MORE; 293 + if (i == nr_reqs - 1) 294 + cur_size = chunk_size_last; 295 + 296 + sqe = io_uring_get_sqe(ring); 297 + 298 + if (!use_sendmsg) { 299 + io_uring_prep_send_zc(sqe, sock_client, buf + i * chunk_size, 300 + cur_size, msg_flags, zc_flags); 301 + if (real_fixed_buf) { 302 + sqe->ioprio |= IORING_RECVSEND_FIXED_BUF; 303 + sqe->buf_index = buf_idx; 304 + } 305 + if (addr) 306 + io_uring_prep_send_set_addr(sqe, (const struct sockaddr *)addr, 307 + addr_len); 308 + } else { 309 + io_uring_prep_sendmsg_zc(sqe, sock_client, &msghdr[i], msg_flags); 310 + 311 + memset(&msghdr[i], 0, sizeof(msghdr[i])); 312 + iov[i].iov_len = cur_size; 313 + iov[i].iov_base = buf + i * chunk_size; 314 + msghdr[i].msg_iov = &iov[i]; 315 + msghdr[i].msg_iovlen = 1; 316 + if (addr) { 317 + msghdr[i].msg_name = addr; 318 + msghdr[i].msg_namelen = addr_len; 319 + } 320 + } 321 + sqe->user_data = i; 322 + if (force_async) 323 + sqe->flags |= IOSQE_ASYNC; 324 + if (i != nr_reqs - 1) 325 + sqe->flags |= IOSQE_IO_LINK; 326 + } 327 + 328 + sqe = io_uring_get_sqe(ring); 329 + io_uring_prep_recv(sqe, sock_server, rx_buffer, send_size, MSG_WAITALL); 330 + sqe->user_data = RX_TAG; 331 + 332 + ret = io_uring_submit(ring); 333 + if (ret != nr_reqs + 1) { 334 + fprintf(stderr, "submit failed, got %i expected %i\n", ret, nr_reqs); 335 + return 1; 336 + } 337 + 338 + nr_cqes = 2 * nr_reqs + 1; 339 + for (i = 0; i < nr_cqes; i++) { 340 + int expected = chunk_size; 341 + 342 + ret = io_uring_wait_cqe(ring, &cqe); 343 + if (ret) { 344 + fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret); 345 + return 1; 346 + } 347 + if (cqe->user_data == RX_TAG) { 348 + if (cqe->res != send_size) { 349 + fprintf(stderr, "rx failed %i\n", cqe->res); 350 + return 1; 351 + } 352 + io_uring_cqe_seen(ring, cqe); 353 + continue; 354 + } 355 + 356 + if (cqe->user_data >= nr_reqs) { 357 + fprintf(stderr, "invalid user_data %lu\n", 358 + (unsigned long)cqe->user_data); 359 + return 1; 360 + } 361 + if (!(cqe->flags & IORING_CQE_F_NOTIF)) { 362 + if (cqe->user_data == nr_reqs - 1) 363 + expected = chunk_size_last; 364 + if (cqe->res != expected) { 365 + fprintf(stderr, "invalid cqe->res %d expected %d\n", 366 + cqe->res, expected); 367 + return 1; 368 + } 369 + } 370 + if ((cqe->flags & IORING_CQE_F_MORE) == 371 + (cqe->flags & IORING_CQE_F_NOTIF)) { 372 + fprintf(stderr, "unexpected cflags %i res %i\n", 373 + cqe->flags, cqe->res); 374 + return 1; 375 + } 376 + io_uring_cqe_seen(ring, cqe); 377 + } 378 + 379 + for (i = 0; i < send_size; i++) { 380 + if (buf[i] != rx_buffer[i]) { 381 + fprintf(stderr, "botched data, first mismated byte %i, " 382 + "%u vs %u\n", i, buf[i], rx_buffer[i]); 383 + return 1; 384 + } 385 + } 386 + return 0; 387 + } 388 + 389 + static int test_inet_send(struct io_uring *ring) 390 + { 391 + struct sockaddr_storage addr; 392 + int sock_client = -1, sock_server = -1; 393 + int ret, j, i; 394 + 395 + for (j = 0; j < 16; j++) { 396 + bool ipv6 = j & 1; 397 + bool client_connect = j & 2; 398 + bool msg_zc_set = j & 4; 399 + bool tcp = j & 8; 400 + 401 + if (tcp && !client_connect) 402 + continue; 403 + 404 + ret = create_socketpair_ip(&addr, &sock_client, &sock_server, ipv6, 405 + client_connect, msg_zc_set, tcp); 406 + if (ret) { 407 + fprintf(stderr, "sock prep failed %d\n", ret); 408 + return 1; 409 + } 410 + 411 + for (i = 0; i < 256; i++) { 412 + int buf_flavour = i & 3; 413 + bool fixed_buf = i & 4; 414 + struct sockaddr_storage *addr_arg = (i & 8) ? &addr : NULL; 415 + bool cork = i & 16; 416 + bool mix_register = i & 32; 417 + bool force_async = i & 64; 418 + bool use_sendmsg = i & 128; 419 + 420 + if (buf_flavour == BUF_T_LARGE && !tcp) 421 + continue; 422 + if (!buffers_iov[buf_flavour].iov_base) 423 + continue; 424 + if (tcp && (cork || addr_arg)) 425 + continue; 426 + if (mix_register && (!cork || fixed_buf)) 427 + continue; 428 + if (!client_connect && addr_arg == NULL) 429 + continue; 430 + if (use_sendmsg && (mix_register || fixed_buf || !has_sendmsg)) 431 + continue; 432 + 433 + ret = do_test_inet_send(ring, sock_client, sock_server, fixed_buf, 434 + addr_arg, cork, mix_register, 435 + buf_flavour, force_async, use_sendmsg); 436 + if (ret) { 437 + fprintf(stderr, "send failed fixed buf %i, conn %i, addr %i, " 438 + "cork %i\n", 439 + fixed_buf, client_connect, !!addr_arg, 440 + cork); 441 + return 1; 442 + } 443 + } 444 + 445 + close(sock_client); 446 + close(sock_server); 447 + } 448 + return 0; 449 + } 450 + 451 + static int test_async_addr(struct io_uring *ring) 452 + { 453 + struct io_uring_sqe *sqe; 454 + struct io_uring_cqe *cqe; 455 + struct sockaddr_storage addr; 456 + int sock_tx = -1, sock_rx = -1; 457 + struct __kernel_timespec ts; 458 + int ret; 459 + 460 + ts.tv_sec = 1; 461 + ts.tv_nsec = 0; 462 + ret = create_socketpair_ip(&addr, &sock_tx, &sock_rx, true, false, false, false); 463 + if (ret) { 464 + fprintf(stderr, "sock prep failed %d\n", ret); 465 + return 1; 466 + } 467 + 468 + sqe = io_uring_get_sqe(ring); 469 + io_uring_prep_timeout(sqe, &ts, 0, IORING_TIMEOUT_ETIME_SUCCESS); 470 + sqe->user_data = 1; 471 + sqe->flags |= IOSQE_IO_LINK; 472 + 473 + sqe = io_uring_get_sqe(ring); 474 + io_uring_prep_send_zc(sqe, sock_tx, tx_buffer, 1, 0, 0); 475 + sqe->user_data = 2; 476 + io_uring_prep_send_set_addr(sqe, (const struct sockaddr *)&addr, 477 + sizeof(struct sockaddr_in6)); 478 + 479 + ret = io_uring_submit(ring); 480 + assert(ret == 2); 481 + memset(&addr, 0, sizeof(addr)); 482 + 483 + ret = io_uring_wait_cqe(ring, &cqe); 484 + if (ret) { 485 + fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret); 486 + return 1; 487 + } 488 + if (cqe->user_data != 1 || cqe->res != -ETIME) { 489 + fprintf(stderr, "invalid timeout res %i %i\n", 490 + (int)cqe->user_data, cqe->res); 491 + return 1; 492 + } 493 + io_uring_cqe_seen(ring, cqe); 494 + 495 + ret = io_uring_wait_cqe(ring, &cqe); 496 + if (ret) { 497 + fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret); 498 + return 1; 499 + } 500 + if (cqe->user_data != 2 || cqe->res != 1) { 501 + fprintf(stderr, "invalid send %i %i\n", 502 + (int)cqe->user_data, cqe->res); 503 + return 1; 504 + } 505 + io_uring_cqe_seen(ring, cqe); 506 + ret = recv(sock_rx, rx_buffer, 1, MSG_TRUNC); 507 + assert(ret == 1); 508 + 509 + ret = io_uring_wait_cqe(ring, &cqe); 510 + if (ret) { 511 + fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret); 512 + return 1; 513 + } 514 + assert(cqe->flags & IORING_CQE_F_NOTIF); 515 + io_uring_cqe_seen(ring, cqe); 516 + 517 + close(sock_tx); 518 + close(sock_rx); 519 + return 0; 520 + } 521 + 522 + static bool io_check_zc_sendmsg(struct io_uring *ring) 523 + { 524 + struct io_uring_probe *p; 525 + int ret; 526 + 527 + p = t_calloc(1, sizeof(*p) + 256 * sizeof(struct io_uring_probe_op)); 528 + if (!p) { 529 + fprintf(stderr, "probe allocation failed\n"); 530 + return false; 531 + } 532 + ret = io_uring_register_probe(ring, p, 256); 533 + if (ret) 534 + return false; 535 + return p->ops_len > IORING_OP_SENDMSG_ZC; 536 + } 537 + 538 + /* see also send_recv.c:test_invalid */ 539 + static int test_invalid_zc(int fds[2]) 540 + { 541 + struct io_uring ring; 542 + int ret; 543 + struct io_uring_cqe *cqe; 544 + struct io_uring_sqe *sqe; 545 + bool notif = false; 546 + 547 + if (!has_sendmsg) 548 + return 0; 549 + 550 + ret = t_create_ring(8, &ring, 0); 551 + if (ret) 552 + return ret; 553 + 554 + sqe = io_uring_get_sqe(&ring); 555 + io_uring_prep_sendmsg(sqe, fds[0], NULL, MSG_WAITALL); 556 + sqe->opcode = IORING_OP_SENDMSG_ZC; 557 + sqe->flags |= IOSQE_ASYNC; 558 + 559 + ret = io_uring_submit(&ring); 560 + if (ret != 1) { 561 + fprintf(stderr, "submit failed %i\n", ret); 562 + return ret; 563 + } 564 + ret = io_uring_wait_cqe(&ring, &cqe); 565 + if (ret) 566 + return 1; 567 + if (cqe->flags & IORING_CQE_F_MORE) 568 + notif = true; 569 + io_uring_cqe_seen(&ring, cqe); 570 + 571 + if (notif) { 572 + ret = io_uring_wait_cqe(&ring, &cqe); 573 + if (ret) 574 + return 1; 575 + io_uring_cqe_seen(&ring, cqe); 576 + } 577 + io_uring_queue_exit(&ring); 578 + return 0; 579 + } 580 + 581 + int main(int argc, char *argv[]) 582 + { 583 + struct sockaddr_storage addr; 584 + struct io_uring ring; 585 + int i, ret, sp[2]; 586 + size_t len; 587 + 588 + if (argc > 1) 589 + return T_EXIT_SKIP; 590 + 591 + /* create TCP IPv6 pair */ 592 + ret = create_socketpair_ip(&addr, &sp[0], &sp[1], true, true, false, true); 593 + if (ret) { 594 + fprintf(stderr, "sock prep failed %d\n", ret); 595 + return T_EXIT_FAIL; 596 + } 597 + 598 + len = 1U << 25; /* 32MB, should be enough to trigger a short send */ 599 + tx_buffer = aligned_alloc(4096, len); 600 + rx_buffer = aligned_alloc(4096, len); 601 + if (tx_buffer && rx_buffer) { 602 + buffers_iov[BUF_T_LARGE].iov_base = tx_buffer; 603 + buffers_iov[BUF_T_LARGE].iov_len = len; 604 + } else { 605 + printf("skip large buffer tests, can't alloc\n"); 606 + 607 + len = 8192; 608 + tx_buffer = aligned_alloc(4096, len); 609 + rx_buffer = aligned_alloc(4096, len); 610 + } 611 + if (!tx_buffer || !rx_buffer) { 612 + fprintf(stderr, "can't allocate buffers\n"); 613 + return T_EXIT_FAIL; 614 + } 615 + 616 + buffers_iov[BUF_T_NORMAL].iov_base = tx_buffer + 4096; 617 + buffers_iov[BUF_T_NORMAL].iov_len = 4096; 618 + buffers_iov[BUF_T_SMALL].iov_base = tx_buffer; 619 + buffers_iov[BUF_T_SMALL].iov_len = 137; 620 + buffers_iov[BUF_T_NONALIGNED].iov_base = tx_buffer + BUFFER_OFFSET; 621 + buffers_iov[BUF_T_NONALIGNED].iov_len = 8192 - BUFFER_OFFSET - 13; 622 + 623 + ret = io_uring_queue_init(32, &ring, 0); 624 + if (ret) { 625 + fprintf(stderr, "queue init failed: %d\n", ret); 626 + return T_EXIT_FAIL; 627 + } 628 + 629 + srand((unsigned)time(NULL)); 630 + for (i = 0; i < len; i++) 631 + tx_buffer[i] = i; 632 + memset(rx_buffer, 0, len); 633 + 634 + ret = test_basic_send(&ring, sp[0], sp[1]); 635 + if (ret == T_EXIT_SKIP) 636 + return ret; 637 + if (ret) { 638 + fprintf(stderr, "test_basic_send() failed\n"); 639 + return T_EXIT_FAIL; 640 + } 641 + 642 + has_sendmsg = io_check_zc_sendmsg(&ring); 643 + 644 + ret = test_send_faults(&ring, sp[0], sp[1]); 645 + if (ret) { 646 + fprintf(stderr, "test_send_faults() failed\n"); 647 + return T_EXIT_FAIL; 648 + } 649 + 650 + ret = test_invalid_zc(sp); 651 + if (ret) { 652 + fprintf(stderr, "test_invalid_zc() failed\n"); 653 + return T_EXIT_FAIL; 654 + } 655 + 656 + close(sp[0]); 657 + close(sp[1]); 658 + 659 + ret = test_async_addr(&ring); 660 + if (ret) { 661 + fprintf(stderr, "test_async_addr() failed\n"); 662 + return T_EXIT_FAIL; 663 + } 664 + 665 + ret = t_register_buffers(&ring, buffers_iov, ARRAY_SIZE(buffers_iov)); 666 + if (ret == T_SETUP_SKIP) { 667 + fprintf(stderr, "can't register bufs, skip\n"); 668 + goto out; 669 + } else if (ret != T_SETUP_OK) { 670 + fprintf(stderr, "buffer registration failed %i\n", ret); 671 + return T_EXIT_FAIL; 672 + } 673 + 674 + ret = test_inet_send(&ring); 675 + if (ret) { 676 + fprintf(stderr, "test_inet_send() failed\n"); 677 + return T_EXIT_FAIL; 678 + } 679 + out: 680 + io_uring_queue_exit(&ring); 681 + close(sp[0]); 682 + close(sp[1]); 683 + return T_EXIT_PASS; 684 + }
+47
vendor/liburing/test/send_recv.c
··· 257 257 return (intptr_t)retval; 258 258 } 259 259 260 + static int test_invalid(void) 261 + { 262 + struct io_uring ring; 263 + int ret, i; 264 + int fds[2]; 265 + struct io_uring_cqe *cqe; 266 + struct io_uring_sqe *sqe; 267 + 268 + ret = t_create_ring(8, &ring, 0); 269 + if (ret) 270 + return ret; 271 + 272 + ret = t_create_socket_pair(fds, true); 273 + if (ret) 274 + return ret; 275 + 276 + sqe = io_uring_get_sqe(&ring); 277 + io_uring_prep_sendmsg(sqe, fds[0], NULL, MSG_WAITALL); 278 + sqe->flags |= IOSQE_ASYNC; 279 + 280 + sqe = io_uring_get_sqe(&ring); 281 + io_uring_prep_recvmsg(sqe, fds[1], NULL, 0); 282 + sqe->flags |= IOSQE_ASYNC; 283 + 284 + ret = io_uring_submit_and_wait(&ring, 2); 285 + if (ret != 2) 286 + return ret; 287 + 288 + for (i = 0; i < 2; i++) { 289 + ret = io_uring_peek_cqe(&ring, &cqe); 290 + if (ret || cqe->res != -EFAULT) 291 + return -1; 292 + io_uring_cqe_seen(&ring, cqe); 293 + } 294 + 295 + io_uring_queue_exit(&ring); 296 + close(fds[0]); 297 + close(fds[1]); 298 + return 0; 299 + } 300 + 260 301 int main(int argc, char *argv[]) 261 302 { 262 303 int ret; 263 304 264 305 if (argc > 1) 265 306 return 0; 307 + 308 + ret = test_invalid(); 309 + if (ret) { 310 + fprintf(stderr, "test_invalid failed\n"); 311 + return ret; 312 + } 266 313 267 314 ret = test(0, 0); 268 315 if (ret) {
+3 -4
vendor/liburing/test/shutdown.c
··· 19 19 #include <arpa/inet.h> 20 20 21 21 #include "liburing.h" 22 + #include "helpers.h" 22 23 23 24 static void sig_pipe(int sig) 24 25 { ··· 29 30 int p_fd[2], ret; 30 31 int32_t recv_s0; 31 32 int32_t val = 1; 32 - struct sockaddr_in addr; 33 + struct sockaddr_in addr = { }; 33 34 34 35 if (argc > 1) 35 36 return 0; ··· 44 45 assert(ret != -1); 45 46 46 47 addr.sin_family = AF_INET; 47 - addr.sin_port = htons((rand() % 61440) + 4096); 48 48 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 49 49 50 - ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); 51 - assert(ret != -1); 50 + assert(!t_bind_ephemeral_port(recv_s0, &addr)); 52 51 ret = listen(recv_s0, 128); 53 52 assert(ret != -1); 54 53
+22 -8
vendor/liburing/test/sigfd-deadlock.c
··· 11 11 #include <poll.h> 12 12 #include <stdio.h> 13 13 #include "liburing.h" 14 + #include "helpers.h" 14 15 15 16 static int setup_signal(void) 16 17 { ··· 34 35 struct io_uring ring; 35 36 int ret; 36 37 37 - io_uring_queue_init(32, &ring, 0); 38 + ret = io_uring_queue_init(32, &ring, 0); 39 + if (ret) 40 + return T_EXIT_FAIL; 38 41 39 42 sqe = io_uring_get_sqe(&ring); 40 43 io_uring_prep_poll_add(sqe, sfd, POLLIN); 41 - io_uring_submit(&ring); 44 + ret = io_uring_submit(&ring); 45 + if (ret < 0) { 46 + ret = T_EXIT_FAIL; 47 + goto err_exit; 48 + } 42 49 43 50 kill(getpid(), SIGINT); 44 51 45 52 io_uring_wait_cqe(&ring, &cqe); 46 - if (cqe->res & POLLIN) { 47 - ret = 0; 53 + if (cqe->res == -EOPNOTSUPP) { 54 + fprintf(stderr, "signalfd poll not supported\n"); 55 + ret = T_EXIT_SKIP; 56 + } else if (cqe->res < 0) { 57 + fprintf(stderr, "poll failed: %d\n", cqe->res); 58 + ret = T_EXIT_FAIL; 59 + } else if (cqe->res & POLLIN) { 60 + ret = T_EXIT_PASS; 48 61 } else { 49 62 fprintf(stderr, "Unexpected poll mask %x\n", cqe->res); 50 - ret = 1; 63 + ret = T_EXIT_FAIL; 51 64 } 52 65 io_uring_cqe_seen(&ring, cqe); 66 + err_exit: 53 67 io_uring_queue_exit(&ring); 54 68 return ret; 55 69 } ··· 59 73 int sfd, ret; 60 74 61 75 if (argc > 1) 62 - return 0; 76 + return T_EXIT_PASS; 63 77 64 78 sfd = setup_signal(); 65 79 if (sfd < 0) 66 - return 1; 80 + return T_EXIT_FAIL; 67 81 68 82 ret = test_uring(sfd); 69 - if (ret) 83 + if (ret == T_EXIT_FAIL) 70 84 fprintf(stderr, "test_uring signalfd failed\n"); 71 85 72 86 close(sfd);
+171
vendor/liburing/test/single-issuer.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + #include <errno.h> 3 + #include <stdio.h> 4 + #include <unistd.h> 5 + #include <stdlib.h> 6 + #include <string.h> 7 + #include <fcntl.h> 8 + #include <error.h> 9 + #include <sys/types.h> 10 + #include <sys/wait.h> 11 + 12 + #include "liburing.h" 13 + #include "test.h" 14 + #include "helpers.h" 15 + 16 + static pid_t pid; 17 + 18 + static pid_t fork_t(void) 19 + { 20 + pid = fork(); 21 + if (pid == -1) { 22 + fprintf(stderr, "fork failed\n"); 23 + exit(T_EXIT_FAIL); 24 + } 25 + return pid; 26 + } 27 + 28 + static void wait_child_t(void) 29 + { 30 + int wstatus; 31 + 32 + if (waitpid(pid, &wstatus, 0) == (pid_t)-1) { 33 + perror("waitpid()"); 34 + exit(T_EXIT_FAIL); 35 + } 36 + if (!WIFEXITED(wstatus)) { 37 + fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus)); 38 + exit(T_EXIT_FAIL); 39 + } 40 + if (WEXITSTATUS(wstatus)) 41 + exit(T_EXIT_FAIL); 42 + } 43 + 44 + static int try_submit(struct io_uring *ring) 45 + { 46 + struct io_uring_cqe *cqe; 47 + struct io_uring_sqe *sqe; 48 + int ret; 49 + 50 + sqe = io_uring_get_sqe(ring); 51 + io_uring_prep_nop(sqe); 52 + sqe->user_data = 42; 53 + 54 + ret = io_uring_submit(ring); 55 + if (ret < 0) 56 + return ret; 57 + 58 + if (ret != 1) 59 + error(1, ret, "submit %i", ret); 60 + ret = io_uring_wait_cqe(ring, &cqe); 61 + if (ret) 62 + error(1, ret, "wait fail %i", ret); 63 + 64 + if (cqe->res || cqe->user_data != 42) 65 + error(1, ret, "invalid cqe"); 66 + 67 + io_uring_cqe_seen(ring, cqe); 68 + return 0; 69 + } 70 + 71 + int main(int argc, char *argv[]) 72 + { 73 + struct io_uring ring; 74 + int ret; 75 + 76 + if (argc > 1) 77 + return T_EXIT_SKIP; 78 + 79 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER); 80 + if (ret == -EINVAL) { 81 + fprintf(stderr, "SETUP_SINGLE_ISSUER is not supported, skip\n"); 82 + return T_EXIT_SKIP; 83 + } else if (ret) { 84 + fprintf(stderr, "io_uring_queue_init() failed %i\n", ret); 85 + return T_EXIT_FAIL; 86 + } 87 + 88 + /* test that the creator iw allowed to submit */ 89 + ret = try_submit(&ring); 90 + if (ret) { 91 + fprintf(stderr, "the creator can't submit %i\n", ret); 92 + return T_EXIT_FAIL; 93 + } 94 + 95 + /* test that a second submitter doesn't succeed */ 96 + if (!fork_t()) { 97 + ret = try_submit(&ring); 98 + if (ret != -EEXIST) 99 + fprintf(stderr, "1: not owner child could submit %i\n", ret); 100 + return ret != -EEXIST; 101 + } 102 + wait_child_t(); 103 + io_uring_queue_exit(&ring); 104 + 105 + /* test that the first submitter but not creator can submit */ 106 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER | 107 + IORING_SETUP_R_DISABLED); 108 + if (ret) 109 + error(1, ret, "ring init (2) %i", ret); 110 + 111 + if (!fork_t()) { 112 + io_uring_enable_rings(&ring); 113 + ret = try_submit(&ring); 114 + if (ret) 115 + fprintf(stderr, "2: not owner child could submit %i\n", ret); 116 + return !!ret; 117 + } 118 + wait_child_t(); 119 + io_uring_queue_exit(&ring); 120 + 121 + /* test that only the first enabler can submit */ 122 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER | 123 + IORING_SETUP_R_DISABLED); 124 + if (ret) 125 + error(1, ret, "ring init (3) %i", ret); 126 + 127 + io_uring_enable_rings(&ring); 128 + if (!fork_t()) { 129 + ret = try_submit(&ring); 130 + if (ret != -EEXIST) 131 + fprintf(stderr, "3: not owner child could submit %i\n", ret); 132 + return ret != -EEXIST; 133 + } 134 + wait_child_t(); 135 + io_uring_queue_exit(&ring); 136 + 137 + /* test that anyone can submit to a SQPOLL|SINGLE_ISSUER ring */ 138 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER|IORING_SETUP_SQPOLL); 139 + if (ret) 140 + error(1, ret, "ring init (4) %i", ret); 141 + 142 + ret = try_submit(&ring); 143 + if (ret) { 144 + fprintf(stderr, "SQPOLL submit failed (creator) %i\n", ret); 145 + return T_EXIT_FAIL; 146 + } 147 + 148 + if (!fork_t()) { 149 + ret = try_submit(&ring); 150 + if (ret) 151 + fprintf(stderr, "SQPOLL submit failed (child) %i\n", ret); 152 + return !!ret; 153 + } 154 + wait_child_t(); 155 + io_uring_queue_exit(&ring); 156 + 157 + /* test that IORING_ENTER_REGISTERED_RING doesn't break anything */ 158 + ret = io_uring_queue_init(8, &ring, IORING_SETUP_SINGLE_ISSUER); 159 + if (ret) 160 + error(1, ret, "ring init (5) %i", ret); 161 + 162 + if (!fork_t()) { 163 + ret = try_submit(&ring); 164 + if (ret != -EEXIST) 165 + fprintf(stderr, "4: not owner child could submit %i\n", ret); 166 + return ret != -EEXIST; 167 + } 168 + wait_child_t(); 169 + io_uring_queue_exit(&ring); 170 + return T_EXIT_PASS; 171 + }
+2 -12
vendor/liburing/test/socket-rw-eagain.c
··· 18 18 #include <arpa/inet.h> 19 19 20 20 #include "liburing.h" 21 + #include "helpers.h" 21 22 22 23 int main(int argc, char *argv[]) 23 24 { ··· 41 42 42 43 addr.sin_family = AF_INET; 43 44 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 44 - 45 - do { 46 - addr.sin_port = htons((rand() % 61440) + 4096); 47 - ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); 48 - if (!ret) 49 - break; 50 - if (errno != EADDRINUSE) { 51 - perror("bind"); 52 - exit(1); 53 - } 54 - } while (1); 55 - 45 + assert(!t_bind_ephemeral_port(recv_s0, &addr)); 56 46 ret = listen(recv_s0, 128); 57 47 assert(ret != -1); 58 48
+2 -11
vendor/liburing/test/socket-rw-offset.c
··· 20 20 #include <arpa/inet.h> 21 21 22 22 #include "liburing.h" 23 + #include "helpers.h" 23 24 24 25 int main(int argc, char *argv[]) 25 26 { ··· 43 44 44 45 addr.sin_family = AF_INET; 45 46 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 46 - 47 - do { 48 - addr.sin_port = htons((rand() % 61440) + 4096); 49 - ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); 50 - if (!ret) 51 - break; 52 - if (errno != EADDRINUSE) { 53 - perror("bind"); 54 - exit(1); 55 - } 56 - } while (1); 47 + assert(!t_bind_ephemeral_port(recv_s0, &addr)); 57 48 ret = listen(recv_s0, 128); 58 49 assert(ret != -1); 59 50
+2 -11
vendor/liburing/test/socket-rw.c
··· 20 20 #include <arpa/inet.h> 21 21 22 22 #include "liburing.h" 23 + #include "helpers.h" 23 24 24 25 int main(int argc, char *argv[]) 25 26 { ··· 43 44 44 45 addr.sin_family = AF_INET; 45 46 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 46 - 47 - do { 48 - addr.sin_port = htons((rand() % 61440) + 4096); 49 - ret = bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)); 50 - if (!ret) 51 - break; 52 - if (errno != EADDRINUSE) { 53 - perror("bind"); 54 - exit(1); 55 - } 56 - } while (1); 47 + assert(!t_bind_ephemeral_port(recv_s0, &addr)); 57 48 ret = listen(recv_s0, 128); 58 49 assert(ret != -1); 59 50
+6 -5
vendor/liburing/test/socket.c
··· 11 11 #include <sys/types.h> 12 12 #include <sys/socket.h> 13 13 #include <pthread.h> 14 + #include <assert.h> 14 15 15 16 #include "liburing.h" 16 17 #include "helpers.h" ··· 19 20 20 21 #define MAX_MSG 128 21 22 22 - #define PORT 10202 23 23 #define HOST "127.0.0.1" 24 24 25 25 static int no_socket; 26 + static __be32 g_port; 26 27 27 28 static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock, 28 29 int registerfiles) ··· 34 35 memset(&saddr, 0, sizeof(saddr)); 35 36 saddr.sin_family = AF_INET; 36 37 saddr.sin_addr.s_addr = htonl(INADDR_ANY); 37 - saddr.sin_port = htons(PORT); 38 38 39 39 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 40 40 if (sockfd < 0) { ··· 45 45 val = 1; 46 46 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 47 47 48 - ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)); 49 - if (ret < 0) { 48 + if (t_bind_ephemeral_port(sockfd, &saddr)) { 50 49 perror("bind"); 51 50 goto err; 52 51 } 52 + g_port = saddr.sin_port; 53 53 54 54 if (registerfiles) { 55 55 ret = io_uring_register_files(ring, &sockfd, 1); ··· 244 244 } 245 245 } 246 246 247 + assert(g_port != 0); 247 248 memset(&saddr, 0, sizeof(saddr)); 248 249 saddr.sin_family = AF_INET; 249 - saddr.sin_port = htons(PORT); 250 + saddr.sin_port = g_port; 250 251 inet_pton(AF_INET, HOST, &saddr.sin_addr); 251 252 252 253 sqe = io_uring_get_sqe(&ring);
+1 -1
vendor/liburing/test/statx.c
··· 40 40 { 41 41 struct io_uring_cqe *cqe; 42 42 struct io_uring_sqe *sqe; 43 - struct statx x1, x2; 43 + struct statx x1 = { }, x2 = { }; 44 44 int ret; 45 45 46 46 sqe = io_uring_get_sqe(ring);
+108
vendor/liburing/test/submit-and-wait.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Description: Test that io_uring_submit_and_wait_timeout() returns the 4 + * right value (submit count) and that it doesn't end up waiting twice. 5 + * 6 + */ 7 + #include <errno.h> 8 + #include <stdio.h> 9 + #include <unistd.h> 10 + #include <stdlib.h> 11 + #include <string.h> 12 + #include <fcntl.h> 13 + #include <sys/time.h> 14 + 15 + #include "liburing.h" 16 + #include "test.h" 17 + 18 + static unsigned long long mtime_since(const struct timeval *s, 19 + const struct timeval *e) 20 + { 21 + long long sec, usec; 22 + 23 + sec = e->tv_sec - s->tv_sec; 24 + usec = (e->tv_usec - s->tv_usec); 25 + if (sec > 0 && usec < 0) { 26 + sec--; 27 + usec += 1000000; 28 + } 29 + 30 + sec *= 1000; 31 + usec /= 1000; 32 + return sec + usec; 33 + } 34 + 35 + static unsigned long long mtime_since_now(struct timeval *tv) 36 + { 37 + struct timeval end; 38 + 39 + gettimeofday(&end, NULL); 40 + return mtime_since(tv, &end); 41 + } 42 + 43 + static int test(struct io_uring *ring) 44 + { 45 + struct io_uring_cqe *cqe; 46 + struct io_uring_sqe *sqe; 47 + struct __kernel_timespec ts; 48 + struct timeval tv; 49 + int ret, i; 50 + 51 + for (i = 0; i < 1; i++) { 52 + sqe = io_uring_get_sqe(ring); 53 + if (!sqe) { 54 + fprintf(stderr, "get sqe failed at %d\n", i); 55 + goto err; 56 + } 57 + io_uring_prep_nop(sqe); 58 + } 59 + 60 + ts.tv_sec = 1; 61 + ts.tv_nsec = 0; 62 + gettimeofday(&tv, NULL); 63 + ret = io_uring_submit_and_wait_timeout(ring, &cqe, 2, &ts, NULL); 64 + if (ret < 0) { 65 + fprintf(stderr, "submit_and_wait_timeout: %d\n", ret); 66 + goto err; 67 + } 68 + ret = mtime_since_now(&tv); 69 + /* allow some slack, should be around 1s */ 70 + if (ret > 1200) { 71 + fprintf(stderr, "wait took too long: %d\n", ret); 72 + goto err; 73 + } 74 + return 0; 75 + err: 76 + return 1; 77 + } 78 + 79 + static int test_ring(void) 80 + { 81 + struct io_uring ring; 82 + struct io_uring_params p = { }; 83 + int ret; 84 + 85 + p.flags = 0; 86 + ret = io_uring_queue_init_params(8, &ring, &p); 87 + if (ret) { 88 + fprintf(stderr, "ring setup failed: %d\n", ret); 89 + return 1; 90 + } 91 + 92 + ret = test(&ring); 93 + if (ret) { 94 + fprintf(stderr, "test failed\n"); 95 + goto err; 96 + } 97 + err: 98 + io_uring_queue_exit(&ring); 99 + return ret; 100 + } 101 + 102 + int main(int argc, char *argv[]) 103 + { 104 + if (argc > 1) 105 + return 0; 106 + 107 + return test_ring(); 108 + }
+235
vendor/liburing/test/sync-cancel.c
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * Description: test io_uring_register_sync_cancel() 4 + * 5 + */ 6 + #include <errno.h> 7 + #include <stdio.h> 8 + #include <unistd.h> 9 + #include <stdlib.h> 10 + #include <string.h> 11 + #include <fcntl.h> 12 + 13 + #include "liburing.h" 14 + #include "helpers.h" 15 + 16 + static int no_sync_cancel; 17 + 18 + static int test_sync_cancel_timeout(struct io_uring *ring, int async) 19 + { 20 + struct io_uring_sync_cancel_reg reg = { }; 21 + struct io_uring_sqe *sqe; 22 + struct io_uring_cqe *cqe; 23 + int ret, fds[2], to_prep; 24 + char buf[32]; 25 + 26 + if (pipe(fds) < 0) { 27 + perror("pipe"); 28 + return 1; 29 + } 30 + 31 + to_prep = 1; 32 + sqe = io_uring_get_sqe(ring); 33 + io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0); 34 + sqe->user_data = 0x89; 35 + if (async) 36 + sqe->flags |= IOSQE_ASYNC; 37 + 38 + ret = io_uring_submit(ring); 39 + if (ret != to_prep) { 40 + fprintf(stderr, "submit=%d\n", ret); 41 + return 1; 42 + } 43 + 44 + usleep(10000); 45 + 46 + reg.addr = 0x89; 47 + reg.timeout.tv_nsec = 1; 48 + ret = io_uring_register_sync_cancel(ring, &reg); 49 + if (async) { 50 + /* we expect -ETIME here, but can race and get 0 */ 51 + if (ret != -ETIME && ret != 0) { 52 + fprintf(stderr, "sync_cancel=%d\n", ret); 53 + return 1; 54 + } 55 + } else { 56 + if (ret < 0) { 57 + fprintf(stderr, "sync_cancel=%d\n", ret); 58 + return 1; 59 + } 60 + } 61 + 62 + /* 63 + * we could _almost_ use peek_cqe() here, but there is still 64 + * a small gap where io-wq is done with the request and on 65 + * its way to posting a completion, but hasn't done it just 66 + * yet. the request is canceled and won't be doing any IO 67 + * to buffers etc, but the cqe may not have quite arrived yet. 68 + */ 69 + ret = io_uring_wait_cqe(ring, &cqe); 70 + if (ret) { 71 + fprintf(stderr, "peek=%d\n", ret); 72 + return 1; 73 + } 74 + if (cqe->res >= 0) { 75 + fprintf(stderr, "cqe->res=%d\n", cqe->res); 76 + return 1; 77 + } 78 + io_uring_cqe_seen(ring, cqe); 79 + return 0; 80 + } 81 + 82 + static int test_sync_cancel(struct io_uring *ring, int async, int nr_all, 83 + int use_fd) 84 + { 85 + struct io_uring_sync_cancel_reg reg = { }; 86 + struct io_uring_sqe *sqe; 87 + struct io_uring_cqe *cqe; 88 + int ret, fds[2], to_prep, i; 89 + char buf[32]; 90 + 91 + if (pipe(fds) < 0) { 92 + perror("pipe"); 93 + return 1; 94 + } 95 + 96 + to_prep = 1; 97 + if (nr_all) 98 + to_prep = 4; 99 + for (i = 0; i < to_prep; i++) { 100 + sqe = io_uring_get_sqe(ring); 101 + io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0); 102 + sqe->user_data = 0x89; 103 + if (async) 104 + sqe->flags |= IOSQE_ASYNC; 105 + } 106 + 107 + ret = io_uring_submit(ring); 108 + if (ret != to_prep) { 109 + fprintf(stderr, "submit=%d\n", ret); 110 + return 1; 111 + } 112 + 113 + usleep(10000); 114 + 115 + if (!use_fd) 116 + reg.addr = 0x89; 117 + else 118 + reg.fd = fds[0]; 119 + reg.timeout.tv_sec = 200; 120 + if (nr_all) 121 + reg.flags |= IORING_ASYNC_CANCEL_ALL; 122 + if (use_fd) 123 + reg.flags |= IORING_ASYNC_CANCEL_FD; 124 + ret = io_uring_register_sync_cancel(ring, &reg); 125 + if (ret < 0) { 126 + if (ret == -EINVAL && !no_sync_cancel) { 127 + no_sync_cancel = 1; 128 + return 0; 129 + } 130 + fprintf(stderr, "sync_cancel=%d\n", ret); 131 + return 1; 132 + } 133 + 134 + for (i = 0; i < to_prep; i++) { 135 + /* 136 + * we could _almost_ use peek_cqe() here, but there is still 137 + * a small gap where io-wq is done with the request and on 138 + * its way to posting a completion, but hasn't done it just 139 + * yet. the request is canceled and won't be doing any IO 140 + * to buffers etc, but the cqe may not have quite arrived yet. 141 + */ 142 + ret = io_uring_wait_cqe(ring, &cqe); 143 + if (ret) { 144 + fprintf(stderr, "peek=%d\n", ret); 145 + return 1; 146 + } 147 + if (cqe->res >= 0) { 148 + fprintf(stderr, "cqe->res=%d\n", cqe->res); 149 + return 1; 150 + } 151 + io_uring_cqe_seen(ring, cqe); 152 + } 153 + 154 + return 0; 155 + } 156 + 157 + int main(int argc, char *argv[]) 158 + { 159 + struct io_uring ring; 160 + int ret; 161 + 162 + if (argc > 1) 163 + return T_EXIT_SKIP; 164 + 165 + ret = t_create_ring(7, &ring, 0); 166 + if (ret == T_SETUP_SKIP) 167 + return T_EXIT_SKIP; 168 + else if (ret != T_SETUP_OK) 169 + return ret; 170 + 171 + ret = test_sync_cancel(&ring, 0, 0, 0); 172 + if (ret) { 173 + fprintf(stderr, "test_sync_cancel 0 0 0 failed\n"); 174 + return T_EXIT_FAIL; 175 + } 176 + if (no_sync_cancel) 177 + return T_EXIT_SKIP; 178 + 179 + ret = test_sync_cancel(&ring, 1, 0, 0); 180 + if (ret) { 181 + fprintf(stderr, "test_sync_cancel 1 0 0 failed\n"); 182 + return T_EXIT_FAIL; 183 + } 184 + 185 + ret = test_sync_cancel(&ring, 0, 1, 0); 186 + if (ret) { 187 + fprintf(stderr, "test_sync_cancel 0 1 0 failed\n"); 188 + return T_EXIT_FAIL; 189 + } 190 + 191 + ret = test_sync_cancel(&ring, 1, 1, 0); 192 + if (ret) { 193 + fprintf(stderr, "test_sync_cancel 1 1 0 failed\n"); 194 + return T_EXIT_FAIL; 195 + } 196 + 197 + ret = test_sync_cancel(&ring, 0, 0, 1); 198 + if (ret) { 199 + fprintf(stderr, "test_sync_cancel 0 0 1 failed\n"); 200 + return T_EXIT_FAIL; 201 + } 202 + 203 + ret = test_sync_cancel(&ring, 1, 0, 1); 204 + if (ret) { 205 + fprintf(stderr, "test_sync_cancel 1 0 1 failed\n"); 206 + return T_EXIT_FAIL; 207 + } 208 + 209 + ret = test_sync_cancel(&ring, 0, 1, 1); 210 + if (ret) { 211 + fprintf(stderr, "test_sync_cancel 0 1 1 failed\n"); 212 + return T_EXIT_FAIL; 213 + } 214 + 215 + ret = test_sync_cancel(&ring, 1, 1, 1); 216 + if (ret) { 217 + fprintf(stderr, "test_sync_cancel 1 1 1 failed\n"); 218 + return T_EXIT_FAIL; 219 + } 220 + 221 + ret = test_sync_cancel_timeout(&ring, 0); 222 + if (ret) { 223 + fprintf(stderr, "test_sync_cancel_timeout 0\n"); 224 + return T_EXIT_FAIL; 225 + } 226 + 227 + /* must be last, leaves request */ 228 + ret = test_sync_cancel_timeout(&ring, 1); 229 + if (ret) { 230 + fprintf(stderr, "test_sync_cancel_timeout 1\n"); 231 + return T_EXIT_FAIL; 232 + } 233 + 234 + return T_EXIT_PASS; 235 + }
+11 -11
vendor/liburing/test/timeout-overflow.c
··· 10 10 #include <sys/time.h> 11 11 12 12 #include "liburing.h" 13 + #include "helpers.h" 13 14 14 15 #define TIMEOUT_MSEC 200 15 16 static int not_supported; ··· 33 34 ret = io_uring_queue_init_params(1, &ring, &p); 34 35 if (ret) { 35 36 fprintf(stderr, "ring setup failed: %d\n", ret); 36 - return 1; 37 + return T_EXIT_FAIL; 37 38 } 38 39 39 40 /* not really a match, but same kernel added batched completions */ 40 41 if (p.features & IORING_FEAT_POLL_32BITS) { 41 - fprintf(stdout, "Skipping\n"); 42 42 not_supported = 1; 43 - return 0; 43 + return T_EXIT_SKIP; 44 44 } 45 45 46 46 sqe = io_uring_get_sqe(&ring); ··· 67 67 68 68 io_uring_cqe_seen(&ring, cqe); 69 69 io_uring_queue_exit(&ring); 70 - return 0; 70 + return T_EXIT_PASS; 71 71 err: 72 72 io_uring_queue_exit(&ring); 73 - return 1; 73 + return T_EXIT_FAIL; 74 74 } 75 75 76 76 /* ··· 183 183 int ret; 184 184 185 185 if (argc > 1) 186 - return 0; 186 + return T_EXIT_SKIP; 187 187 188 188 ret = check_timeout_support(); 189 - if (ret) { 189 + if (ret == T_EXIT_FAIL) { 190 190 fprintf(stderr, "check_timeout_support failed: %d\n", ret); 191 - return 1; 191 + return T_EXIT_FAIL; 192 192 } 193 193 194 194 if (not_supported) 195 - return 0; 195 + return T_EXIT_SKIP; 196 196 197 197 ret = test_timeout_overflow(); 198 198 if (ret) { 199 199 fprintf(stderr, "test_timeout_overflow failed\n"); 200 - return 1; 200 + return T_EXIT_FAIL; 201 201 } 202 202 203 - return 0; 203 + return T_EXIT_PASS; 204 204 }
+4 -4
vendor/liburing/test/timeout.c
··· 156 156 157 157 /* 158 158 * NOP commands have user_data as 1. Check that we get the 159 - * at least 'nr' NOPs first, then the successfully removed timout. 159 + * at least 'nr' NOPs first, then the successfully removed timeout. 160 160 */ 161 161 if (io_uring_cqe_get_data(cqe) == NULL) { 162 162 if (i < nr) { ··· 588 588 } 589 589 590 590 if (cqe->user_data != user_data) { 591 - fprintf(stderr, "%s: unexpected timeout req %d sequece\n", 591 + fprintf(stderr, "%s: unexpected timeout req %d sequence\n", 592 592 __FUNCTION__, i+1); 593 593 goto err; 594 594 } ··· 678 678 case 1: 679 679 /* Should be timeout req_2 */ 680 680 if (cqe->user_data != 2) { 681 - fprintf(stderr, "%s: unexpected timeout req %d sequece\n", 681 + fprintf(stderr, "%s: unexpected timeout req %d sequence\n", 682 682 __FUNCTION__, i+1); 683 683 goto err; 684 684 } ··· 691 691 case 2: 692 692 /* Should be timeout req_1 */ 693 693 if (cqe->user_data != 1) { 694 - fprintf(stderr, "%s: unexpected timeout req %d sequece\n", 694 + fprintf(stderr, "%s: unexpected timeout req %d sequence\n", 695 695 __FUNCTION__, i+1); 696 696 goto err; 697 697 }
+2 -2
vendor/liburing/test/xattr.c
··· 210 210 211 211 /* Test reading attributes. */ 212 212 value_len = io_uring_fgetxattr(&ring, fd, KEY1, value, XATTR_SIZE); 213 - if (value_len != strlen(value) || strncmp(value, VALUE1, value_len)) { 213 + if (value_len != strlen(VALUE1) || strncmp(value, VALUE1, value_len)) { 214 214 fprintf(stderr, "Error: fgetxattr expected value: %s, returned value: %s\n", VALUE1, value); 215 215 rc = -1; 216 216 goto Exit; 217 217 } 218 218 219 219 value_len = io_uring_fgetxattr(&ring, fd, KEY2, value, XATTR_SIZE); 220 - if (value_len != strlen(value)|| strncmp(value, VALUE2, value_len)) { 220 + if (value_len != strlen(VALUE2) || strncmp(value, VALUE2, value_len)) { 221 221 fprintf(stderr, "Error: fgetxattr expected value: %s, returned value: %s\n", VALUE2, value); 222 222 rc = -1; 223 223 goto Exit;