test/msg-ring-sync: mix in IO for remote testing
Some things can behave differently depending on what the other end is
currently doing, so try and test those cases too where the other end
isn't just idle, waiting for a message.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/test/msg-ring-sync.c b/test/msg-ring-sync.c
index f09e5d8..7daa158 100644
--- a/test/msg-ring-sync.c
+++ b/test/msg-ring-sync.c
@@ -19,62 +19,126 @@
struct data {
struct io_uring *ring;
unsigned int flags;
+ int with_io;
pthread_barrier_t startup;
pthread_barrier_t barrier;
};
+#define FILE_SIZE (512 * 1024)
+#define BS 4096
+#define BUFFERS (FILE_SIZE / BS)
+
static void *wait_cqe_fn(void *__data)
{
+ struct iovec *vecs;
+ char fname[256];
struct data *d = __data;
struct io_uring_cqe *cqe;
struct io_uring ring;
- int ret;
+ int ret, i, fd = -1, to_wait;
- ret = io_uring_queue_init(4, &ring, d->flags);
+ srand((unsigned)time(NULL));
+ snprintf(fname, sizeof(fname), ".basic-rw-%u-%u",
+ (unsigned)rand(), (unsigned)getpid());
+ if (d->with_io) {
+ t_create_file(fname, FILE_SIZE);
+ vecs = t_create_buffers(BUFFERS, BS);
+ } else {
+ vecs = NULL;
+ }
+
+ ret = io_uring_queue_init(BUFFERS, &ring, d->flags);
+ if (ret) {
+up_skip:
+ pthread_barrier_wait(&d->startup);
+ pthread_barrier_wait(&d->barrier);
+ goto skip;
+ }
+
+ if (d->with_io) {
+ off_t off = 0;
+
+ fd = open(fname, O_RDONLY | O_DIRECT);
+ if (fd < 0)
+ goto up_skip;
+
+ for (i = 0; i < BUFFERS; i++) {
+ struct io_uring_sqe *sqe;
+
+ sqe = io_uring_get_sqe(&ring);
+ io_uring_prep_read(sqe, fd, vecs[i].iov_base,
+ vecs[i].iov_len, off);
+ sqe->user_data = 1;
+ io_uring_submit(&ring);
+ off += vecs[i].iov_len;
+ }
+ }
+
d->ring = ˚
pthread_barrier_wait(&d->startup);
-
pthread_barrier_wait(&d->barrier);
- if (ret == -EINVAL)
- goto skip;
+ to_wait = 1;
+ if (d->with_io)
+ to_wait += BUFFERS;
- ret = io_uring_wait_cqe(&ring, &cqe);
- if (ret) {
- fprintf(stderr, "wait cqe %d\n", ret);
- goto err_no_cqe;
+ for (i = 0; i < to_wait; i++) {
+ ret = io_uring_wait_cqe(&ring, &cqe);
+ if (ret) {
+ fprintf(stderr, "wait cqe %d\n", ret);
+ goto err_no_cqe;
+ }
+ if (cqe->user_data != 0x5aa5 && cqe->user_data != 1) {
+ fprintf(stderr, "user_data %llx\n", (long long) cqe->user_data);
+ goto err;
+ }
+ if (cqe->user_data == 0x5aa5) {
+ if (cqe->res != 0x20) {
+ fprintf(stderr, "msg len %x\n", cqe->res);
+ goto err;
+ }
+ } else {
+ if (cqe->res != BS && cqe->res != -EINVAL &&
+ cqe->res != -EOPNOTSUPP) {
+ fprintf(stderr, "rw len %d\n", cqe->res);
+ goto err;
+ }
+ }
+ io_uring_cqe_seen(&ring, cqe);
}
-
- if (cqe->user_data != 0x5aa5) {
- fprintf(stderr, "user_data %llx\n", (long long) cqe->user_data);
- goto err;
- }
- if (cqe->res != 0x20) {
- fprintf(stderr, "len %x\n", cqe->res);
- goto err;
- }
-
- io_uring_cqe_seen(&ring, cqe);
skip:
+ if (fd != -1)
+ close(fd);
+ if (d->with_io) {
+ t_destroy_buffers(vecs, BUFFERS);
+ unlink(fname);
+ }
io_uring_queue_exit(&ring);
return NULL;
err:
io_uring_cqe_seen(&ring, cqe);
err_no_cqe:
+ if (fd != -1)
+ close(fd);
+ if (d->with_io) {
+ t_destroy_buffers(vecs, BUFFERS);
+ unlink(fname);
+ }
io_uring_queue_exit(&ring);
return (void *) (unsigned long) 1;
}
-static int test_remote(unsigned int ring_flags)
+static int test_remote(unsigned int ring_flags, int with_io)
{
struct io_uring *target;
pthread_t thread;
void *tret;
struct io_uring_sqe sqe = { };
- struct data d;
+ struct data d = { };
int ret;
d.flags = ring_flags;
+ d.with_io = with_io;
pthread_barrier_init(&d.barrier, NULL, 2);
pthread_barrier_init(&d.startup, NULL, 2);
pthread_create(&thread, NULL, wait_cqe_fn, &d);
@@ -142,7 +206,7 @@
sqe.user_data = 1;
ret = io_uring_register_sync_msg_ring(&sqe);
- if (ret != 0 && ret != -EBADFD) {
+ if (ret != -EBADFD) {
fprintf(stderr, "res %d\n", ret);
return 1;
}
@@ -160,15 +224,28 @@
return T_EXIT_FAIL;
}
- ret = test_remote(ring_flags);
+ ret = test_remote(ring_flags, 0);
if (ret) {
- fprintf(stderr, "test_remote failed\n");
+ fprintf(stderr, "test_remote 0 failed\n");
return T_EXIT_FAIL;
}
- ret = test_remote(ring_flags | IORING_SETUP_IOPOLL);
+ ret = test_remote(ring_flags, 1);
if (ret) {
- fprintf(stderr, "test_remote failed\n");
+ fprintf(stderr, "test_remote 1 failed\n");
+ return T_EXIT_FAIL;
+ }
+
+
+ ret = test_remote(ring_flags | IORING_SETUP_IOPOLL, 0);
+ if (ret) {
+ fprintf(stderr, "test_remote poll 0 failed\n");
+ return T_EXIT_FAIL;
+ }
+
+ ret = test_remote(ring_flags | IORING_SETUP_IOPOLL, 1);
+ if (ret) {
+ fprintf(stderr, "test_remote poll 1 failed\n");
return T_EXIT_FAIL;
}
@@ -187,24 +264,28 @@
int main(int argc, char *argv[])
{
- int ret;
+ int ret, i;
if (argc > 1)
return T_EXIT_SKIP;
- ret = test(0);
- if (ret != T_EXIT_PASS) {
- fprintf(stderr, "ring flags 0 failed\n");
- return ret;
- }
- if (no_msg)
- return T_EXIT_SKIP;
-
- ret = test(IORING_SETUP_SINGLE_ISSUER|IORING_SETUP_DEFER_TASKRUN);
- if (ret != T_EXIT_PASS) {
- fprintf(stderr, "ring flags defer failed\n");
- return ret;
+ for (i = 0; i < 5; i++) {
+ ret = test(0);
+ if (ret != T_EXIT_PASS) {
+ fprintf(stderr, "ring flags 0 failed\n");
+ return ret;
+ }
+ if (no_msg)
+ return T_EXIT_SKIP;
}
- return ret;
+ for (i = 0; i < 5; i++) {
+ ret = test(IORING_SETUP_SINGLE_ISSUER|IORING_SETUP_DEFER_TASKRUN);
+ if (ret != T_EXIT_PASS) {
+ fprintf(stderr, "ring flags defer failed\n");
+ return ret;
+ }
+ }
+
+ return T_EXIT_PASS;
}