open-direct-link.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: link <open file><read from file><close file>
  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 "helpers.h"
  15. #define MAX_FILES 8
  16. #define FNAME ".link.direct"
  17. static int test(struct io_uring *ring, int skip_success, int drain, int async)
  18. {
  19. struct io_uring_cqe *cqe;
  20. struct io_uring_sqe *sqe;
  21. char buf[4096];
  22. int ret, i;
  23. /* drain and cqe skip are mutually exclusive */
  24. if (skip_success && drain)
  25. return 1;
  26. sqe = io_uring_get_sqe(ring);
  27. io_uring_prep_openat_direct(sqe, AT_FDCWD, FNAME, O_RDONLY, 0, 0);
  28. if (!drain)
  29. sqe->flags |= IOSQE_IO_LINK;
  30. if (skip_success)
  31. sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
  32. if (async)
  33. sqe->flags |= IOSQE_ASYNC;
  34. sqe->user_data = 1;
  35. sqe = io_uring_get_sqe(ring);
  36. io_uring_prep_read(sqe, 0, buf, sizeof(buf), 0);
  37. sqe->flags |= IOSQE_FIXED_FILE;
  38. if (drain)
  39. sqe->flags |= IOSQE_IO_DRAIN;
  40. else
  41. sqe->flags |= IOSQE_IO_LINK;
  42. if (async)
  43. sqe->flags |= IOSQE_ASYNC;
  44. sqe->user_data = 2;
  45. sqe = io_uring_get_sqe(ring);
  46. io_uring_prep_close_direct(sqe, 0);
  47. sqe->user_data = 3;
  48. if (skip_success)
  49. sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
  50. if (drain)
  51. sqe->flags |= IOSQE_IO_DRAIN;
  52. if (async)
  53. sqe->flags |= IOSQE_ASYNC;
  54. ret = io_uring_submit(ring);
  55. if (ret != 3) {
  56. fprintf(stderr, "sqe submit failed: %d\n", ret);
  57. goto err;
  58. }
  59. if (skip_success) {
  60. ret = io_uring_wait_cqe(ring, &cqe);
  61. if (ret < 0) {
  62. fprintf(stderr, "wait completion %d\n", ret);
  63. goto err;
  64. }
  65. if (cqe->user_data != 2) {
  66. fprintf(stderr, "Unexpected cqe %lu/%d\n",
  67. (unsigned long) cqe->user_data,
  68. cqe->res);
  69. goto err;
  70. }
  71. if (cqe->res != sizeof(buf)) {
  72. fprintf(stderr, "bad read %d\n", cqe->res);
  73. goto err;
  74. }
  75. io_uring_cqe_seen(ring, cqe);
  76. return 0;
  77. }
  78. for (i = 0; i < 3; i++) {
  79. ret = io_uring_wait_cqe(ring, &cqe);
  80. if (ret < 0) {
  81. fprintf(stderr, "wait completion %d\n", ret);
  82. goto err;
  83. }
  84. switch (cqe->user_data) {
  85. case 1:
  86. if (cqe->res) {
  87. fprintf(stderr, "bad open %d\n", cqe->res);
  88. goto err;
  89. }
  90. break;
  91. case 2:
  92. if (cqe->res != sizeof(buf)) {
  93. fprintf(stderr, "bad read %d\n", cqe->res);
  94. goto err;
  95. }
  96. break;
  97. case 3:
  98. if (cqe->res) {
  99. fprintf(stderr, "bad close %d\n", cqe->res);
  100. goto err;
  101. }
  102. break;
  103. }
  104. io_uring_cqe_seen(ring, cqe);
  105. }
  106. return 0;
  107. err:
  108. return 1;
  109. }
  110. int main(int argc, char *argv[])
  111. {
  112. struct io_uring ring;
  113. struct io_uring_params p = { };
  114. int ret, files[MAX_FILES];
  115. if (argc > 1)
  116. return 0;
  117. ret = io_uring_queue_init_params(8, &ring, &p);
  118. if (ret) {
  119. fprintf(stderr, "ring setup failed: %d\n", ret);
  120. return 1;
  121. }
  122. if (!(p.features & IORING_FEAT_CQE_SKIP))
  123. return 0;
  124. memset(files, -1, sizeof(files));
  125. ret = io_uring_register_files(&ring, files, ARRAY_SIZE(files));
  126. if (ret) {
  127. fprintf(stderr, "Failed registering files\n");
  128. return 1;
  129. }
  130. t_create_file(FNAME, 4096);
  131. ret = test(&ring, 0, 0, 0);
  132. if (ret) {
  133. fprintf(stderr, "test 0 0 0 failed\n");
  134. goto err;
  135. }
  136. ret = test(&ring, 0, 1, 0);
  137. if (ret) {
  138. fprintf(stderr, "test 0 1 0 failed\n");
  139. goto err;
  140. }
  141. ret = test(&ring, 0, 0, 1);
  142. if (ret) {
  143. fprintf(stderr, "test 0 0 1 failed\n");
  144. goto err;
  145. }
  146. ret = test(&ring, 0, 1, 1);
  147. if (ret) {
  148. fprintf(stderr, "test 0 1 1 failed\n");
  149. goto err;
  150. }
  151. ret = test(&ring, 1, 0, 0);
  152. if (ret) {
  153. fprintf(stderr, "test 1 0 0 failed\n");
  154. goto err;
  155. }
  156. ret = test(&ring, 1, 0, 1);
  157. if (ret) {
  158. fprintf(stderr, "test 1 0 1 failed\n");
  159. goto err;
  160. }
  161. unlink(FNAME);
  162. return 0;
  163. err:
  164. unlink(FNAME);
  165. return 1;
  166. }