nop.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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_nop_inject(struct io_uring *ring, unsigned req_flags)
  17. {
  18. struct io_uring_cqe *cqe;
  19. struct io_uring_sqe *sqe;
  20. int ret;
  21. sqe = io_uring_get_sqe(ring);
  22. if (!sqe) {
  23. fprintf(stderr, "get sqe failed\n");
  24. goto err;
  25. }
  26. io_uring_prep_nop(sqe);
  27. sqe->user_data = ++seq;
  28. sqe->nop_flags = IORING_NOP_INJECT_RESULT;
  29. sqe->flags |= req_flags;
  30. sqe->len = -EFAULT;
  31. ret = io_uring_submit(ring);
  32. if (ret <= 0) {
  33. fprintf(stderr, "sqe submit failed: %d\n", ret);
  34. goto err;
  35. }
  36. ret = io_uring_wait_cqe(ring, &cqe);
  37. if (ret < 0) {
  38. fprintf(stderr, "wait completion %d\n", ret);
  39. goto err;
  40. }
  41. if (cqe->res != -EINVAL && cqe->res != -EFAULT) {
  42. fprintf(stderr, "expected injected result, got %d\n", cqe->res);
  43. goto err;
  44. }
  45. io_uring_cqe_seen(ring, cqe);
  46. return 0;
  47. err:
  48. return 1;
  49. }
  50. static int test_single_nop(struct io_uring *ring, unsigned req_flags)
  51. {
  52. struct io_uring_cqe *cqe;
  53. struct io_uring_sqe *sqe;
  54. int ret;
  55. bool cqe32 = (ring->flags & IORING_SETUP_CQE32);
  56. sqe = io_uring_get_sqe(ring);
  57. if (!sqe) {
  58. fprintf(stderr, "get sqe failed\n");
  59. goto err;
  60. }
  61. io_uring_prep_nop(sqe);
  62. sqe->user_data = ++seq;
  63. sqe->flags |= req_flags;
  64. ret = io_uring_submit(ring);
  65. if (ret <= 0) {
  66. fprintf(stderr, "sqe submit failed: %d\n", ret);
  67. goto err;
  68. }
  69. ret = io_uring_wait_cqe(ring, &cqe);
  70. if (ret < 0) {
  71. fprintf(stderr, "wait completion %d\n", ret);
  72. goto err;
  73. }
  74. if (!cqe->user_data) {
  75. fprintf(stderr, "Unexpected 0 user_data\n");
  76. goto err;
  77. }
  78. if (cqe32) {
  79. if (cqe->big_cqe[0] != 0) {
  80. fprintf(stderr, "Unexpected extra1\n");
  81. goto err;
  82. }
  83. if (cqe->big_cqe[1] != 0) {
  84. fprintf(stderr, "Unexpected extra2\n");
  85. goto err;
  86. }
  87. }
  88. io_uring_cqe_seen(ring, cqe);
  89. return 0;
  90. err:
  91. return 1;
  92. }
  93. static int test_barrier_nop(struct io_uring *ring, unsigned req_flags)
  94. {
  95. struct io_uring_cqe *cqe;
  96. struct io_uring_sqe *sqe;
  97. int ret, i;
  98. bool cqe32 = (ring->flags & IORING_SETUP_CQE32);
  99. for (i = 0; i < 8; i++) {
  100. sqe = io_uring_get_sqe(ring);
  101. if (!sqe) {
  102. fprintf(stderr, "get sqe failed\n");
  103. goto err;
  104. }
  105. io_uring_prep_nop(sqe);
  106. if (i == 4)
  107. sqe->flags = IOSQE_IO_DRAIN;
  108. sqe->user_data = ++seq;
  109. sqe->flags |= req_flags;
  110. }
  111. ret = io_uring_submit(ring);
  112. if (ret < 0) {
  113. fprintf(stderr, "sqe submit failed: %d\n", ret);
  114. goto err;
  115. } else if (ret < 8) {
  116. fprintf(stderr, "Submitted only %d\n", ret);
  117. goto err;
  118. }
  119. for (i = 0; i < 8; i++) {
  120. ret = io_uring_wait_cqe(ring, &cqe);
  121. if (ret < 0) {
  122. fprintf(stderr, "wait completion %d\n", ret);
  123. goto err;
  124. }
  125. if (!cqe->user_data) {
  126. fprintf(stderr, "Unexpected 0 user_data\n");
  127. goto err;
  128. }
  129. if (cqe32) {
  130. if (cqe->big_cqe[0] != 0) {
  131. fprintf(stderr, "Unexpected extra1\n");
  132. goto err;
  133. }
  134. if (cqe->big_cqe[1] != 0) {
  135. fprintf(stderr, "Unexpected extra2\n");
  136. goto err;
  137. }
  138. }
  139. io_uring_cqe_seen(ring, cqe);
  140. }
  141. return 0;
  142. err:
  143. return 1;
  144. }
  145. static int test_ring(unsigned flags)
  146. {
  147. struct io_uring ring;
  148. struct io_uring_params p = { };
  149. int ret, i;
  150. p.flags = flags;
  151. ret = io_uring_queue_init_params(8, &ring, &p);
  152. if (ret) {
  153. if (ret == -EINVAL)
  154. return 0;
  155. fprintf(stderr, "ring setup failed: %d\n", ret);
  156. return 1;
  157. }
  158. for (i = 0; i < 1000; i++) {
  159. unsigned req_flags = (i & 1) ? IOSQE_ASYNC : 0;
  160. ret = test_single_nop(&ring, req_flags);
  161. if (ret) {
  162. fprintf(stderr, "test_single_nop failed\n");
  163. goto err;
  164. }
  165. ret = test_barrier_nop(&ring, req_flags);
  166. if (ret) {
  167. fprintf(stderr, "test_barrier_nop failed\n");
  168. goto err;
  169. }
  170. ret = test_nop_inject(&ring, req_flags);
  171. if (ret) {
  172. fprintf(stderr, "test_nop_inject failed\n");
  173. goto err;
  174. }
  175. }
  176. err:
  177. io_uring_queue_exit(&ring);
  178. return ret;
  179. }
  180. int main(int argc, char *argv[])
  181. {
  182. int ret;
  183. if (argc > 1)
  184. return 0;
  185. FOR_ALL_TEST_CONFIGS {
  186. ret = test_ring(IORING_GET_TEST_CONFIG_FLAGS());
  187. if (ret) {
  188. fprintf(stderr, "Normal ring test failed: %s\n",
  189. IORING_GET_TEST_CONFIG_DESCRIPTION());
  190. return ret;
  191. }
  192. }
  193. return 0;
  194. }