diff options
author | Jens Axboe <axboe@kernel.dk> | 2019-10-16 09:14:11 -0600 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2019-10-16 09:14:11 -0600 |
commit | 80d8217c2fcfff2cfd6d82fb5ffe31796cc8dd5c (patch) | |
tree | 7d948e9aaec2e74a27227368e85fefad026d3b65 | |
parent | b75b52e2d4373fa75c756b9f64c2f046ec5bd58b (diff) | |
download | liburing-80d8217c2fcfff2cfd6d82fb5ffe31796cc8dd5c.tar.gz liburing-80d8217c2fcfff2cfd6d82fb5ffe31796cc8dd5c.tar.bz2 |
Add IORING_OP_TIMEOUT_REMOVE
Add the command opcode, and add two test cases for it.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | src/include/liburing.h | 7 | ||||
-rw-r--r-- | src/include/liburing/io_uring.h | 1 | ||||
-rw-r--r-- | test/timeout.c | 160 |
3 files changed, 168 insertions, 0 deletions
diff --git a/src/include/liburing.h b/src/include/liburing.h index 6d7c423..d7a2bc2 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -263,6 +263,13 @@ static inline void io_uring_prep_timeout(struct io_uring_sqe *sqe, sqe->timeout_flags = flags; } +static inline void io_uring_prep_timeout_remove(struct io_uring_sqe *sqe, + __u64 user_data, unsigned flags) +{ + io_uring_prep_rw(IORING_OP_TIMEOUT_REMOVE, sqe, 0, (void *)user_data, 0, 0); + sqe->timeout_flags = flags; +} + static inline unsigned io_uring_sq_space_left(struct io_uring *ring) { return *ring->sq.kring_entries - (ring->sq.sqe_tail - ring->sq.sqe_head); diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index b402dfe..6dc5ced 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -64,6 +64,7 @@ struct io_uring_sqe { #define IORING_OP_SENDMSG 9 #define IORING_OP_RECVMSG 10 #define IORING_OP_TIMEOUT 11 +#define IORING_OP_TIMEOUT_REMOVE 12 /* * sqe->fsync_flags diff --git a/test/timeout.c b/test/timeout.c index 3b12d9f..71147ce 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -14,6 +14,7 @@ #define TIMEOUT_MSEC 1000 static int not_supported; +static int no_modify; static unsigned long long mtime_since(const struct timeval *s, const struct timeval *e) @@ -278,6 +279,153 @@ err: return 1; } +static int test_single_timeout_remove_notfound(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + struct __kernel_timespec ts; + int ret, i; + + if (no_modify) + return 0; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__); + goto err; + } + + ts.tv_sec = TIMEOUT_MSEC / 1000; + ts.tv_nsec = 0; + io_uring_prep_timeout(sqe, &ts, 2, 0); + sqe->user_data = 1; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret); + goto err; + } + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__); + goto err; + } + + io_uring_prep_timeout_remove(sqe, 2, 0); + sqe->user_data = 2; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret); + goto err; + } + + /* + * We should get two completions. One is our modify request, which should + * complete with -ENOENT. The other is the timeout that will trigger after + * TIMEOUT_MSEC. + */ + for (i = 0; i < 2; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret); + goto err; + } + if (cqe->user_data == 2) { + if (cqe->res != -ENOENT) { + fprintf(stderr, "%s: modify ret %d, wanted ENOENT\n", __FUNCTION__, cqe->res); + break; + } + } else if (cqe->user_data == 1) { + if (cqe->res != -ETIME) { + fprintf(stderr, "%s: timeout ret %d, wanted -ETIME\n", __FUNCTION__, cqe->res); + break; + } + } + io_uring_cqe_seen(ring, cqe); + } + return 0; +err: + return 1; +} + +static int test_single_timeout_remove(struct io_uring *ring) +{ + struct io_uring_cqe *cqe; + struct io_uring_sqe *sqe; + struct __kernel_timespec ts; + int ret, i; + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__); + goto err; + } + + ts.tv_sec = TIMEOUT_MSEC / 1000; + ts.tv_nsec = 0; + io_uring_prep_timeout(sqe, &ts, 0, 0); + sqe->user_data = 1; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret); + goto err; + } + + sqe = io_uring_get_sqe(ring); + if (!sqe) { + fprintf(stderr, "%s: get sqe failed\n", __FUNCTION__); + goto err; + } + + io_uring_prep_timeout_remove(sqe, 1, 0); + sqe->user_data = 2; + + ret = io_uring_submit(ring); + if (ret <= 0) { + fprintf(stderr, "%s: sqe submit failed: %d\n", __FUNCTION__, ret); + goto err; + } + + /* + * We should have two completions ready. One is for the original timeout + * request, user_data == 1, that should have a ret of -ECANCELED. The other + * is for our modify request, user_data == 2, that should have a ret of 0. + */ + for (i = 0; i < 2; i++) { + ret = io_uring_wait_cqe(ring, &cqe); + if (ret < 0) { + fprintf(stderr, "%s: wait completion %d\n", __FUNCTION__, ret); + goto err; + } + if (no_modify) + goto seen; + if (cqe->res == -EINVAL && cqe->user_data == 2) { + fprintf(stdout, "Timeout modify not supported, ignoring\n"); + no_modify = 1; + goto seen; + } + if (cqe->user_data == 1) { + if (cqe->res != -ECANCELED) { + fprintf(stderr, "%s: timeout ret %d, wanted canceled\n", __FUNCTION__, cqe->res); + break; + } + } else if (cqe->user_data == 2) { + if (cqe->res) { + fprintf(stderr, "%s: modify ret %d, wanted 0\n", __FUNCTION__, cqe->res); + break; + } + } +seen: + io_uring_cqe_seen(ring, cqe); + } + return 0; +err: + return 1; +} + /* * Test single absolute timeout waking us up */ @@ -389,6 +537,18 @@ int main(int argc, char *argv[]) return ret; } + ret = test_single_timeout_remove(&ring); + if (ret) { + fprintf(stderr, "test_single_timeout_remove failed\n"); + return ret; + } + + ret = test_single_timeout_remove_notfound(&ring); + if (ret) { + fprintf(stderr, "test_single_timeout_remove_notfound failed\n"); + return ret; + } + ret = test_single_timeout_many(&ring); if (ret) { fprintf(stderr, "test_single_timeout_many failed\n"); |