2828
2929#define NR_RDS 4
3030
31+ static bool no_iter_support ;
3132static bool no_limit_support ;
3233
3334static int use_port = PORT ;
@@ -48,6 +49,7 @@ struct recv_data {
4849 int total_bytes ;
4950
5051 int recv_bundle ;
52+ int mshot_limit ;
5153
5254 int use_port ;
5355 int id ;
@@ -64,13 +66,11 @@ static void arm_recv(struct io_uring *ring, struct recv_data *rd)
6466 struct io_uring_sqe * sqe ;
6567 int len = PER_ITER_LIMIT ;
6668
67- if (rd -> total_bytes && rd -> bytes_since_arm > PER_MSHOT_LIMIT )
68- rd -> mshot_too_big ++ ;
69-
7069 rd -> bytes_since_arm = 0 ;
7170 sqe = io_uring_get_sqe (ring );
7271 io_uring_prep_recv_multishot (sqe , rd -> accept_fd , NULL , len , 0 );
73- sqe -> optlen = PER_MSHOT_LIMIT ;
72+ if (rd -> mshot_limit )
73+ sqe -> optlen = PER_MSHOT_LIMIT ;
7474 if (rd -> recv_bundle )
7575 sqe -> ioprio |= IORING_RECVSEND_BUNDLE ;
7676 sqe -> buf_group = RECV_BGID ;
@@ -224,6 +224,8 @@ static int do_recv(struct io_uring *ring)
224224 done ++ ;
225225 continue ;
226226 }
227+ if (rd -> mshot_limit && rd -> bytes_since_arm > PER_MSHOT_LIMIT )
228+ rd -> mshot_too_big ++ ;
227229 io_uring_cqe_seen (ring , cqe );
228230 if (!(cqe -> flags & IORING_CQE_F_MORE ) && rd -> recv_bytes ) {
229231 arm_recv (ring , rd );
@@ -260,7 +262,7 @@ static void *recv_fn(void *data)
260262 ret = io_uring_queue_init_params (16 , & ring , & p );
261263 if (ret ) {
262264 if (ret == - EINVAL ) {
263- no_limit_support = true;
265+ no_iter_support = true;
264266 goto skip ;
265267 }
266268 fprintf (stderr , "ring init: %d\n" , ret );
@@ -275,7 +277,7 @@ static void *recv_fn(void *data)
275277 br = io_uring_setup_buf_ring (& ring , RECV_BIDS , RECV_BGID , brflags , & ret );
276278 if (!br ) {
277279 if (ret == - EINVAL ) {
278- no_limit_support = true;
280+ no_iter_support = true;
279281 goto skip ;
280282 }
281283 fprintf (stderr , "failed setting up recv ring %d\n" , ret );
@@ -304,7 +306,10 @@ static void *recv_fn(void *data)
304306
305307 if (!io_uring_peek_cqe (& ring , & cqe )) {
306308 if (cqe -> res == - EINVAL ) {
307- no_limit_support = true;
309+ if (rds [0 ].mshot_limit )
310+ no_limit_support = true;
311+ else
312+ no_iter_support = true;
308313 goto skip ;
309314 }
310315 }
@@ -384,7 +389,8 @@ struct res {
384389 int unfair ;
385390};
386391
387- static int test (int nr_send , int bundle , unsigned int queue_flags , struct res * r )
392+ static int test (int nr_send , int bundle , int mshot_limit ,
393+ unsigned int queue_flags , struct res * r )
388394{
389395 struct recv_data rds [NR_RDS ] = { };
390396 pthread_t recv_thread ;
@@ -406,6 +412,7 @@ static int test(int nr_send, int bundle, unsigned int queue_flags, struct res *r
406412 rd -> max_sends = nr_send ;
407413 rd -> recv_bundle = bundle ;
408414 rd -> recv_bytes = nr_send * 4096 ;
415+ rd -> mshot_limit = mshot_limit ;
409416 rd -> id = i + 1 ;
410417 }
411418
@@ -440,9 +447,9 @@ static int run_tests(void)
440447 struct res r ;
441448 int ret ;
442449
443- ret = test (2 , 1 , IORING_SETUP_DEFER_TASKRUN | IORING_SETUP_SINGLE_ISSUER , & r );
450+ ret = test (2 , 1 , 0 , IORING_SETUP_DEFER_TASKRUN | IORING_SETUP_SINGLE_ISSUER , & r );
444451 if (ret ) {
445- if (no_limit_support )
452+ if (no_iter_support )
446453 return T_EXIT_SKIP ;
447454 fprintf (stderr , "test DEFER bundle failed\n" );
448455 return T_EXIT_FAIL ;
@@ -454,7 +461,7 @@ static int run_tests(void)
454461 return T_EXIT_FAIL ;
455462 }
456463
457- ret = test (2 , 0 , IORING_SETUP_DEFER_TASKRUN | IORING_SETUP_SINGLE_ISSUER , & r );
464+ ret = test (2 , 0 , 0 , IORING_SETUP_DEFER_TASKRUN | IORING_SETUP_SINGLE_ISSUER , & r );
458465 if (ret ) {
459466 fprintf (stderr , "test DEFER failed\n" );
460467 return T_EXIT_FAIL ;
@@ -465,18 +472,18 @@ static int run_tests(void)
465472 return T_EXIT_FAIL ;
466473 }
467474
468- ret = test (2 , 1 , IORING_SETUP_COOP_TASKRUN , & r );
475+ ret = test (2 , 1 , 0 , IORING_SETUP_COOP_TASKRUN , & r );
469476 if (ret ) {
470477 fprintf (stderr , "test COOP bundle failed\n" );
471478 return T_EXIT_FAIL ;
472479 }
473480
474481 if (r .unfair || r .mshot_too_big ) {
475- fprintf (stderr , "!DEFER bundle too_big=%d\n" , r .mshot_too_big );
482+ fprintf (stderr , "COOP bundle too_big=%d\n" , r .mshot_too_big );
476483 return T_EXIT_FAIL ;
477484 }
478485
479- ret = test (2 , 0 , IORING_SETUP_COOP_TASKRUN , & r );
486+ ret = test (2 , 0 , 0 , IORING_SETUP_COOP_TASKRUN , & r );
480487 if (ret ) {
481488 fprintf (stderr , "test COOP failed\n" );
482489 return T_EXIT_FAIL ;
@@ -486,7 +493,54 @@ static int run_tests(void)
486493 fprintf (stderr , "!DEFER too_big=%d\n" , r .mshot_too_big );
487494 return T_EXIT_FAIL ;
488495 }
489-
496+
497+ ret = test (2 , 1 , 1 , IORING_SETUP_DEFER_TASKRUN | IORING_SETUP_SINGLE_ISSUER , & r );
498+ if (ret ) {
499+ if (no_limit_support )
500+ return T_EXIT_PASS ;
501+ fprintf (stderr , "test DEFER bundle cap failed\n" );
502+ return T_EXIT_FAIL ;
503+ }
504+
505+ /* DEFER_TASKRUN should be fully fair and not have overshoots */
506+ if (r .unfair || r .mshot_too_big ) {
507+ fprintf (stderr , "DEFER bundle cap unfair=%d, too_big=%d\n" , r .unfair , r .mshot_too_big );
508+ return T_EXIT_FAIL ;
509+ }
510+
511+ ret = test (2 , 0 , 1 , IORING_SETUP_DEFER_TASKRUN | IORING_SETUP_SINGLE_ISSUER , & r );
512+ if (ret ) {
513+ fprintf (stderr , "test DEFER cap failed\n" );
514+ return T_EXIT_FAIL ;
515+ }
516+
517+ if (r .unfair || r .mshot_too_big ) {
518+ fprintf (stderr , "DEFER cap unfair=%d, too_big=%d\n" , r .unfair , r .mshot_too_big );
519+ return T_EXIT_FAIL ;
520+ }
521+
522+ ret = test (2 , 1 , 1 , IORING_SETUP_COOP_TASKRUN , & r );
523+ if (ret ) {
524+ fprintf (stderr , "test COOP bundle cap failed\n" );
525+ return T_EXIT_FAIL ;
526+ }
527+
528+ if (r .unfair || r .mshot_too_big ) {
529+ fprintf (stderr , "COOP bundle cap too_big=%d\n" , r .mshot_too_big );
530+ return T_EXIT_FAIL ;
531+ }
532+
533+ ret = test (2 , 0 , 1 , IORING_SETUP_COOP_TASKRUN , & r );
534+ if (ret ) {
535+ fprintf (stderr , "test COOP cap failed\n" );
536+ return T_EXIT_FAIL ;
537+ }
538+
539+ if (r .unfair || r .mshot_too_big ) {
540+ fprintf (stderr , "COOP cap too_big=%d\n" , r .mshot_too_big );
541+ return T_EXIT_FAIL ;
542+ }
543+
490544 return T_EXIT_PASS ;
491545}
492546
0 commit comments