mirror of
https://github.com/openharmony/third_party_liburing.git
synced 2026-07-20 22:58:41 -04:00
update existing tests for defer taskrun
Add defer_taskrun to a few choice tests that can expose some bad behaviour. This requires adding some io_uring_get_events calls to make sure deferred tasks are run Signed-off-by: Dylan Yudaken <dylany@fb.com> Tested-by: Ammar Faizi <ammarfaizi2@gnuweeb.org> # Build Link: https://lore.kernel.org/r/20220905132258.1858915-6-dylany@fb.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
committed by
Jens Axboe
parent
014f46e794
commit
eaf8ff7ca9
+30
-3
@@ -15,7 +15,7 @@
|
||||
#include "liburing.h"
|
||||
#include "helpers.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
static int test(bool defer)
|
||||
{
|
||||
struct io_uring_params p = {};
|
||||
struct io_uring_sqe *sqe;
|
||||
@@ -28,8 +28,9 @@ int main(int argc, char *argv[])
|
||||
};
|
||||
int ret, evfd, i;
|
||||
|
||||
if (argc > 1)
|
||||
return T_EXIT_SKIP;
|
||||
if (defer)
|
||||
p.flags |= IORING_SETUP_SINGLE_ISSUER |
|
||||
IORING_SETUP_DEFER_TASKRUN;
|
||||
|
||||
ret = io_uring_queue_init_params(64, &ring, &p);
|
||||
if (ret) {
|
||||
@@ -148,5 +149,31 @@ int main(int argc, char *argv[])
|
||||
io_uring_cqe_seen(&ring, cqe);
|
||||
}
|
||||
|
||||
io_uring_queue_exit(&ring);
|
||||
close(evfd);
|
||||
return T_EXIT_PASS;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (argc > 1)
|
||||
return T_EXIT_SKIP;
|
||||
|
||||
ret = test(false);
|
||||
if (ret != T_EXIT_PASS) {
|
||||
fprintf(stderr, "%s: test(false) failed\n", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (t_probe_defer_taskrun()) {
|
||||
ret = test(true);
|
||||
if (ret != T_EXIT_PASS) {
|
||||
fprintf(stderr, "%s: test(true) failed\n", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+12
-5
@@ -274,7 +274,7 @@ ok:
|
||||
}
|
||||
|
||||
static int test_io(const char *file, int write, int sqthread, int fixed,
|
||||
int buf_select)
|
||||
int buf_select, int defer)
|
||||
{
|
||||
struct io_uring ring;
|
||||
int ret, ring_flags = IORING_SETUP_IOPOLL;
|
||||
@@ -282,6 +282,10 @@ static int test_io(const char *file, int write, int sqthread, int fixed,
|
||||
if (no_iopoll)
|
||||
return 0;
|
||||
|
||||
if (defer)
|
||||
ring_flags |= IORING_SETUP_SINGLE_ISSUER |
|
||||
IORING_SETUP_DEFER_TASKRUN;
|
||||
|
||||
ret = t_create_ring(64, &ring, ring_flags);
|
||||
if (ret == T_SETUP_SKIP)
|
||||
return 0;
|
||||
@@ -337,19 +341,22 @@ int main(int argc, char *argv[])
|
||||
|
||||
vecs = t_create_buffers(BUFFERS, BS);
|
||||
|
||||
nr = 16;
|
||||
nr = 32;
|
||||
if (no_buf_select)
|
||||
nr = 8;
|
||||
else if (!t_probe_defer_taskrun())
|
||||
nr = 16;
|
||||
for (i = 0; i < nr; i++) {
|
||||
int write = (i & 1) != 0;
|
||||
int sqthread = (i & 2) != 0;
|
||||
int fixed = (i & 4) != 0;
|
||||
int buf_select = (i & 8) != 0;
|
||||
int defer = (i & 16) != 0;
|
||||
|
||||
ret = test_io(fname, write, sqthread, fixed, buf_select);
|
||||
ret = test_io(fname, write, sqthread, fixed, buf_select, defer);
|
||||
if (ret) {
|
||||
fprintf(stderr, "test_io failed %d/%d/%d/%d\n",
|
||||
write, sqthread, fixed, buf_select);
|
||||
fprintf(stderr, "test_io failed %d/%d/%d/%d/%d\n",
|
||||
write, sqthread, fixed, buf_select, defer);
|
||||
goto err;
|
||||
}
|
||||
if (no_iopoll)
|
||||
|
||||
+44
-6
@@ -233,6 +233,8 @@ static int test_generic_drain(struct io_uring *ring)
|
||||
|
||||
if (trigger_event(pipes[i]))
|
||||
goto err;
|
||||
|
||||
io_uring_get_events(ring);
|
||||
}
|
||||
sleep(1);
|
||||
i = 0;
|
||||
@@ -246,7 +248,7 @@ static int test_generic_drain(struct io_uring *ring)
|
||||
* compl_bits is a bit map to record completions.
|
||||
* eg. sqe[0], sqe[1], sqe[2] fully completed
|
||||
* then compl_bits is 000...00111b
|
||||
*
|
||||
*
|
||||
*/
|
||||
unsigned long long compl_bits = 0;
|
||||
for (j = 0; j < i; j++) {
|
||||
@@ -295,7 +297,12 @@ static int test_simple_drain(struct io_uring *ring)
|
||||
io_uring_prep_poll_add(sqe[1], pipe2[0], POLLIN);
|
||||
sqe[1]->user_data = 1;
|
||||
|
||||
ret = io_uring_submit(ring);
|
||||
/* This test relies on multishot poll to trigger events continually.
|
||||
* however with IORING_SETUP_DEFER_TASKRUN this will only happen when
|
||||
* triggered with a get_events. Hence we sprinkle get_events whenever
|
||||
* there might be work to process in order to get the same result
|
||||
*/
|
||||
ret = io_uring_submit_and_get_events(ring);
|
||||
if (ret < 0) {
|
||||
printf("sqe submit failed\n");
|
||||
goto err;
|
||||
@@ -307,9 +314,11 @@ static int test_simple_drain(struct io_uring *ring)
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (trigger_event(pipe1))
|
||||
goto err;
|
||||
io_uring_get_events(ring);
|
||||
}
|
||||
if (trigger_event(pipe2))
|
||||
goto err;
|
||||
io_uring_get_events(ring);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
sqe[i] = io_uring_get_sqe(ring);
|
||||
@@ -355,15 +364,17 @@ err:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
static int test(bool defer_taskrun)
|
||||
{
|
||||
struct io_uring ring;
|
||||
int i, ret;
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (argc > 1)
|
||||
return T_EXIT_SKIP;
|
||||
if (defer_taskrun)
|
||||
flags = IORING_SETUP_SINGLE_ISSUER |
|
||||
IORING_SETUP_DEFER_TASKRUN;
|
||||
|
||||
ret = io_uring_queue_init(1024, &ring, 0);
|
||||
ret = io_uring_queue_init(1024, &ring, flags);
|
||||
if (ret) {
|
||||
printf("ring setup failed\n");
|
||||
return T_EXIT_FAIL;
|
||||
@@ -384,5 +395,32 @@ int main(int argc, char *argv[])
|
||||
return T_EXIT_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
io_uring_queue_exit(&ring);
|
||||
|
||||
return T_EXIT_PASS;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (argc > 1)
|
||||
return T_EXIT_SKIP;
|
||||
|
||||
ret = test(false);
|
||||
if (ret != T_EXIT_PASS) {
|
||||
fprintf(stderr, "%s: test(false) failed\n", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (t_probe_defer_taskrun()) {
|
||||
ret = test(true);
|
||||
if (ret != T_EXIT_PASS) {
|
||||
fprintf(stderr, "%s: test(true) failed\n", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ int check_final_cqe(struct io_uring *ring)
|
||||
return T_EXIT_PASS;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
static int test(bool defer_taskrun)
|
||||
{
|
||||
struct io_uring_cqe *cqe;
|
||||
struct io_uring_sqe *sqe;
|
||||
@@ -50,9 +50,6 @@ int main(int argc, char *argv[])
|
||||
int pipe1[2];
|
||||
int ret, i;
|
||||
|
||||
if (argc > 1)
|
||||
return 0;
|
||||
|
||||
if (pipe(pipe1) != 0) {
|
||||
perror("pipe");
|
||||
return T_EXIT_FAIL;
|
||||
@@ -66,6 +63,10 @@ int main(int argc, char *argv[])
|
||||
.cq_entries = 2
|
||||
};
|
||||
|
||||
if (defer_taskrun)
|
||||
params.flags |= IORING_SETUP_SINGLE_ISSUER |
|
||||
IORING_SETUP_DEFER_TASKRUN;
|
||||
|
||||
ret = io_uring_queue_init_params(2, &ring, ¶ms);
|
||||
if (ret)
|
||||
return T_EXIT_SKIP;
|
||||
@@ -113,6 +114,9 @@ int main(int argc, char *argv[])
|
||||
io_uring_cqe_seen(&ring, cqe);
|
||||
}
|
||||
|
||||
/* make sure everything is processed */
|
||||
io_uring_get_events(&ring);
|
||||
|
||||
/* now remove the poll */
|
||||
sqe = io_uring_get_sqe(&ring);
|
||||
io_uring_prep_poll_remove(sqe, 1);
|
||||
@@ -126,5 +130,33 @@ int main(int argc, char *argv[])
|
||||
|
||||
ret = check_final_cqe(&ring);
|
||||
|
||||
close(pipe1[0]);
|
||||
close(pipe1[1]);
|
||||
io_uring_queue_exit(&ring);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (argc > 1)
|
||||
return T_EXIT_SKIP;
|
||||
|
||||
ret = test(false);
|
||||
if (ret != T_EXIT_PASS) {
|
||||
fprintf(stderr, "%s: test(false) failed\n", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (t_probe_defer_taskrun()) {
|
||||
ret = test(true);
|
||||
if (ret != T_EXIT_PASS) {
|
||||
fprintf(stderr, "%s: test(true) failed\n", argv[0]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+22
-11
@@ -29,6 +29,7 @@ struct args {
|
||||
bool wait_each;
|
||||
bool recvmsg;
|
||||
enum early_error_t early_error;
|
||||
bool defer;
|
||||
};
|
||||
|
||||
static int check_sockaddr(struct sockaddr_in *in)
|
||||
@@ -76,19 +77,22 @@ static int test(struct args *args)
|
||||
.tv_sec = 1,
|
||||
};
|
||||
struct msghdr msg;
|
||||
struct io_uring_params params = { };
|
||||
int n_sqe = 32;
|
||||
|
||||
memset(recv_buffs, 0, sizeof(recv_buffs));
|
||||
|
||||
if (args->early_error == ERROR_EARLY_OVERFLOW) {
|
||||
struct io_uring_params params = {
|
||||
.flags = IORING_SETUP_CQSIZE,
|
||||
.cq_entries = N_CQE_OVERFLOW
|
||||
};
|
||||
if (args->defer)
|
||||
params.flags |= IORING_SETUP_SINGLE_ISSUER |
|
||||
IORING_SETUP_DEFER_TASKRUN;
|
||||
|
||||
ret = io_uring_queue_init_params(N_CQE_OVERFLOW, &ring, ¶ms);
|
||||
} else {
|
||||
ret = io_uring_queue_init(32, &ring, 0);
|
||||
if (args->early_error == ERROR_EARLY_OVERFLOW) {
|
||||
params.flags |= IORING_SETUP_CQSIZE;
|
||||
params.cq_entries = N_CQE_OVERFLOW;
|
||||
n_sqe = N_CQE_OVERFLOW;
|
||||
}
|
||||
|
||||
ret = io_uring_queue_init_params(n_sqe, &ring, ¶ms);
|
||||
if (ret) {
|
||||
fprintf(stderr, "queue init failed: %d\n", ret);
|
||||
return ret;
|
||||
@@ -457,23 +461,30 @@ int main(int argc, char *argv[])
|
||||
int ret;
|
||||
int loop;
|
||||
int early_error = 0;
|
||||
bool has_defer;
|
||||
|
||||
if (argc > 1)
|
||||
return T_EXIT_SKIP;
|
||||
|
||||
for (loop = 0; loop < 8; loop++) {
|
||||
has_defer = t_probe_defer_taskrun();
|
||||
|
||||
for (loop = 0; loop < 16; loop++) {
|
||||
struct args a = {
|
||||
.stream = loop & 0x01,
|
||||
.wait_each = loop & 0x2,
|
||||
.recvmsg = loop & 0x04,
|
||||
.defer = loop & 0x08,
|
||||
};
|
||||
if (a.defer && !has_defer)
|
||||
continue;
|
||||
for (early_error = 0; early_error < ERROR_EARLY_LAST; early_error++) {
|
||||
a.early_error = (enum early_error_t)early_error;
|
||||
ret = test(&a);
|
||||
if (ret) {
|
||||
fprintf(stderr,
|
||||
"test stream=%d wait_each=%d recvmsg=%d early_error=%d failed\n",
|
||||
a.stream, a.wait_each, a.recvmsg, a.early_error);
|
||||
"test stream=%d wait_each=%d recvmsg=%d early_error=%d "
|
||||
" defer=%d failed\n",
|
||||
a.stream, a.wait_each, a.recvmsg, a.early_error, a.defer);
|
||||
return T_EXIT_FAIL;
|
||||
}
|
||||
if (no_recv_mshot)
|
||||
|
||||
+8
-2
@@ -401,7 +401,8 @@ static int test_notag(void)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ring_flags[] = {0, IORING_SETUP_IOPOLL, IORING_SETUP_SQPOLL};
|
||||
int ring_flags[] = {0, IORING_SETUP_IOPOLL, IORING_SETUP_SQPOLL,
|
||||
IORING_SETUP_SINGLE_ISSUER | IORING_SETUP_DEFER_TASKRUN};
|
||||
int i, ret;
|
||||
|
||||
if (argc > 1)
|
||||
@@ -423,7 +424,12 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(ring_flags) / sizeof(ring_flags[0]); i++) {
|
||||
ret = test_files(ring_flags[i]);
|
||||
int flag = ring_flags[i];
|
||||
|
||||
if (flag & IORING_SETUP_DEFER_TASKRUN && !t_probe_defer_taskrun())
|
||||
continue;
|
||||
|
||||
ret = test_files(flag);
|
||||
if (ret) {
|
||||
printf("test_tag failed, type %i\n", i);
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user