From patchwork Mon Aug 15 13:09:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dylan Yudaken X-Patchwork-Id: 12943565 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90F8AC00140 for ; Mon, 15 Aug 2022 13:19:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229490AbiHONTi (ORCPT ); Mon, 15 Aug 2022 09:19:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54150 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242914AbiHONP0 (ORCPT ); Mon, 15 Aug 2022 09:15:26 -0400 Received: from mx0b-00082601.pphosted.com (mx0b-00082601.pphosted.com [67.231.153.30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 478A81BE for ; Mon, 15 Aug 2022 06:15:24 -0700 (PDT) Received: from pps.filterd (m0109331.ppops.net [127.0.0.1]) by mx0a-00082601.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 27FBOM8K005208 for ; Mon, 15 Aug 2022 06:15:23 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fb.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=facebook; bh=AQkts6nBI0t/kpJkui7v86zB/LQ2RJED5mJftQKpRjo=; b=PXEwVJ3H3QDPfkCBwnMxIGXVkCmbWGriGjiiJLE2Uj5Y9vVYKhk1LTr4M2/K4iUwzwsF SNPjzGJ7CRwgcjswKsn4mlZa2w0F+aXK+PlINDXXRTpLxBJPVdBX9cIJuqIHXv1l7Ixu BKl+LXAxHWukNZlLvqyG066g0DWe2V0HZBU= Received: from mail.thefacebook.com ([163.114.132.120]) by mx0a-00082601.pphosted.com (PPS) with ESMTPS id 3hyn83rfvu-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Mon, 15 Aug 2022 06:15:23 -0700 Received: from twshared14074.07.ash9.facebook.com (2620:10d:c085:208::f) by mail.thefacebook.com (2620:10d:c085:21d::4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.31; Mon, 15 Aug 2022 06:15:22 -0700 Received: by devbig038.lla2.facebook.com (Postfix, from userid 572232) id 1C48C49B72E5; Mon, 15 Aug 2022 06:09:55 -0700 (PDT) From: Dylan Yudaken To: Jens Axboe , Pavel Begunkov , CC: , Dylan Yudaken Subject: [PATCH liburing 04/11] update existing tests for defer taskrun Date: Mon, 15 Aug 2022 06:09:40 -0700 Message-ID: <20220815130947.1002152-5-dylany@fb.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220815130947.1002152-1-dylany@fb.com> References: <20220815130947.1002152-1-dylany@fb.com> MIME-Version: 1.0 X-FB-Internal: Safe X-Proofpoint-ORIG-GUID: Rrc-aJdvSf7PwZdTWmQci8P_efegRzeH X-Proofpoint-GUID: Rrc-aJdvSf7PwZdTWmQci8P_efegRzeH X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.122.1 definitions=2022-08-15_08,2022-08-15_01,2022-06-22_01 Precedence: bulk List-ID: X-Mailing-List: io-uring@vger.kernel.org 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 --- test/eventfd-disable.c | 32 ++++++++++++++++++++++--- test/iopoll.c | 16 +++++++++---- test/multicqes_drain.c | 49 +++++++++++++++++++++++++++++++++----- test/poll-mshot-overflow.c | 39 ++++++++++++++++++++++++++---- test/recv-multishot.c | 32 ++++++++++++++++--------- test/rsrc_tags.c | 10 ++++++-- 6 files changed, 147 insertions(+), 31 deletions(-) diff --git a/test/eventfd-disable.c b/test/eventfd-disable.c index 2c8cf6dad7c1..a8ecd6d0faee 100644 --- a/test/eventfd-disable.c +++ b/test/eventfd-disable.c @@ -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,8 @@ int main(int argc, char *argv[]) }; int ret, evfd, i; - if (argc > 1) - return T_EXIT_SKIP; + if (defer) + p.flags |= IORING_SETUP_DEFER_TASKRUN; ret = io_uring_queue_init_params(64, &ring, &p); if (ret) { @@ -148,5 +148,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; +} diff --git a/test/iopoll.c b/test/iopoll.c index 51b192f0a10e..32040d24bbda 100644 --- a/test/iopoll.c +++ b/test/iopoll.c @@ -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,9 @@ static int test_io(const char *file, int write, int sqthread, int fixed, if (no_iopoll) return 0; + if (defer) + ring_flags |= IORING_SETUP_DEFER_TASKRUN; + ret = t_create_ring(64, &ring, ring_flags); if (ret == T_SETUP_SKIP) return 0; @@ -337,19 +340,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) diff --git a/test/multicqes_drain.c b/test/multicqes_drain.c index 1423f9290ec7..c2bc2ae84672 100644 --- a/test/multicqes_drain.c +++ b/test/multicqes_drain.c @@ -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,16 @@ 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_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 +394,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; +} diff --git a/test/poll-mshot-overflow.c b/test/poll-mshot-overflow.c index 360df65d2b15..729f7751410b 100644 --- a/test/poll-mshot-overflow.c +++ b/test/poll-mshot-overflow.c @@ -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,9 @@ int main(int argc, char *argv[]) .cq_entries = 2 }; + if (defer_taskrun) + params.flags |= IORING_SETUP_DEFER_TASKRUN; + ret = io_uring_queue_init_params(2, &ring, ¶ms); if (ret) return T_EXIT_SKIP; @@ -113,6 +113,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 +129,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; } diff --git a/test/recv-multishot.c b/test/recv-multishot.c index a322e4317232..71664ba3c0fe 100644 --- a/test/recv-multishot.c +++ b/test/recv-multishot.c @@ -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,21 @@ 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_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 +460,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) diff --git a/test/rsrc_tags.c b/test/rsrc_tags.c index ca380d84a42f..b69223a54b12 100644 --- a/test/rsrc_tags.c +++ b/test/rsrc_tags.c @@ -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_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;