uringmachine 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/dependabot.yml +12 -0
- data/.github/workflows/test.yml +35 -0
- data/.gitignore +59 -0
- data/.gitmodules +3 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +11 -0
- data/Rakefile +39 -0
- data/TODO.md +0 -0
- data/examples/echo_server.rb +52 -0
- data/examples/event_loop.rb +69 -0
- data/examples/fibers.rb +105 -0
- data/examples/http_server.rb +56 -0
- data/examples/http_server_multishot.rb +57 -0
- data/examples/http_server_simpler.rb +34 -0
- data/ext/um/extconf.rb +71 -0
- data/ext/um/iou.h +101 -0
- data/ext/um/op_ctx.c +138 -0
- data/ext/um/ring.c +755 -0
- data/ext/um/um.c +267 -0
- data/ext/um/um.h +97 -0
- data/ext/um/um_class.c +175 -0
- data/ext/um/um_ext.c +11 -0
- data/ext/um/um_op.c +87 -0
- data/ext/um/um_utils.c +23 -0
- data/lib/uringmachine/version.rb +3 -0
- data/lib/uringmachine.rb +8 -0
- data/test/helper.rb +70 -0
- data/test/test_iou.rb +876 -0
- data/test/test_um.rb +168 -0
- data/uringmachine.gemspec +27 -0
- data/vendor/liburing/.github/actions/codespell/stopwords +7 -0
- data/vendor/liburing/.github/pull_request_template.md +86 -0
- data/vendor/liburing/.github/workflows/build.yml +137 -0
- data/vendor/liburing/.github/workflows/codespell.yml +25 -0
- data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
- data/vendor/liburing/.gitignore +41 -0
- data/vendor/liburing/CHANGELOG +111 -0
- data/vendor/liburing/CITATION.cff +11 -0
- data/vendor/liburing/COPYING +502 -0
- data/vendor/liburing/COPYING.GPL +339 -0
- data/vendor/liburing/LICENSE +20 -0
- data/vendor/liburing/Makefile +96 -0
- data/vendor/liburing/Makefile.common +7 -0
- data/vendor/liburing/Makefile.quiet +11 -0
- data/vendor/liburing/README +106 -0
- data/vendor/liburing/SECURITY.md +6 -0
- data/vendor/liburing/configure +624 -0
- data/vendor/liburing/debian/README.Debian +7 -0
- data/vendor/liburing/debian/changelog +38 -0
- data/vendor/liburing/debian/control +39 -0
- data/vendor/liburing/debian/copyright +49 -0
- data/vendor/liburing/debian/liburing-dev.install +4 -0
- data/vendor/liburing/debian/liburing-dev.manpages +5 -0
- data/vendor/liburing/debian/liburing2.install +1 -0
- data/vendor/liburing/debian/liburing2.symbols +56 -0
- data/vendor/liburing/debian/patches/series +1 -0
- data/vendor/liburing/debian/rules +29 -0
- data/vendor/liburing/debian/source/format +1 -0
- data/vendor/liburing/debian/source/local-options +2 -0
- data/vendor/liburing/debian/source/options +1 -0
- data/vendor/liburing/debian/watch +3 -0
- data/vendor/liburing/examples/Makefile +53 -0
- data/vendor/liburing/examples/helpers.c +62 -0
- data/vendor/liburing/examples/helpers.h +7 -0
- data/vendor/liburing/examples/io_uring-close-test.c +123 -0
- data/vendor/liburing/examples/io_uring-cp.c +282 -0
- data/vendor/liburing/examples/io_uring-test.c +112 -0
- data/vendor/liburing/examples/io_uring-udp.c +403 -0
- data/vendor/liburing/examples/link-cp.c +193 -0
- data/vendor/liburing/examples/napi-busy-poll-client.c +509 -0
- data/vendor/liburing/examples/napi-busy-poll-server.c +450 -0
- data/vendor/liburing/examples/poll-bench.c +101 -0
- data/vendor/liburing/examples/proxy.c +2461 -0
- data/vendor/liburing/examples/proxy.h +102 -0
- data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
- data/vendor/liburing/examples/send-zerocopy.c +658 -0
- data/vendor/liburing/examples/ucontext-cp.c +258 -0
- data/vendor/liburing/liburing-ffi.pc.in +12 -0
- data/vendor/liburing/liburing.pc.in +12 -0
- data/vendor/liburing/liburing.spec +66 -0
- data/vendor/liburing/make-debs.sh +55 -0
- data/vendor/liburing/src/Makefile +129 -0
- data/vendor/liburing/src/arch/aarch64/lib.h +47 -0
- data/vendor/liburing/src/arch/aarch64/syscall.h +91 -0
- data/vendor/liburing/src/arch/generic/lib.h +17 -0
- data/vendor/liburing/src/arch/generic/syscall.h +100 -0
- data/vendor/liburing/src/arch/riscv64/lib.h +48 -0
- data/vendor/liburing/src/arch/riscv64/syscall.h +100 -0
- data/vendor/liburing/src/arch/syscall-defs.h +94 -0
- data/vendor/liburing/src/arch/x86/lib.h +11 -0
- data/vendor/liburing/src/arch/x86/syscall.h +296 -0
- data/vendor/liburing/src/ffi.c +15 -0
- data/vendor/liburing/src/include/liburing/barrier.h +81 -0
- data/vendor/liburing/src/include/liburing/io_uring.h +818 -0
- data/vendor/liburing/src/include/liburing.h +1602 -0
- data/vendor/liburing/src/int_flags.h +11 -0
- data/vendor/liburing/src/lib.h +52 -0
- data/vendor/liburing/src/liburing-ffi.map +211 -0
- data/vendor/liburing/src/liburing.map +104 -0
- data/vendor/liburing/src/nolibc.c +55 -0
- data/vendor/liburing/src/queue.c +468 -0
- data/vendor/liburing/src/register.c +374 -0
- data/vendor/liburing/src/setup.c +689 -0
- data/vendor/liburing/src/setup.h +9 -0
- data/vendor/liburing/src/syscall.c +29 -0
- data/vendor/liburing/src/syscall.h +53 -0
- data/vendor/liburing/src/version.c +21 -0
- data/vendor/liburing/test/232c93d07b74.c +305 -0
- data/vendor/liburing/test/35fa71a030ca.c +329 -0
- data/vendor/liburing/test/500f9fbadef8.c +91 -0
- data/vendor/liburing/test/7ad0e4b2f83c.c +94 -0
- data/vendor/liburing/test/8a9973408177.c +107 -0
- data/vendor/liburing/test/917257daa0fe.c +54 -0
- data/vendor/liburing/test/Makefile +297 -0
- data/vendor/liburing/test/a0908ae19763.c +59 -0
- data/vendor/liburing/test/a4c0b3decb33.c +181 -0
- data/vendor/liburing/test/accept-link.c +255 -0
- data/vendor/liburing/test/accept-non-empty.c +256 -0
- data/vendor/liburing/test/accept-reuse.c +163 -0
- data/vendor/liburing/test/accept-test.c +83 -0
- data/vendor/liburing/test/accept.c +919 -0
- data/vendor/liburing/test/across-fork.c +284 -0
- data/vendor/liburing/test/b19062a56726.c +54 -0
- data/vendor/liburing/test/b5837bd5311d.c +78 -0
- data/vendor/liburing/test/bind-listen.c +408 -0
- data/vendor/liburing/test/buf-ring-nommap.c +123 -0
- data/vendor/liburing/test/buf-ring-put.c +83 -0
- data/vendor/liburing/test/buf-ring.c +473 -0
- data/vendor/liburing/test/ce593a6c480a.c +139 -0
- data/vendor/liburing/test/close-opath.c +123 -0
- data/vendor/liburing/test/config +14 -0
- data/vendor/liburing/test/connect-rep.c +204 -0
- data/vendor/liburing/test/connect.c +442 -0
- data/vendor/liburing/test/coredump.c +60 -0
- data/vendor/liburing/test/cq-full.c +97 -0
- data/vendor/liburing/test/cq-overflow.c +530 -0
- data/vendor/liburing/test/cq-peek-batch.c +103 -0
- data/vendor/liburing/test/cq-ready.c +95 -0
- data/vendor/liburing/test/cq-size.c +65 -0
- data/vendor/liburing/test/d4ae271dfaae.c +96 -0
- data/vendor/liburing/test/d77a67ed5f27.c +65 -0
- data/vendor/liburing/test/defer-taskrun.c +391 -0
- data/vendor/liburing/test/defer-tw-timeout.c +173 -0
- data/vendor/liburing/test/defer.c +319 -0
- data/vendor/liburing/test/double-poll-crash.c +195 -0
- data/vendor/liburing/test/drop-submit.c +94 -0
- data/vendor/liburing/test/eeed8b54e0df.c +120 -0
- data/vendor/liburing/test/empty-eownerdead.c +45 -0
- data/vendor/liburing/test/eploop.c +74 -0
- data/vendor/liburing/test/eventfd-disable.c +179 -0
- data/vendor/liburing/test/eventfd-reg.c +77 -0
- data/vendor/liburing/test/eventfd-ring.c +98 -0
- data/vendor/liburing/test/eventfd.c +113 -0
- data/vendor/liburing/test/evloop.c +73 -0
- data/vendor/liburing/test/exec-target.c +6 -0
- data/vendor/liburing/test/exit-no-cleanup.c +117 -0
- data/vendor/liburing/test/fadvise.c +202 -0
- data/vendor/liburing/test/fallocate.c +265 -0
- data/vendor/liburing/test/fc2a85cb02ef.c +132 -0
- data/vendor/liburing/test/fd-install.c +500 -0
- data/vendor/liburing/test/fd-pass.c +237 -0
- data/vendor/liburing/test/fdinfo.c +419 -0
- data/vendor/liburing/test/file-register.c +1189 -0
- data/vendor/liburing/test/file-update.c +231 -0
- data/vendor/liburing/test/file-verify.c +654 -0
- data/vendor/liburing/test/files-exit-hang-poll.c +114 -0
- data/vendor/liburing/test/files-exit-hang-timeout.c +137 -0
- data/vendor/liburing/test/fixed-buf-iter.c +115 -0
- data/vendor/liburing/test/fixed-buf-merge.c +101 -0
- data/vendor/liburing/test/fixed-hugepage.c +411 -0
- data/vendor/liburing/test/fixed-link.c +90 -0
- data/vendor/liburing/test/fixed-reuse.c +160 -0
- data/vendor/liburing/test/fpos.c +255 -0
- data/vendor/liburing/test/fsnotify.c +118 -0
- data/vendor/liburing/test/fsync.c +224 -0
- data/vendor/liburing/test/futex.c +571 -0
- data/vendor/liburing/test/hardlink.c +170 -0
- data/vendor/liburing/test/helpers.c +318 -0
- data/vendor/liburing/test/helpers.h +108 -0
- data/vendor/liburing/test/ignore-single-mmap.c +48 -0
- data/vendor/liburing/test/init-mem.c +164 -0
- data/vendor/liburing/test/io-cancel.c +561 -0
- data/vendor/liburing/test/io_uring_enter.c +264 -0
- data/vendor/liburing/test/io_uring_passthrough.c +482 -0
- data/vendor/liburing/test/io_uring_register.c +503 -0
- data/vendor/liburing/test/io_uring_setup.c +110 -0
- data/vendor/liburing/test/iopoll-leak.c +85 -0
- data/vendor/liburing/test/iopoll-overflow.c +118 -0
- data/vendor/liburing/test/iopoll.c +465 -0
- data/vendor/liburing/test/lfs-openat-write.c +119 -0
- data/vendor/liburing/test/lfs-openat.c +273 -0
- data/vendor/liburing/test/link-timeout.c +1108 -0
- data/vendor/liburing/test/link.c +497 -0
- data/vendor/liburing/test/link_drain.c +255 -0
- data/vendor/liburing/test/madvise.c +195 -0
- data/vendor/liburing/test/min-timeout-wait.c +354 -0
- data/vendor/liburing/test/min-timeout.c +233 -0
- data/vendor/liburing/test/mkdir.c +112 -0
- data/vendor/liburing/test/msg-ring-fd.c +331 -0
- data/vendor/liburing/test/msg-ring-flags.c +212 -0
- data/vendor/liburing/test/msg-ring-overflow.c +159 -0
- data/vendor/liburing/test/msg-ring.c +467 -0
- data/vendor/liburing/test/multicqes_drain.c +429 -0
- data/vendor/liburing/test/napi-test.c +215 -0
- data/vendor/liburing/test/napi-test.sh +48 -0
- data/vendor/liburing/test/no-mmap-inval.c +42 -0
- data/vendor/liburing/test/nolibc.c +62 -0
- data/vendor/liburing/test/nop-all-sizes.c +99 -0
- data/vendor/liburing/test/nop.c +177 -0
- data/vendor/liburing/test/nvme.h +169 -0
- data/vendor/liburing/test/ooo-file-unreg.c +82 -0
- data/vendor/liburing/test/open-close.c +261 -0
- data/vendor/liburing/test/open-direct-link.c +188 -0
- data/vendor/liburing/test/open-direct-pick.c +180 -0
- data/vendor/liburing/test/openat2.c +312 -0
- data/vendor/liburing/test/personality.c +204 -0
- data/vendor/liburing/test/pipe-bug.c +95 -0
- data/vendor/liburing/test/pipe-eof.c +83 -0
- data/vendor/liburing/test/pipe-reuse.c +105 -0
- data/vendor/liburing/test/poll-cancel-all.c +496 -0
- data/vendor/liburing/test/poll-cancel-ton.c +135 -0
- data/vendor/liburing/test/poll-cancel.c +228 -0
- data/vendor/liburing/test/poll-link.c +221 -0
- data/vendor/liburing/test/poll-many.c +230 -0
- data/vendor/liburing/test/poll-mshot-overflow.c +265 -0
- data/vendor/liburing/test/poll-mshot-update.c +323 -0
- data/vendor/liburing/test/poll-race-mshot.c +276 -0
- data/vendor/liburing/test/poll-race.c +105 -0
- data/vendor/liburing/test/poll-ring.c +48 -0
- data/vendor/liburing/test/poll-v-poll.c +353 -0
- data/vendor/liburing/test/poll.c +327 -0
- data/vendor/liburing/test/probe.c +135 -0
- data/vendor/liburing/test/read-before-exit.c +129 -0
- data/vendor/liburing/test/read-mshot-empty.c +153 -0
- data/vendor/liburing/test/read-mshot.c +404 -0
- data/vendor/liburing/test/read-write.c +1013 -0
- data/vendor/liburing/test/recv-msgall-stream.c +398 -0
- data/vendor/liburing/test/recv-msgall.c +263 -0
- data/vendor/liburing/test/recv-multishot.c +602 -0
- data/vendor/liburing/test/recvsend_bundle.c +691 -0
- data/vendor/liburing/test/reg-fd-only.c +131 -0
- data/vendor/liburing/test/reg-hint.c +56 -0
- data/vendor/liburing/test/reg-reg-ring.c +90 -0
- data/vendor/liburing/test/regbuf-merge.c +91 -0
- data/vendor/liburing/test/register-restrictions.c +633 -0
- data/vendor/liburing/test/rename.c +132 -0
- data/vendor/liburing/test/ring-leak.c +283 -0
- data/vendor/liburing/test/ring-leak2.c +249 -0
- data/vendor/liburing/test/ringbuf-read.c +196 -0
- data/vendor/liburing/test/ringbuf-status.c +242 -0
- data/vendor/liburing/test/rsrc_tags.c +461 -0
- data/vendor/liburing/test/runtests-loop.sh +16 -0
- data/vendor/liburing/test/runtests-quiet.sh +11 -0
- data/vendor/liburing/test/runtests.sh +168 -0
- data/vendor/liburing/test/rw_merge_test.c +98 -0
- data/vendor/liburing/test/self.c +91 -0
- data/vendor/liburing/test/send-zerocopy.c +971 -0
- data/vendor/liburing/test/send_recv.c +412 -0
- data/vendor/liburing/test/send_recvmsg.c +444 -0
- data/vendor/liburing/test/shared-wq.c +84 -0
- data/vendor/liburing/test/short-read.c +75 -0
- data/vendor/liburing/test/shutdown.c +165 -0
- data/vendor/liburing/test/sigfd-deadlock.c +88 -0
- data/vendor/liburing/test/single-issuer.c +169 -0
- data/vendor/liburing/test/skip-cqe.c +428 -0
- data/vendor/liburing/test/socket-getsetsock-cmd.c +346 -0
- data/vendor/liburing/test/socket-io-cmd.c +237 -0
- data/vendor/liburing/test/socket-rw-eagain.c +149 -0
- data/vendor/liburing/test/socket-rw-offset.c +149 -0
- data/vendor/liburing/test/socket-rw.c +137 -0
- data/vendor/liburing/test/socket.c +408 -0
- data/vendor/liburing/test/splice.c +512 -0
- data/vendor/liburing/test/sq-full-cpp.cc +45 -0
- data/vendor/liburing/test/sq-full.c +45 -0
- data/vendor/liburing/test/sq-poll-dup.c +211 -0
- data/vendor/liburing/test/sq-poll-kthread.c +169 -0
- data/vendor/liburing/test/sq-poll-share.c +138 -0
- data/vendor/liburing/test/sq-space_left.c +159 -0
- data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
- data/vendor/liburing/test/sqpoll-exec.c +132 -0
- data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
- data/vendor/liburing/test/sqpoll-sleep.c +69 -0
- data/vendor/liburing/test/statx.c +172 -0
- data/vendor/liburing/test/stdout.c +232 -0
- data/vendor/liburing/test/submit-and-wait.c +108 -0
- data/vendor/liburing/test/submit-link-fail.c +156 -0
- data/vendor/liburing/test/submit-reuse.c +237 -0
- data/vendor/liburing/test/symlink.c +117 -0
- data/vendor/liburing/test/sync-cancel.c +235 -0
- data/vendor/liburing/test/teardowns.c +58 -0
- data/vendor/liburing/test/test.h +36 -0
- data/vendor/liburing/test/thread-exit.c +143 -0
- data/vendor/liburing/test/timeout-new.c +256 -0
- data/vendor/liburing/test/timeout.c +1798 -0
- data/vendor/liburing/test/truncate.c +186 -0
- data/vendor/liburing/test/tty-write-dpoll.c +60 -0
- data/vendor/liburing/test/unlink.c +112 -0
- data/vendor/liburing/test/version.c +25 -0
- data/vendor/liburing/test/wait-timeout.c +287 -0
- data/vendor/liburing/test/waitid.c +373 -0
- data/vendor/liburing/test/wakeup-hang.c +162 -0
- data/vendor/liburing/test/wq-aff.c +146 -0
- data/vendor/liburing/test/xattr.c +442 -0
- metadata +412 -0
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
/* SPDX-License-Identifier: MIT */
|
|
2
|
+
/*
|
|
3
|
+
* Description: exercise futex wait/wake/waitv
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <unistd.h>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
#include <pthread.h>
|
|
10
|
+
#include <errno.h>
|
|
11
|
+
#include <linux/futex.h>
|
|
12
|
+
|
|
13
|
+
#include "liburing.h"
|
|
14
|
+
#include "helpers.h"
|
|
15
|
+
|
|
16
|
+
#define LOOPS 500
|
|
17
|
+
#define NFUTEX 8
|
|
18
|
+
|
|
19
|
+
#ifndef FUTEX2_SIZE_U8
|
|
20
|
+
#define FUTEX2_SIZE_U8 0x00
|
|
21
|
+
#define FUTEX2_SIZE_U16 0x01
|
|
22
|
+
#define FUTEX2_SIZE_U32 0x02
|
|
23
|
+
#define FUTEX2_SIZE_U64 0x03
|
|
24
|
+
#define FUTEX2_NUMA 0x04
|
|
25
|
+
/* 0x08 */
|
|
26
|
+
/* 0x10 */
|
|
27
|
+
/* 0x20 */
|
|
28
|
+
/* 0x40 */
|
|
29
|
+
#define FUTEX2_PRIVATE FUTEX_PRIVATE_FLAG
|
|
30
|
+
|
|
31
|
+
#define FUTEX2_SIZE_MASK 0x03
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
static int no_futex;
|
|
35
|
+
|
|
36
|
+
static void *fwake(void *data)
|
|
37
|
+
{
|
|
38
|
+
unsigned int *futex = data;
|
|
39
|
+
struct io_uring_sqe *sqe;
|
|
40
|
+
struct io_uring_cqe *cqe;
|
|
41
|
+
struct io_uring ring;
|
|
42
|
+
int ret;
|
|
43
|
+
|
|
44
|
+
ret = io_uring_queue_init(1, &ring, 0);
|
|
45
|
+
if (ret) {
|
|
46
|
+
fprintf(stderr, "queue init: %d\n", ret);
|
|
47
|
+
return NULL;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
*futex = 1;
|
|
51
|
+
sqe = io_uring_get_sqe(&ring);
|
|
52
|
+
io_uring_prep_futex_wake(sqe, futex, 1, FUTEX_BITSET_MATCH_ANY,
|
|
53
|
+
FUTEX2_SIZE_U32, 0);
|
|
54
|
+
sqe->user_data = 3;
|
|
55
|
+
|
|
56
|
+
io_uring_submit(&ring);
|
|
57
|
+
|
|
58
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
59
|
+
if (ret) {
|
|
60
|
+
fprintf(stderr, "wait: %d\n", ret);
|
|
61
|
+
return NULL;
|
|
62
|
+
}
|
|
63
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
64
|
+
io_uring_queue_exit(&ring);
|
|
65
|
+
return NULL;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static int __test(struct io_uring *ring, int vectored, int async,
|
|
69
|
+
int async_cancel)
|
|
70
|
+
{
|
|
71
|
+
struct io_uring_sqe *sqe;
|
|
72
|
+
struct io_uring_cqe *cqe;
|
|
73
|
+
struct futex_waitv fw[NFUTEX];
|
|
74
|
+
unsigned int *futex;
|
|
75
|
+
pthread_t threads[NFUTEX];
|
|
76
|
+
void *tret;
|
|
77
|
+
int ret, i, nfutex;
|
|
78
|
+
|
|
79
|
+
nfutex = NFUTEX;
|
|
80
|
+
if (!vectored)
|
|
81
|
+
nfutex = 1;
|
|
82
|
+
|
|
83
|
+
futex = calloc(nfutex, sizeof(*futex));
|
|
84
|
+
for (i = 0; i < nfutex; i++) {
|
|
85
|
+
fw[i].val = 0;
|
|
86
|
+
fw[i].uaddr = (unsigned long) &futex[i];
|
|
87
|
+
fw[i].flags = FUTEX2_SIZE_U32;
|
|
88
|
+
fw[i].__reserved = 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
sqe = io_uring_get_sqe(ring);
|
|
92
|
+
if (vectored)
|
|
93
|
+
io_uring_prep_futex_waitv(sqe, fw, nfutex, 0);
|
|
94
|
+
else
|
|
95
|
+
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
|
|
96
|
+
FUTEX2_SIZE_U32, 0);
|
|
97
|
+
if (async)
|
|
98
|
+
sqe->flags |= IOSQE_ASYNC;
|
|
99
|
+
sqe->user_data = 1;
|
|
100
|
+
|
|
101
|
+
io_uring_submit(ring);
|
|
102
|
+
|
|
103
|
+
for (i = 0; i < nfutex; i++)
|
|
104
|
+
pthread_create(&threads[i], NULL, fwake, &futex[i]);
|
|
105
|
+
|
|
106
|
+
sqe = io_uring_get_sqe(ring);
|
|
107
|
+
io_uring_prep_cancel64(sqe, 1, 0);
|
|
108
|
+
if (async_cancel)
|
|
109
|
+
sqe->flags |= IOSQE_ASYNC;
|
|
110
|
+
sqe->user_data = 2;
|
|
111
|
+
|
|
112
|
+
io_uring_submit(ring);
|
|
113
|
+
|
|
114
|
+
for (i = 0; i < 2; i++) {
|
|
115
|
+
ret = io_uring_wait_cqe(ring, &cqe);
|
|
116
|
+
if (ret) {
|
|
117
|
+
fprintf(stderr, "parent wait %d\n", ret);
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (cqe->res == -EINVAL || cqe->res == -EOPNOTSUPP) {
|
|
122
|
+
no_futex = 1;
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
io_uring_cqe_seen(ring, cqe);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
ret = io_uring_peek_cqe(ring, &cqe);
|
|
129
|
+
if (!ret) {
|
|
130
|
+
fprintf(stderr, "peek found cqe!\n");
|
|
131
|
+
return 1;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
for (i = 0; i < nfutex; i++)
|
|
135
|
+
pthread_join(threads[i], &tret);
|
|
136
|
+
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static int test(int flags, int vectored)
|
|
141
|
+
{
|
|
142
|
+
struct io_uring ring;
|
|
143
|
+
int ret, i;
|
|
144
|
+
|
|
145
|
+
ret = io_uring_queue_init(8, &ring, flags);
|
|
146
|
+
if (ret)
|
|
147
|
+
return ret;
|
|
148
|
+
|
|
149
|
+
for (i = 0; i < LOOPS; i++) {
|
|
150
|
+
int async_cancel = (!i % 2);
|
|
151
|
+
int async_wait = !(i % 3);
|
|
152
|
+
ret = __test(&ring, vectored, async_wait, async_cancel);
|
|
153
|
+
if (ret) {
|
|
154
|
+
fprintf(stderr, "flags=%x, failed=%d\n", flags, i);
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
if (no_futex)
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
io_uring_queue_exit(&ring);
|
|
162
|
+
return ret;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static int test_order(int vectored, int async)
|
|
166
|
+
{
|
|
167
|
+
struct io_uring_sqe *sqe;
|
|
168
|
+
struct io_uring_cqe *cqe;
|
|
169
|
+
struct futex_waitv fw;
|
|
170
|
+
struct io_uring ring;
|
|
171
|
+
unsigned int *futex;
|
|
172
|
+
int ret, i;
|
|
173
|
+
|
|
174
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
|
175
|
+
if (ret)
|
|
176
|
+
return ret;
|
|
177
|
+
|
|
178
|
+
futex = malloc(sizeof(*futex));
|
|
179
|
+
*futex = 0;
|
|
180
|
+
|
|
181
|
+
fw.val = 0;
|
|
182
|
+
fw.uaddr = (unsigned long) futex;
|
|
183
|
+
fw.flags = FUTEX2_SIZE_U32;
|
|
184
|
+
fw.__reserved = 0;
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
* Submit two futex waits
|
|
188
|
+
*/
|
|
189
|
+
sqe = io_uring_get_sqe(&ring);
|
|
190
|
+
if (!vectored)
|
|
191
|
+
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
|
|
192
|
+
FUTEX2_SIZE_U32, 0);
|
|
193
|
+
else
|
|
194
|
+
io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
|
|
195
|
+
sqe->user_data = 1;
|
|
196
|
+
|
|
197
|
+
sqe = io_uring_get_sqe(&ring);
|
|
198
|
+
if (!vectored)
|
|
199
|
+
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
|
|
200
|
+
FUTEX2_SIZE_U32, 0);
|
|
201
|
+
else
|
|
202
|
+
io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
|
|
203
|
+
sqe->user_data = 2;
|
|
204
|
+
|
|
205
|
+
io_uring_submit(&ring);
|
|
206
|
+
|
|
207
|
+
/*
|
|
208
|
+
* Now submit wake for just one futex
|
|
209
|
+
*/
|
|
210
|
+
*futex = 1;
|
|
211
|
+
sqe = io_uring_get_sqe(&ring);
|
|
212
|
+
io_uring_prep_futex_wake(sqe, futex, 1, FUTEX_BITSET_MATCH_ANY,
|
|
213
|
+
FUTEX2_SIZE_U32, 0);
|
|
214
|
+
sqe->user_data = 100;
|
|
215
|
+
if (async)
|
|
216
|
+
sqe->flags |= IOSQE_ASYNC;
|
|
217
|
+
|
|
218
|
+
io_uring_submit(&ring);
|
|
219
|
+
|
|
220
|
+
/*
|
|
221
|
+
* We expect to find completions for the first futex wait, and
|
|
222
|
+
* the futex wake. We should not see the last futex wait.
|
|
223
|
+
*/
|
|
224
|
+
for (i = 0; i < 2; i++) {
|
|
225
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
226
|
+
if (ret) {
|
|
227
|
+
fprintf(stderr, "wait %d\n", ret);
|
|
228
|
+
return 1;
|
|
229
|
+
}
|
|
230
|
+
if (cqe->user_data == 1 || cqe->user_data == 100) {
|
|
231
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
fprintf(stderr, "unexpected cqe %lu, res %d\n", (unsigned long) cqe->user_data, cqe->res);
|
|
235
|
+
return 1;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
ret = io_uring_peek_cqe(&ring, &cqe);
|
|
239
|
+
if (ret != -EAGAIN) {
|
|
240
|
+
fprintf(stderr, "Unexpected cqe available: %d\n", cqe->res);
|
|
241
|
+
return 1;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
io_uring_queue_exit(&ring);
|
|
245
|
+
return 0;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static int test_multi_wake(int vectored)
|
|
249
|
+
{
|
|
250
|
+
struct io_uring_sqe *sqe;
|
|
251
|
+
struct io_uring_cqe *cqe;
|
|
252
|
+
struct futex_waitv fw;
|
|
253
|
+
struct io_uring ring;
|
|
254
|
+
unsigned int *futex;
|
|
255
|
+
int ret, i;
|
|
256
|
+
|
|
257
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
|
258
|
+
if (ret)
|
|
259
|
+
return ret;
|
|
260
|
+
|
|
261
|
+
futex = malloc(sizeof(*futex));
|
|
262
|
+
*futex = 0;
|
|
263
|
+
|
|
264
|
+
fw.val = 0;
|
|
265
|
+
fw.uaddr = (unsigned long) futex;
|
|
266
|
+
fw.flags = FUTEX2_SIZE_U32;
|
|
267
|
+
fw.__reserved = 0;
|
|
268
|
+
|
|
269
|
+
/*
|
|
270
|
+
* Submit two futex waits
|
|
271
|
+
*/
|
|
272
|
+
sqe = io_uring_get_sqe(&ring);
|
|
273
|
+
if (!vectored)
|
|
274
|
+
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
|
|
275
|
+
FUTEX2_SIZE_U32, 0);
|
|
276
|
+
else
|
|
277
|
+
io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
|
|
278
|
+
sqe->user_data = 1;
|
|
279
|
+
|
|
280
|
+
sqe = io_uring_get_sqe(&ring);
|
|
281
|
+
if (!vectored)
|
|
282
|
+
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
|
|
283
|
+
FUTEX2_SIZE_U32, 0);
|
|
284
|
+
else
|
|
285
|
+
io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
|
|
286
|
+
sqe->user_data = 2;
|
|
287
|
+
|
|
288
|
+
io_uring_submit(&ring);
|
|
289
|
+
|
|
290
|
+
/*
|
|
291
|
+
* Now submit wake for both futexes
|
|
292
|
+
*/
|
|
293
|
+
*futex = 1;
|
|
294
|
+
sqe = io_uring_get_sqe(&ring);
|
|
295
|
+
io_uring_prep_futex_wake(sqe, futex, 2, FUTEX_BITSET_MATCH_ANY,
|
|
296
|
+
FUTEX2_SIZE_U32, 0);
|
|
297
|
+
sqe->user_data = 100;
|
|
298
|
+
|
|
299
|
+
io_uring_submit(&ring);
|
|
300
|
+
|
|
301
|
+
/*
|
|
302
|
+
* We expect to find completions for the both futex waits, and
|
|
303
|
+
* the futex wake.
|
|
304
|
+
*/
|
|
305
|
+
for (i = 0; i < 3; i++) {
|
|
306
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
307
|
+
if (ret) {
|
|
308
|
+
fprintf(stderr, "wait %d\n", ret);
|
|
309
|
+
return 1;
|
|
310
|
+
}
|
|
311
|
+
if (cqe->res < 0) {
|
|
312
|
+
fprintf(stderr, "cqe error %d\n", cqe->res);
|
|
313
|
+
return 1;
|
|
314
|
+
}
|
|
315
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
ret = io_uring_peek_cqe(&ring, &cqe);
|
|
319
|
+
if (!ret) {
|
|
320
|
+
fprintf(stderr, "peek found cqe!\n");
|
|
321
|
+
return 1;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
io_uring_queue_exit(&ring);
|
|
325
|
+
return 0;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/*
|
|
329
|
+
* Test that waking 0 futexes returns 0
|
|
330
|
+
*/
|
|
331
|
+
static int test_wake_zero(void)
|
|
332
|
+
{
|
|
333
|
+
struct io_uring_sqe *sqe;
|
|
334
|
+
struct io_uring_cqe *cqe;
|
|
335
|
+
struct io_uring ring;
|
|
336
|
+
unsigned int *futex;
|
|
337
|
+
int ret;
|
|
338
|
+
|
|
339
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
|
340
|
+
if (ret)
|
|
341
|
+
return ret;
|
|
342
|
+
|
|
343
|
+
futex = malloc(sizeof(*futex));
|
|
344
|
+
*futex = 0;
|
|
345
|
+
|
|
346
|
+
sqe = io_uring_get_sqe(&ring);
|
|
347
|
+
sqe->user_data = 1;
|
|
348
|
+
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
|
|
349
|
+
FUTEX2_SIZE_U32, 0);
|
|
350
|
+
|
|
351
|
+
io_uring_submit(&ring);
|
|
352
|
+
|
|
353
|
+
sqe = io_uring_get_sqe(&ring);
|
|
354
|
+
sqe->user_data = 2;
|
|
355
|
+
io_uring_prep_futex_wake(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
|
|
356
|
+
FUTEX2_SIZE_U32, 0);
|
|
357
|
+
|
|
358
|
+
io_uring_submit(&ring);
|
|
359
|
+
|
|
360
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
361
|
+
|
|
362
|
+
/*
|
|
363
|
+
* Should get zero res and it should be the wake
|
|
364
|
+
*/
|
|
365
|
+
if (cqe->res || cqe->user_data != 2) {
|
|
366
|
+
fprintf(stderr, "cqe res %d, data %ld\n", cqe->res, (long) cqe->user_data);
|
|
367
|
+
return 1;
|
|
368
|
+
}
|
|
369
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
370
|
+
|
|
371
|
+
/*
|
|
372
|
+
* Should not have the wait complete
|
|
373
|
+
*/
|
|
374
|
+
ret = io_uring_peek_cqe(&ring, &cqe);
|
|
375
|
+
if (!ret) {
|
|
376
|
+
fprintf(stderr, "peek found cqe!\n");
|
|
377
|
+
return 1;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
io_uring_queue_exit(&ring);
|
|
381
|
+
return 0;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/*
|
|
385
|
+
* Test invalid wait/wake/waitv flags
|
|
386
|
+
*/
|
|
387
|
+
static int test_invalid(void)
|
|
388
|
+
{
|
|
389
|
+
struct io_uring_sqe *sqe;
|
|
390
|
+
struct io_uring_cqe *cqe;
|
|
391
|
+
struct futex_waitv fw;
|
|
392
|
+
struct io_uring ring;
|
|
393
|
+
unsigned int *futex;
|
|
394
|
+
int ret;
|
|
395
|
+
|
|
396
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
|
397
|
+
if (ret)
|
|
398
|
+
return ret;
|
|
399
|
+
|
|
400
|
+
futex = malloc(sizeof(*futex));
|
|
401
|
+
*futex = 0;
|
|
402
|
+
|
|
403
|
+
sqe = io_uring_get_sqe(&ring);
|
|
404
|
+
sqe->user_data = 1;
|
|
405
|
+
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY, 0x1000,
|
|
406
|
+
0);
|
|
407
|
+
|
|
408
|
+
io_uring_submit(&ring);
|
|
409
|
+
|
|
410
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
411
|
+
|
|
412
|
+
/*
|
|
413
|
+
* Should get zero res and it should be the wake
|
|
414
|
+
*/
|
|
415
|
+
if (cqe->res != -EINVAL) {
|
|
416
|
+
fprintf(stderr, "wait cqe res %d\n", cqe->res);
|
|
417
|
+
return 1;
|
|
418
|
+
}
|
|
419
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
420
|
+
|
|
421
|
+
sqe = io_uring_get_sqe(&ring);
|
|
422
|
+
sqe->user_data = 1;
|
|
423
|
+
io_uring_prep_futex_wake(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY, 0x1000,
|
|
424
|
+
0);
|
|
425
|
+
|
|
426
|
+
io_uring_submit(&ring);
|
|
427
|
+
|
|
428
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
429
|
+
|
|
430
|
+
/*
|
|
431
|
+
* Should get zero res and it should be the wake
|
|
432
|
+
*/
|
|
433
|
+
if (cqe->res != -EINVAL) {
|
|
434
|
+
fprintf(stderr, "wake cqe res %d\n", cqe->res);
|
|
435
|
+
return 1;
|
|
436
|
+
}
|
|
437
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
438
|
+
|
|
439
|
+
fw.val = 0;
|
|
440
|
+
fw.uaddr = (unsigned long) futex;
|
|
441
|
+
fw.flags = FUTEX2_SIZE_U32 | 0x1000;
|
|
442
|
+
fw.__reserved = 0;
|
|
443
|
+
|
|
444
|
+
sqe = io_uring_get_sqe(&ring);
|
|
445
|
+
sqe->user_data = 1;
|
|
446
|
+
io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
|
|
447
|
+
|
|
448
|
+
io_uring_submit(&ring);
|
|
449
|
+
|
|
450
|
+
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
451
|
+
|
|
452
|
+
/*
|
|
453
|
+
* Should get zero res and it should be the wake
|
|
454
|
+
*/
|
|
455
|
+
if (cqe->res != -EINVAL) {
|
|
456
|
+
fprintf(stderr, "waitv cqe res %d\n", cqe->res);
|
|
457
|
+
return 1;
|
|
458
|
+
}
|
|
459
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
460
|
+
|
|
461
|
+
io_uring_queue_exit(&ring);
|
|
462
|
+
return 0;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
int main(int argc, char *argv[])
|
|
466
|
+
{
|
|
467
|
+
int ret;
|
|
468
|
+
|
|
469
|
+
if (argc > 1)
|
|
470
|
+
return T_EXIT_SKIP;
|
|
471
|
+
|
|
472
|
+
ret = test(0, 0);
|
|
473
|
+
if (ret) {
|
|
474
|
+
fprintf(stderr, "test 0 0 failed\n");
|
|
475
|
+
return T_EXIT_FAIL;
|
|
476
|
+
}
|
|
477
|
+
if (no_futex)
|
|
478
|
+
return T_EXIT_SKIP;
|
|
479
|
+
|
|
480
|
+
ret = test(0, 1);
|
|
481
|
+
if (ret) {
|
|
482
|
+
fprintf(stderr, "test 0 1 failed\n");
|
|
483
|
+
return T_EXIT_FAIL;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
ret = test_wake_zero();
|
|
487
|
+
if (ret) {
|
|
488
|
+
fprintf(stderr, "wake 0 failed\n");
|
|
489
|
+
return T_EXIT_FAIL;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
ret = test_invalid();
|
|
493
|
+
if (ret) {
|
|
494
|
+
fprintf(stderr, "test invalid failed\n");
|
|
495
|
+
return T_EXIT_FAIL;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
ret = test(IORING_SETUP_SQPOLL, 0);
|
|
499
|
+
if (ret) {
|
|
500
|
+
fprintf(stderr, "test sqpoll 0 failed\n");
|
|
501
|
+
return T_EXIT_FAIL;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
ret = test(IORING_SETUP_SQPOLL, 1);
|
|
505
|
+
if (ret) {
|
|
506
|
+
fprintf(stderr, "test sqpoll 1 failed\n");
|
|
507
|
+
return T_EXIT_FAIL;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 0);
|
|
511
|
+
if (ret) {
|
|
512
|
+
fprintf(stderr, "test single coop 0 failed\n");
|
|
513
|
+
return T_EXIT_FAIL;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
ret = test(IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN, 1);
|
|
517
|
+
if (ret) {
|
|
518
|
+
fprintf(stderr, "test single coop 1 failed\n");
|
|
519
|
+
return T_EXIT_FAIL;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
ret = test(IORING_SETUP_COOP_TASKRUN, 0);
|
|
523
|
+
if (ret) {
|
|
524
|
+
fprintf(stderr, "test taskrun 0 failed\n");
|
|
525
|
+
return T_EXIT_FAIL;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
ret = test(IORING_SETUP_COOP_TASKRUN, 1);
|
|
529
|
+
if (ret) {
|
|
530
|
+
fprintf(stderr, "test taskrun 1 failed\n");
|
|
531
|
+
return T_EXIT_FAIL;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
ret = test_order(0, 0);
|
|
535
|
+
if (ret) {
|
|
536
|
+
fprintf(stderr, "test_order 0 0 failed\n");
|
|
537
|
+
return T_EXIT_FAIL;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
ret = test_order(1, 0);
|
|
541
|
+
if (ret) {
|
|
542
|
+
fprintf(stderr, "test_order 1 0 failed\n");
|
|
543
|
+
return T_EXIT_FAIL;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
ret = test_order(0, 1);
|
|
547
|
+
if (ret) {
|
|
548
|
+
fprintf(stderr, "test_order 0 1 failed\n");
|
|
549
|
+
return T_EXIT_FAIL;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
ret = test_order(1, 1);
|
|
553
|
+
if (ret) {
|
|
554
|
+
fprintf(stderr, "test_order 1 1 failed\n");
|
|
555
|
+
return T_EXIT_FAIL;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
ret = test_multi_wake(0);
|
|
559
|
+
if (ret) {
|
|
560
|
+
fprintf(stderr, "multi_wake 0 failed\n");
|
|
561
|
+
return T_EXIT_FAIL;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
ret = test_multi_wake(1);
|
|
565
|
+
if (ret) {
|
|
566
|
+
fprintf(stderr, "multi_wake 1 failed\n");
|
|
567
|
+
return T_EXIT_FAIL;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return T_EXIT_PASS;
|
|
571
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/* SPDX-License-Identifier: MIT */
|
|
2
|
+
/*
|
|
3
|
+
* Description: test io_uring linkat handling
|
|
4
|
+
*/
|
|
5
|
+
#include <fcntl.h>
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
#include <sys/stat.h>
|
|
9
|
+
#include <sys/types.h>
|
|
10
|
+
#include <unistd.h>
|
|
11
|
+
|
|
12
|
+
#include "liburing.h"
|
|
13
|
+
#include "helpers.h"
|
|
14
|
+
|
|
15
|
+
static int do_linkat(struct io_uring *ring, int olddirfd, const char *oldname,
|
|
16
|
+
const char *newname, int flags)
|
|
17
|
+
{
|
|
18
|
+
struct io_uring_sqe *sqe;
|
|
19
|
+
struct io_uring_cqe *cqe;
|
|
20
|
+
int ret;
|
|
21
|
+
|
|
22
|
+
sqe = io_uring_get_sqe(ring);
|
|
23
|
+
if (!sqe) {
|
|
24
|
+
fprintf(stderr, "sqe get failed\n");
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
io_uring_prep_linkat(sqe, olddirfd, oldname, AT_FDCWD, newname, flags);
|
|
28
|
+
|
|
29
|
+
ret = io_uring_submit(ring);
|
|
30
|
+
if (ret != 1) {
|
|
31
|
+
fprintf(stderr, "submit failed: %d\n", ret);
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
ret = io_uring_wait_cqes(ring, &cqe, 1, 0, 0);
|
|
36
|
+
if (ret) {
|
|
37
|
+
fprintf(stderr, "wait_cqe failed: %d\n", ret);
|
|
38
|
+
return 1;
|
|
39
|
+
}
|
|
40
|
+
ret = cqe->res;
|
|
41
|
+
io_uring_cqe_seen(ring, cqe);
|
|
42
|
+
return ret;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static int files_linked_ok(const char* fn1, const char *fn2)
|
|
46
|
+
{
|
|
47
|
+
struct stat s1, s2;
|
|
48
|
+
|
|
49
|
+
if (stat(fn1, &s1)) {
|
|
50
|
+
fprintf(stderr, "stat(%s): %s\n", fn1, strerror(errno));
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
if (stat(fn2, &s2)) {
|
|
54
|
+
fprintf(stderr, "stat(%s): %s\n", fn2, strerror(errno));
|
|
55
|
+
return 0;
|
|
56
|
+
}
|
|
57
|
+
if (s1.st_dev != s2.st_dev || s1.st_ino != s2.st_ino) {
|
|
58
|
+
fprintf(stderr, "linked files have different device / inode numbers\n");
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
if (s1.st_nlink != 2 || s2.st_nlink != 2) {
|
|
62
|
+
fprintf(stderr, "linked files have unexpected links count\n");
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
int main(int argc, char *argv[])
|
|
69
|
+
{
|
|
70
|
+
static const char target[] = "io_uring-linkat-test-target";
|
|
71
|
+
static const char emptyname[] = "io_uring-linkat-test-empty";
|
|
72
|
+
static const char linkname[] = "io_uring-linkat-test-link";
|
|
73
|
+
static const char symlinkname[] = "io_uring-linkat-test-symlink";
|
|
74
|
+
struct io_uring ring;
|
|
75
|
+
int ret, fd, exit_status = T_EXIT_FAIL;
|
|
76
|
+
|
|
77
|
+
if (argc > 1)
|
|
78
|
+
return T_EXIT_SKIP;
|
|
79
|
+
|
|
80
|
+
ret = io_uring_queue_init(8, &ring, 0);
|
|
81
|
+
if (ret) {
|
|
82
|
+
fprintf(stderr, "queue init failed: %d\n", ret);
|
|
83
|
+
return ret;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ret = fd = open(target, O_CREAT | O_RDWR | O_EXCL, 0600);
|
|
87
|
+
if (ret < 0) {
|
|
88
|
+
perror("open");
|
|
89
|
+
goto out;
|
|
90
|
+
}
|
|
91
|
+
if (write(fd, "linktest", 8) != 8) {
|
|
92
|
+
close(fd);
|
|
93
|
+
goto out;
|
|
94
|
+
}
|
|
95
|
+
if(geteuid()) {
|
|
96
|
+
fprintf(stdout, "not root, skipping AT_EMPTY_PATH test\n");
|
|
97
|
+
} else {
|
|
98
|
+
ret = do_linkat(&ring, fd, "", emptyname, AT_EMPTY_PATH);
|
|
99
|
+
if (ret < 0) {
|
|
100
|
+
if (ret == -EBADF || ret == -EINVAL) {
|
|
101
|
+
fprintf(stdout, "linkat not supported, skipping\n");
|
|
102
|
+
exit_status = T_EXIT_SKIP;
|
|
103
|
+
goto out;
|
|
104
|
+
}
|
|
105
|
+
fprintf(stderr, "linkat: %s\n", strerror(-ret));
|
|
106
|
+
goto out;
|
|
107
|
+
} else if (ret) {
|
|
108
|
+
goto out;
|
|
109
|
+
}
|
|
110
|
+
if (!files_linked_ok(emptyname, target))
|
|
111
|
+
goto out;
|
|
112
|
+
unlinkat(AT_FDCWD, emptyname, 0);
|
|
113
|
+
}
|
|
114
|
+
close(fd);
|
|
115
|
+
|
|
116
|
+
ret = symlink(target, symlinkname);
|
|
117
|
+
if (ret < 0) {
|
|
118
|
+
perror("open");
|
|
119
|
+
goto out;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
ret = do_linkat(&ring, AT_FDCWD, target, linkname, 0);
|
|
123
|
+
if (ret < 0) {
|
|
124
|
+
if (ret == -EBADF || ret == -EINVAL) {
|
|
125
|
+
fprintf(stdout, "linkat not supported, skipping\n");
|
|
126
|
+
exit_status = T_EXIT_SKIP;
|
|
127
|
+
goto out;
|
|
128
|
+
}
|
|
129
|
+
fprintf(stderr, "linkat: %s\n", strerror(-ret));
|
|
130
|
+
goto out;
|
|
131
|
+
} else if (ret) {
|
|
132
|
+
goto out;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!files_linked_ok(linkname, target))
|
|
136
|
+
goto out;
|
|
137
|
+
|
|
138
|
+
unlinkat(AT_FDCWD, linkname, 0);
|
|
139
|
+
|
|
140
|
+
ret = do_linkat(&ring, AT_FDCWD, symlinkname, linkname, AT_SYMLINK_FOLLOW);
|
|
141
|
+
if (ret < 0) {
|
|
142
|
+
fprintf(stderr, "linkat: %s\n", strerror(-ret));
|
|
143
|
+
goto out;
|
|
144
|
+
} else if (ret) {
|
|
145
|
+
goto out;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (!files_linked_ok(symlinkname, target))
|
|
149
|
+
goto out;
|
|
150
|
+
|
|
151
|
+
ret = do_linkat(&ring, AT_FDCWD, target, linkname, 0);
|
|
152
|
+
if (ret != -EEXIST) {
|
|
153
|
+
fprintf(stderr, "test_linkat linkname already exists failed: %d\n", ret);
|
|
154
|
+
goto out;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
ret = do_linkat(&ring, AT_FDCWD, target, "surely/this/does/not/exist", 0);
|
|
158
|
+
if (ret != -ENOENT) {
|
|
159
|
+
fprintf(stderr, "test_linkat no parent failed: %d\n", ret);
|
|
160
|
+
goto out;
|
|
161
|
+
}
|
|
162
|
+
exit_status = T_EXIT_PASS;
|
|
163
|
+
out:
|
|
164
|
+
unlinkat(AT_FDCWD, symlinkname, 0);
|
|
165
|
+
unlinkat(AT_FDCWD, linkname, 0);
|
|
166
|
+
unlinkat(AT_FDCWD, emptyname, 0);
|
|
167
|
+
unlinkat(AT_FDCWD, target, 0);
|
|
168
|
+
io_uring_queue_exit(&ring);
|
|
169
|
+
return exit_status;
|
|
170
|
+
}
|