summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2019-10-16 09:14:11 -0600
committerJens Axboe <axboe@kernel.dk>2019-10-16 09:14:11 -0600
commit80d8217c2fcfff2cfd6d82fb5ffe31796cc8dd5c (patch)
tree7d948e9aaec2e74a27227368e85fefad026d3b65
parentb75b52e2d4373fa75c756b9f64c2f046ec5bd58b (diff)
downloadliburing-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.h7
-rw-r--r--src/include/liburing/io_uring.h1
-rw-r--r--test/timeout.c160
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");