read-mshot-stdin.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: test multishot read on stdin. Not that this REQUIRES input
  5. * to be received on stdin, and hence if invoked with no
  6. * arguments, or without the single argument being 'stdin',
  7. * the test will just return SKIPPED. Can't be run from the
  8. * standard test harness, as it's interactive.
  9. *
  10. * To run, do run "test/read-mshot-stdin.t stdin" and then input text on
  11. * the console, followed by enter / line feed. If it works as it should,
  12. * it'll output the received CQE data. If an error is detected, it'll
  13. * abort with an error.
  14. */
  15. #include <errno.h>
  16. #include <stdio.h>
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <fcntl.h>
  21. #include <sys/stat.h>
  22. #include "liburing.h"
  23. #include "helpers.h"
  24. #define BUF_SIZE 32
  25. #define NR_BUFS 64
  26. #define BUF_BGID 1
  27. #define BR_MASK (NR_BUFS - 1)
  28. static int test_stdin(void)
  29. {
  30. struct io_uring_buf_ring *br;
  31. struct io_uring_params p = { };
  32. struct io_uring_sqe *sqe;
  33. struct io_uring_cqe *cqe;
  34. struct io_uring ring;
  35. int ret, i, last_bid;
  36. char *buf, *ptr;
  37. p.flags = IORING_SETUP_CQSIZE;
  38. p.cq_entries = NR_BUFS;
  39. ret = io_uring_queue_init_params(1, &ring, &p);
  40. if (ret) {
  41. if (ret == -EINVAL)
  42. return T_EXIT_SKIP;
  43. fprintf(stderr, "ring setup failed: %d\n", ret);
  44. return T_EXIT_FAIL;
  45. }
  46. if (posix_memalign((void **) &buf, 4096, NR_BUFS * BUF_SIZE))
  47. return T_EXIT_FAIL;
  48. br = io_uring_setup_buf_ring(&ring, NR_BUFS, BUF_BGID, 0, &ret);
  49. if (!br) {
  50. if (ret == -EINVAL)
  51. return T_EXIT_SKIP;
  52. fprintf(stderr, "Buffer ring register failed %d\n", ret);
  53. return T_EXIT_FAIL;
  54. }
  55. ptr = buf;
  56. for (i = 0; i < NR_BUFS; i++) {
  57. io_uring_buf_ring_add(br, ptr, BUF_SIZE, i + 1, BR_MASK, i);
  58. ptr += BUF_SIZE;
  59. }
  60. io_uring_buf_ring_advance(br, NR_BUFS);
  61. sqe = io_uring_get_sqe(&ring);
  62. io_uring_prep_read_multishot(sqe, STDIN_FILENO, 0, 0, BUF_BGID);
  63. ret = io_uring_submit(&ring);
  64. if (ret != 1) {
  65. fprintf(stderr, "submit: %d\n", ret);
  66. return T_EXIT_FAIL;
  67. }
  68. last_bid = -1;
  69. do {
  70. int bid;
  71. ret = io_uring_wait_cqe(&ring, &cqe);
  72. if (ret) {
  73. fprintf(stderr, "wait cqe failed %d\n", ret);
  74. return T_EXIT_FAIL;
  75. }
  76. if (cqe->res && !(cqe->flags & IORING_CQE_F_BUFFER)) {
  77. fprintf(stderr, "BUF flag not set %x\n", cqe->flags);
  78. return T_EXIT_FAIL;
  79. }
  80. bid = cqe->flags >> 16;
  81. printf("CQE res %d, bid %d, flags %x\n", cqe->res, bid, cqe->flags);
  82. if (cqe->res > 0 && last_bid != -1 && last_bid + 1 != bid) {
  83. fprintf(stderr, "Got bid %d, wanted %d\n", bid, last_bid + 1);
  84. return T_EXIT_FAIL;
  85. }
  86. if (!(cqe->flags & IORING_CQE_F_MORE)) {
  87. io_uring_cqe_seen(&ring, cqe);
  88. break;
  89. }
  90. last_bid = bid;
  91. io_uring_cqe_seen(&ring, cqe);
  92. }while (1);
  93. io_uring_free_buf_ring(&ring, br, NR_BUFS, BUF_BGID);
  94. io_uring_queue_exit(&ring);
  95. free(buf);
  96. return T_EXIT_PASS;
  97. }
  98. int main(int argc, char *argv[])
  99. {
  100. if (argc == 1)
  101. return T_EXIT_SKIP;
  102. else if (argc > 2)
  103. return T_EXIT_SKIP;
  104. if (!strcmp(argv[1], "stdin"))
  105. return test_stdin();
  106. return T_EXIT_SKIP;
  107. }