test/send_recv: add SQPOLL test case

Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/test/send_recv.c b/test/send_recv.c
index da73f1f..5f4fe54 100644
--- a/test/send_recv.c
+++ b/test/send_recv.c
@@ -26,11 +26,11 @@
 #	define io_uring_prep_recv io_uring_prep_read
 #endif
 
-static int recv_prep(struct io_uring *ring, struct iovec *iov)
+static int recv_prep(struct io_uring *ring, struct iovec *iov, int *sock)
 {
 	struct sockaddr_in saddr;
 	struct io_uring_sqe *sqe;
-	int sockfd, ret;
+	int sockfd, ret, val;
 
 	memset(&saddr, 0, sizeof(saddr));
 	saddr.sin_family = AF_INET;
@@ -43,14 +43,24 @@
 		return 1;
 	}
 
+	val = 1;
+	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+
 	ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
 	if (ret < 0) {
 		perror("bind");
 		goto err;
 	}
 
+	ret = io_uring_register_files(ring, &sockfd, 1);
+	if (ret) {
+		fprintf(stderr, "file reg failed\n");
+		goto err;
+	}
+
 	sqe = io_uring_get_sqe(ring);
-	io_uring_prep_recv(sqe, sockfd, iov->iov_base, iov->iov_len, 0);
+	io_uring_prep_recv(sqe, 0, iov->iov_base, iov->iov_len, 0);
+	sqe->flags |= IOSQE_FIXED_FILE;
 	sqe->user_data = 2;
 
 	ret = io_uring_submit(ring);
@@ -59,6 +69,7 @@
 		goto err;
 	}
 
+	*sock = sockfd;
 	return 0;
 err:
 	close(sockfd);
@@ -95,33 +106,41 @@
 	return 1;
 }
 
+struct recv_data {
+	pthread_mutex_t mutex;
+	int use_sqthread;
+};
+
 static void *recv_fn(void *data)
 {
-	pthread_mutex_t *mutex = data;
+	struct recv_data *rd = data;
 	char buf[MAX_MSG + 1];
 	struct iovec iov = {
 		.iov_base = buf,
 		.iov_len = sizeof(buf) - 1,
 	};
+	struct io_uring_params p = { };
 	struct io_uring ring;
-	int ret;
+	int ret, sock;
 
-	ret = io_uring_queue_init(1, &ring, 0);
+	if (rd->use_sqthread)
+		p.flags = IORING_SETUP_SQPOLL;
+	ret = io_uring_queue_init_params(1, &ring, &p);
 	if (ret) {
 		fprintf(stderr, "queue init failed: %d\n", ret);
 		goto err;
 	}
 
-	ret = recv_prep(&ring, &iov);
+	ret = recv_prep(&ring, &iov, &sock);
 	if (ret) {
 		fprintf(stderr, "recv_prep failed: %d\n", ret);
 		goto err;
 	}
-	pthread_mutex_unlock(mutex);
+	pthread_mutex_unlock(&rd->mutex);
 	ret = do_recv(&ring, &iov);
 
+	close(sock);
 	io_uring_queue_exit(&ring);
-
 err:
 	return (void *)(intptr_t)ret;
 }
@@ -189,32 +208,55 @@
 	return 1;
 }
 
-int main(int argc, char *argv[])
+static int test(int use_sqthread)
 {
 	pthread_mutexattr_t attr;
 	pthread_t recv_thread;
-	pthread_mutex_t mutex;
+	struct recv_data rd;
 	int ret;
 	void *retval;
 
-	if (argc > 1)
-		return 0;
-
 	pthread_mutexattr_init(&attr);
 	pthread_mutexattr_setpshared(&attr, 1);
-	pthread_mutex_init(&mutex, &attr);
-	pthread_mutex_lock(&mutex);
+	pthread_mutex_init(&rd.mutex, &attr);
+	pthread_mutex_lock(&rd.mutex);
+	rd.use_sqthread = use_sqthread;
 
-	ret = pthread_create(&recv_thread, NULL, recv_fn, &mutex);
+	ret = pthread_create(&recv_thread, NULL, recv_fn, &rd);
 	if (ret) {
 		fprintf(stderr, "Thread create failed: %d\n", ret);
 		return 1;
 	}
 
-	pthread_mutex_lock(&mutex);
+	pthread_mutex_lock(&rd.mutex);
 	do_send();
 	pthread_join(recv_thread, &retval);
-	ret = (int)(intptr_t)retval;
+	return (int)(intptr_t)retval;
+}
 
-	return ret;
+int main(int argc, char *argv[])
+{
+	int ret;
+
+	if (argc > 1)
+		return 0;
+
+	ret = test(0);
+	if (ret) {
+		fprintf(stderr, "test sqthread=0 failed\n");
+		return ret;
+	}
+
+	if (geteuid()) {
+		fprintf(stdout, "%s: skipping SQPOLL variant\n", argv[0]);
+		return 0;
+	}
+
+	ret = test(1);
+	if (ret) {
+		fprintf(stderr, "test sqthread=1 failed\n");
+		return ret;
+	}
+
+	return 0;
 }