* [PATCH liburing 0/2] test timeout updates
@ 2020-11-29 17:29 Pavel Begunkov
2020-11-29 17:29 ` [PATCH liburing 1/2] Add timeout update Pavel Begunkov
2020-11-29 17:29 ` [PATCH liburing 2/2] test/timeout: test timeout updates Pavel Begunkov
0 siblings, 2 replies; 3+ messages in thread
From: Pavel Begunkov @ 2020-11-29 17:29 UTC (permalink / raw)
To: Jens Axboe, io-uring
Pavel Begunkov (2):
Add timeout update
test/timeout: test timeout updates
src/include/liburing.h | 9 ++
src/include/liburing/io_uring.h | 1 +
test/timeout.c | 255 ++++++++++++++++++++++++++++++++
3 files changed, 265 insertions(+)
--
2.24.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH liburing 1/2] Add timeout update
2020-11-29 17:29 [PATCH liburing 0/2] test timeout updates Pavel Begunkov
@ 2020-11-29 17:29 ` Pavel Begunkov
2020-11-29 17:29 ` [PATCH liburing 2/2] test/timeout: test timeout updates Pavel Begunkov
1 sibling, 0 replies; 3+ messages in thread
From: Pavel Begunkov @ 2020-11-29 17:29 UTC (permalink / raw)
To: Jens Axboe, io-uring
Add io_uring_prep_timeout_update() helper and update io_uring.h.
Signed-off-by: Pavel Begunkov <[email protected]>
---
src/include/liburing.h | 9 +++++++++
src/include/liburing/io_uring.h | 1 +
2 files changed, 10 insertions(+)
diff --git a/src/include/liburing.h b/src/include/liburing.h
index cc32232..ebfc424 100644
--- a/src/include/liburing.h
+++ b/src/include/liburing.h
@@ -326,6 +326,15 @@ static inline void io_uring_prep_timeout_remove(struct io_uring_sqe *sqe,
sqe->timeout_flags = flags;
}
+static inline void io_uring_prep_timeout_update(struct io_uring_sqe *sqe,
+ struct __kernel_timespec *ts,
+ __u64 user_data, unsigned flags)
+{
+ io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, -1,
+ (void *)(unsigned long)user_data, 0, (__u64)ts);
+ sqe->timeout_flags = flags | IORING_TIMEOUT_UPDATE;
+}
+
static inline void io_uring_prep_accept(struct io_uring_sqe *sqe, int fd,
struct sockaddr *addr,
socklen_t *addrlen, int flags)
diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h
index 8555de9..abdc737 100644
--- a/src/include/liburing/io_uring.h
+++ b/src/include/liburing/io_uring.h
@@ -155,6 +155,7 @@ enum {
* sqe->timeout_flags
*/
#define IORING_TIMEOUT_ABS (1U << 0)
+#define IORING_TIMEOUT_UPDATE (1U << 31)
/*
* sqe->splice_flags
--
2.24.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH liburing 2/2] test/timeout: test timeout updates
2020-11-29 17:29 [PATCH liburing 0/2] test timeout updates Pavel Begunkov
2020-11-29 17:29 ` [PATCH liburing 1/2] Add timeout update Pavel Begunkov
@ 2020-11-29 17:29 ` Pavel Begunkov
1 sibling, 0 replies; 3+ messages in thread
From: Pavel Begunkov @ 2020-11-29 17:29 UTC (permalink / raw)
To: Jens Axboe, io-uring
Test timeout updates if supported. Fuzzy checks that it sustains
specified timings. Tests async/linked update, short and longer delays.
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/timeout.c | 255 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 255 insertions(+)
diff --git a/test/timeout.c b/test/timeout.c
index 7e9f11d..9db7661 100644
--- a/test/timeout.c
+++ b/test/timeout.c
@@ -965,10 +965,213 @@ err:
return 1;
}
+static int test_update_timeout(struct io_uring *ring, unsigned long ms,
+ bool abs, bool async, bool linked)
+{
+ struct io_uring_sqe *sqe;
+ struct io_uring_cqe *cqe;
+ struct __kernel_timespec ts, ts_upd;
+ unsigned long long exp_ms, base_ms = 10000;
+ struct timeval tv;
+ int ret, i, nr = 2;
+ __u32 mode = abs ? IORING_TIMEOUT_ABS : 0;
+
+ msec_to_ts(&ts_upd, ms);
+ gettimeofday(&tv, NULL);
+
+ sqe = io_uring_get_sqe(ring);
+ if (!sqe) {
+ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+ goto err;
+ }
+ msec_to_ts(&ts, base_ms);
+ io_uring_prep_timeout(sqe, &ts, 0, 0);
+ sqe->user_data = 1;
+
+ if (linked) {
+ sqe = io_uring_get_sqe(ring);
+ if (!sqe) {
+ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+ goto err;
+ }
+ io_uring_prep_nop(sqe);
+ sqe->user_data = 3;
+ sqe->flags = IOSQE_IO_LINK;
+ if (async)
+ sqe->flags |= IOSQE_ASYNC;
+ nr++;
+ }
+
+ sqe = io_uring_get_sqe(ring);
+ if (!sqe) {
+ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+ goto err;
+ }
+ io_uring_prep_timeout_update(sqe, &ts_upd, 1, mode);
+ sqe->user_data = 2;
+ if (async)
+ sqe->flags |= IOSQE_ASYNC;
+
+ ret = io_uring_submit(ring);
+ if (ret != nr) {
+ fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+ goto err;
+ }
+
+ for (i = 0; i < nr; i++) {
+ ret = io_uring_wait_cqe(ring, &cqe);
+ if (ret < 0) {
+ fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+ goto err;
+ }
+
+ switch (cqe->user_data) {
+ case 1:
+ if (cqe->res != -ETIME) {
+ fprintf(stderr, "%s: got %d, wanted %d\n",
+ __FUNCTION__, cqe->res, -ETIME);
+ goto err;
+ }
+ break;
+ case 2:
+ if (cqe->res != 0) {
+ fprintf(stderr, "%s: got %d, wanted %d\n",
+ __FUNCTION__, cqe->res,
+ 0);
+ goto err;
+ }
+ break;
+ case 3:
+ if (cqe->res != 0) {
+ fprintf(stderr, "nop failed\n");
+ goto err;
+ }
+ break;
+ default:
+ goto err;
+ }
+ io_uring_cqe_seen(ring, cqe);
+ }
+
+ exp_ms = mtime_since_now(&tv);
+ if (exp_ms >= base_ms / 2) {
+ fprintf(stderr, "too long, timeout wasn't updated\n");
+ goto err;
+ }
+ if (ms >= 1000 && !abs && exp_ms < ms / 2) {
+ fprintf(stderr, "fired too early, potentially updated to 0 ms"
+ "instead of %lu\n", ms);
+ goto err;
+ }
+ return 0;
+err:
+ return 1;
+}
+
+static int test_update_nonexistent_timeout(struct io_uring *ring)
+{
+ struct io_uring_sqe *sqe;
+ struct io_uring_cqe *cqe;
+ struct __kernel_timespec ts;
+ int ret;
+
+ sqe = io_uring_get_sqe(ring);
+ if (!sqe) {
+ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+ goto err;
+ }
+ msec_to_ts(&ts, 0);
+ io_uring_prep_timeout_update(sqe, &ts, 42, 0);
+
+ ret = io_uring_submit(ring);
+ if (ret != 1) {
+ fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+ goto err;
+ }
+
+ ret = io_uring_wait_cqe(ring, &cqe);
+ if (ret < 0) {
+ fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+ goto err;
+ }
+
+ ret = cqe->res;
+ if (ret == -ENOENT)
+ ret = 0;
+ io_uring_cqe_seen(ring, cqe);
+ return ret;
+err:
+ return 1;
+}
+
+static int test_update_invalid_flags(struct io_uring *ring)
+{
+ struct io_uring_sqe *sqe;
+ struct io_uring_cqe *cqe;
+ struct __kernel_timespec ts;
+ int ret;
+
+ sqe = io_uring_get_sqe(ring);
+ if (!sqe) {
+ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+ goto err;
+ }
+ io_uring_prep_timeout_remove(sqe, 0, IORING_TIMEOUT_ABS);
+
+ ret = io_uring_submit(ring);
+ if (ret != 1) {
+ fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+ goto err;
+ }
+
+ ret = io_uring_wait_cqe(ring, &cqe);
+ if (ret < 0) {
+ fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+ goto err;
+ }
+ if (cqe->res != -EINVAL) {
+ fprintf(stderr, "%s: got %d, wanted %d\n",
+ __FUNCTION__, cqe->res, -EINVAL);
+ goto err;
+ }
+ io_uring_cqe_seen(ring, cqe);
+
+
+ sqe = io_uring_get_sqe(ring);
+ if (!sqe) {
+ fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__);
+ goto err;
+ }
+ msec_to_ts(&ts, 0);
+ io_uring_prep_timeout_update(sqe, &ts, 0, -1);
+
+ ret = io_uring_submit(ring);
+ if (ret != 1) {
+ fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret);
+ goto err;
+ }
+
+ ret = io_uring_wait_cqe(ring, &cqe);
+ if (ret < 0) {
+ fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret);
+ goto err;
+ }
+ if (cqe->res != -EINVAL) {
+ fprintf(stderr, "%s: got %d, wanted %d\n",
+ __FUNCTION__, cqe->res, -EINVAL);
+ goto err;
+ }
+ io_uring_cqe_seen(ring, cqe);
+
+ return 0;
+err:
+ return 1;
+}
int main(int argc, char *argv[])
{
struct io_uring ring;
+ bool has_timeout_update;
int ret;
if (argc > 1)
@@ -1054,6 +1257,58 @@ int main(int argc, char *argv[])
return ret;
}
+ ret = test_update_nonexistent_timeout(&ring);
+ has_timeout_update = (ret != -EINVAL);
+ if (has_timeout_update) {
+ if (ret) {
+ fprintf(stderr, "test_update_nonexistent_timeout failed\n");
+ return ret;
+ }
+
+ ret = test_update_invalid_flags(&ring);
+ if (ret) {
+ fprintf(stderr, "test_update_invalid_flags failed\n");
+ return ret;
+ }
+
+ ret = test_update_timeout(&ring, 0, false, false, false);
+ if (ret) {
+ fprintf(stderr, "test_update_timeout failed\n");
+ return ret;
+ }
+
+ ret = test_update_timeout(&ring, 1, false, false, false);
+ if (ret) {
+ fprintf(stderr, "test_update_timeout 1ms failed\n");
+ return ret;
+ }
+
+ ret = test_update_timeout(&ring, 1000, false, false, false);
+ if (ret) {
+ fprintf(stderr, "test_update_timeout 1s failed\n");
+ return ret;
+ }
+
+ ret = test_update_timeout(&ring, 0, true, true, false);
+ if (ret) {
+ fprintf(stderr, "test_update_timeout abs failed\n");
+ return ret;
+ }
+
+
+ ret = test_update_timeout(&ring, 0, false, true, false);
+ if (ret) {
+ fprintf(stderr, "test_update_timeout async failed\n");
+ return ret;
+ }
+
+ ret = test_update_timeout(&ring, 0, false, false, true);
+ if (ret) {
+ fprintf(stderr, "test_update_timeout linked failed\n");
+ return ret;
+ }
+ }
+
/*
* this test must go last, it kills the ring
*/
--
2.24.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-11-29 17:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-11-29 17:29 [PATCH liburing 0/2] test timeout updates Pavel Begunkov
2020-11-29 17:29 ` [PATCH liburing 1/2] Add timeout update Pavel Begunkov
2020-11-29 17:29 ` [PATCH liburing 2/2] test/timeout: test timeout updates Pavel Begunkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox