test/resize-rings: add test case for mmap vs resize race Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/test/resize-rings.c b/test/resize-rings.c index 8d2707a..7e3cd7c 100644 --- a/test/resize-rings.c +++ b/test/resize-rings.c
@@ -468,6 +468,78 @@ return T_EXIT_PASS; } +static int mmap_child(struct io_uring *__ring, struct io_uring_params *__p) +{ + struct io_uring ring = *__ring; + struct timeval tv; + int ret; + + gettimeofday(&tv, NULL); + do { + struct io_uring_params p = *__p; + void *sq_ptr, *cq_ptr; + + ret = io_uring_queue_mmap(__ring->ring_fd, &p, &ring); + if (ret) + continue; + + sq_ptr = ring.sq.ring_ptr + 2 * sizeof(__u32); + cq_ptr = ring.cq.ring_ptr + 2 * sizeof(__u32); + memset(sq_ptr, 0x5a, ring.sq.ring_sz - 2 * sizeof(__u32)); + memset(cq_ptr, 0xa5, ring.cq.ring_sz - 2 * sizeof(__u32)); + io_uring_unmap_rings(&ring.sq, &ring.cq); + } while (mtime_since_now(&tv) < 2500); + + exit(T_EXIT_PASS); +} + +static int test_mmap_race(struct io_uring *ring, struct io_uring_params *__p) +{ + unsigned long useless_sum; + int i, w, nr_children; + struct timeval tv; + pid_t pid; + + nr_children = sysconf(_SC_NPROCESSORS_ONLN); + if (nr_children < 0) + nr_children = 4; + + for (i = 0; i < nr_children; i++) { + pid = fork(); + if (!pid) { + mmap_child(ring, __p); + return T_EXIT_PASS; + } + } + + useless_sum = 0; + gettimeofday(&tv, NULL); + do { + struct io_uring_params p = { .sq_entries = 32, }; + void *ptr; + + io_uring_resize_rings(ring, &p); + + ptr = memchr(ring->sq.ring_ptr, 0x5a, ring->sq.ring_sz); + if (ptr) + useless_sum += ptr - ring->sq.ring_ptr; + + ptr = memchr(ring->cq.ring_ptr, 0xa5, ring->cq.ring_sz); + if (ptr) + useless_sum += ptr - ring->cq.ring_ptr; + + p.sq_entries = 128; + io_uring_resize_rings(ring, &p); + } while (mtime_since_now(&tv) < 2500); + + for (i = 0; i < nr_children; i++) + wait(&w); + + if (useless_sum) + return T_EXIT_PASS; + return T_EXIT_PASS; +} + static int test(int flags, int fd, int async) { struct io_uring_params p = { @@ -502,6 +574,9 @@ return T_EXIT_FAIL; } + if (async) + return T_EXIT_PASS; + ret = test_all_copy(&ring); if (ret == T_EXIT_FAIL) { fprintf(stderr, "test_all_copy %x failed\n", flags); @@ -520,6 +595,13 @@ return T_EXIT_FAIL; } + /* must go at the end, insert more tests above this one */ + ret = test_mmap_race(&ring, &p); + if (ret == T_EXIT_FAIL) { + fprintf(stderr, "test_mmap_race %x failed\n", flags); + return T_EXIT_FAIL; + } + io_uring_queue_exit(&ring); return T_EXIT_PASS; }