nop.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: run various nop tests
  5. *
  6. */
  7. #include <errno.h>
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <fcntl.h>
  13. #include "liburing.h"
  14. #include "test.h"
  15. static int seq;
  16. static int test_single_nop(struct io_uring *ring, unsigned req_flags)
  17. {
  18. struct io_uring_cqe *cqe;
  19. struct io_uring_sqe *sqe;
  20. int ret;
  21. bool cqe32 = (ring->flags & IORING_SETUP_CQE32);
  22. sqe = io_uring_get_sqe(ring);
  23. if (!sqe) {
  24. fprintf(stderr, "get sqe failed\n");
  25. goto err;
  26. }
  27. io_uring_prep_nop(sqe);
  28. sqe->user_data = ++seq;
  29. sqe->flags |= req_flags;
  30. ret = io_uring_submit(ring);
  31. if (ret <= 0) {
  32. fprintf(stderr, "sqe submit failed: %d\n", ret);
  33. goto err;
  34. }
  35. ret = io_uring_wait_cqe(ring, &cqe);
  36. if (ret < 0) {
  37. fprintf(stderr, "wait completion %d\n", ret);
  38. goto err;
  39. }
  40. if (!cqe->user_data) {
  41. fprintf(stderr, "Unexpected 0 user_data\n");
  42. goto err;
  43. }
  44. if (cqe32) {
  45. if (cqe->big_cqe[0] != 0) {
  46. fprintf(stderr, "Unexpected extra1\n");
  47. goto err;
  48. }
  49. if (cqe->big_cqe[1] != 0) {
  50. fprintf(stderr, "Unexpected extra2\n");
  51. goto err;
  52. }
  53. }
  54. io_uring_cqe_seen(ring, cqe);
  55. return 0;
  56. err:
  57. return 1;
  58. }
  59. static int test_barrier_nop(struct io_uring *ring, unsigned req_flags)
  60. {
  61. struct io_uring_cqe *cqe;
  62. struct io_uring_sqe *sqe;
  63. int ret, i;
  64. bool cqe32 = (ring->flags & IORING_SETUP_CQE32);
  65. for (i = 0; i < 8; i++) {
  66. sqe = io_uring_get_sqe(ring);
  67. if (!sqe) {
  68. fprintf(stderr, "get sqe failed\n");
  69. goto err;
  70. }
  71. io_uring_prep_nop(sqe);
  72. if (i == 4)
  73. sqe->flags = IOSQE_IO_DRAIN;
  74. sqe->user_data = ++seq;
  75. sqe->flags |= req_flags;
  76. }
  77. ret = io_uring_submit(ring);
  78. if (ret < 0) {
  79. fprintf(stderr, "sqe submit failed: %d\n", ret);
  80. goto err;
  81. } else if (ret < 8) {
  82. fprintf(stderr, "Submitted only %d\n", ret);
  83. goto err;
  84. }
  85. for (i = 0; i < 8; i++) {
  86. ret = io_uring_wait_cqe(ring, &cqe);
  87. if (ret < 0) {
  88. fprintf(stderr, "wait completion %d\n", ret);
  89. goto err;
  90. }
  91. if (!cqe->user_data) {
  92. fprintf(stderr, "Unexpected 0 user_data\n");
  93. goto err;
  94. }
  95. if (cqe32) {
  96. if (cqe->big_cqe[0] != 0) {
  97. fprintf(stderr, "Unexpected extra1\n");
  98. goto err;
  99. }
  100. if (cqe->big_cqe[1] != 0) {
  101. fprintf(stderr, "Unexpected extra2\n");
  102. goto err;
  103. }
  104. }
  105. io_uring_cqe_seen(ring, cqe);
  106. }
  107. return 0;
  108. err:
  109. return 1;
  110. }
  111. static int test_ring(unsigned flags)
  112. {
  113. struct io_uring ring;
  114. struct io_uring_params p = { };
  115. int ret, i;
  116. p.flags = flags;
  117. ret = io_uring_queue_init_params(8, &ring, &p);
  118. if (ret) {
  119. if (ret == -EINVAL)
  120. return 0;
  121. fprintf(stderr, "ring setup failed: %d\n", ret);
  122. return 1;
  123. }
  124. for (i = 0; i < 1000; i++) {
  125. unsigned req_flags = (i & 1) ? IOSQE_ASYNC : 0;
  126. ret = test_single_nop(&ring, req_flags);
  127. if (ret) {
  128. fprintf(stderr, "test_single_nop failed\n");
  129. goto err;
  130. }
  131. ret = test_barrier_nop(&ring, req_flags);
  132. if (ret) {
  133. fprintf(stderr, "test_barrier_nop failed\n");
  134. goto err;
  135. }
  136. }
  137. err:
  138. io_uring_queue_exit(&ring);
  139. return ret;
  140. }
  141. int main(int argc, char *argv[])
  142. {
  143. int ret;
  144. if (argc > 1)
  145. return 0;
  146. FOR_ALL_TEST_CONFIGS {
  147. ret = test_ring(IORING_GET_TEST_CONFIG_FLAGS());
  148. if (ret) {
  149. fprintf(stderr, "Normal ring test failed: %s\n",
  150. IORING_GET_TEST_CONFIG_DESCRIPTION());
  151. return ret;
  152. }
  153. }
  154. return 0;
  155. }