sq-poll-share.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: test SQPOLL with IORING_SETUP_ATTACH_WQ
  5. */
  6. #include <errno.h>
  7. #include <stdio.h>
  8. #include <unistd.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <fcntl.h>
  12. #include <sys/types.h>
  13. #include <poll.h>
  14. #include <sys/eventfd.h>
  15. #include <sys/resource.h>
  16. #include "helpers.h"
  17. #include "liburing.h"
  18. #define FILE_SIZE (128 * 1024 * 1024)
  19. #define BS 4096
  20. #define BUFFERS 64
  21. #define NR_RINGS 4
  22. static struct iovec *vecs;
  23. static int wait_io(struct io_uring *ring, int nr_ios)
  24. {
  25. struct io_uring_cqe *cqe;
  26. while (nr_ios) {
  27. int ret = io_uring_wait_cqe(ring, &cqe);
  28. if (ret == -EAGAIN) {
  29. continue;
  30. } else if (ret) {
  31. fprintf(stderr, "io_uring_wait_cqe failed %i\n", ret);
  32. return 1;
  33. }
  34. if (cqe->res != BS) {
  35. fprintf(stderr, "Unexpected ret %d\n", cqe->res);
  36. return 1;
  37. }
  38. io_uring_cqe_seen(ring, cqe);
  39. nr_ios--;
  40. }
  41. return 0;
  42. }
  43. static int queue_io(struct io_uring *ring, int fd, int nr_ios)
  44. {
  45. unsigned long off;
  46. int i;
  47. i = 0;
  48. off = 0;
  49. while (nr_ios) {
  50. struct io_uring_sqe *sqe;
  51. sqe = io_uring_get_sqe(ring);
  52. if (!sqe)
  53. break;
  54. io_uring_prep_read(sqe, fd, vecs[i].iov_base, vecs[i].iov_len, off);
  55. nr_ios--;
  56. i++;
  57. off += BS;
  58. }
  59. io_uring_submit(ring);
  60. return i;
  61. }
  62. int main(int argc, char *argv[])
  63. {
  64. struct io_uring rings[NR_RINGS];
  65. int rets[NR_RINGS];
  66. unsigned long ios;
  67. int i, ret, fd;
  68. char *fname;
  69. if (argc > 1) {
  70. fname = argv[1];
  71. } else {
  72. fname = ".basic-rw-poll-share";
  73. t_create_file(fname, FILE_SIZE);
  74. }
  75. vecs = t_create_buffers(BUFFERS, BS);
  76. fd = open(fname, O_RDONLY | O_DIRECT);
  77. if (fd < 0) {
  78. perror("open");
  79. return -1;
  80. }
  81. if (fname != argv[1])
  82. unlink(fname);
  83. for (i = 0; i < NR_RINGS; i++) {
  84. struct io_uring_params p = { };
  85. p.flags = IORING_SETUP_SQPOLL;
  86. if (i) {
  87. p.wq_fd = rings[0].ring_fd;
  88. p.flags |= IORING_SETUP_ATTACH_WQ;
  89. }
  90. ret = io_uring_queue_init_params(BUFFERS, &rings[i], &p);
  91. if (ret) {
  92. fprintf(stderr, "queue_init: %d/%d\n", ret, i);
  93. goto err;
  94. }
  95. /* no sharing for non-fixed either */
  96. if (!(p.features & IORING_FEAT_SQPOLL_NONFIXED)) {
  97. fprintf(stdout, "No SQPOLL sharing, skipping\n");
  98. return 0;
  99. }
  100. }
  101. ios = 0;
  102. while (ios < (FILE_SIZE / BS)) {
  103. for (i = 0; i < NR_RINGS; i++) {
  104. ret = queue_io(&rings[i], fd, BUFFERS);
  105. if (ret < 0)
  106. goto err;
  107. rets[i] = ret;
  108. }
  109. for (i = 0; i < NR_RINGS; i++) {
  110. if (wait_io(&rings[i], rets[i]))
  111. goto err;
  112. }
  113. ios += BUFFERS;
  114. }
  115. return 0;
  116. err:
  117. return 1;
  118. }