file-update.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: run various file registration 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 "helpers.h"
  14. #include "liburing.h"
  15. static void close_files(int *files, int nr_files, int add)
  16. {
  17. char fname[32];
  18. int i;
  19. for (i = 0; i < nr_files; i++) {
  20. if (files)
  21. close(files[i]);
  22. if (!add)
  23. sprintf(fname, ".reg.%d", i);
  24. else
  25. sprintf(fname, ".add.%d", i + add);
  26. unlink(fname);
  27. }
  28. if (files)
  29. free(files);
  30. }
  31. static int *open_files(int nr_files, int extra, int add)
  32. {
  33. char fname[32];
  34. int *files;
  35. int i;
  36. files = t_calloc(nr_files + extra, sizeof(int));
  37. for (i = 0; i < nr_files; i++) {
  38. if (!add)
  39. sprintf(fname, ".reg.%d", i);
  40. else
  41. sprintf(fname, ".add.%d", i + add);
  42. files[i] = open(fname, O_RDWR | O_CREAT, 0644);
  43. if (files[i] < 0) {
  44. perror("open");
  45. free(files);
  46. files = NULL;
  47. break;
  48. }
  49. }
  50. if (extra) {
  51. for (i = nr_files; i < nr_files + extra; i++)
  52. files[i] = -1;
  53. }
  54. return files;
  55. }
  56. static int test_update_multiring(struct io_uring *r1, struct io_uring *r2,
  57. struct io_uring *r3, int do_unreg)
  58. {
  59. int *fds, *newfds;
  60. fds = open_files(10, 0, 0);
  61. newfds = open_files(10, 0, 1);
  62. if (io_uring_register_files(r1, fds, 10) ||
  63. io_uring_register_files(r2, fds, 10) ||
  64. io_uring_register_files(r3, fds, 10)) {
  65. fprintf(stderr, "%s: register files failed\n", __FUNCTION__);
  66. goto err;
  67. }
  68. if (io_uring_register_files_update(r1, 0, newfds, 10) != 10 ||
  69. io_uring_register_files_update(r2, 0, newfds, 10) != 10 ||
  70. io_uring_register_files_update(r3, 0, newfds, 10) != 10) {
  71. fprintf(stderr, "%s: update files failed\n", __FUNCTION__);
  72. goto err;
  73. }
  74. if (!do_unreg)
  75. goto done;
  76. if (io_uring_unregister_files(r1) ||
  77. io_uring_unregister_files(r2) ||
  78. io_uring_unregister_files(r3)) {
  79. fprintf(stderr, "%s: unregister files failed\n", __FUNCTION__);
  80. goto err;
  81. }
  82. done:
  83. close_files(fds, 10, 0);
  84. close_files(newfds, 10, 1);
  85. return 0;
  86. err:
  87. close_files(fds, 10, 0);
  88. close_files(newfds, 10, 1);
  89. return 1;
  90. }
  91. static int test_sqe_update(struct io_uring *ring)
  92. {
  93. struct io_uring_sqe *sqe;
  94. struct io_uring_cqe *cqe;
  95. int *fds, i, ret;
  96. fds = t_malloc(sizeof(int) * 10);
  97. for (i = 0; i < 10; i++)
  98. fds[i] = -1;
  99. sqe = io_uring_get_sqe(ring);
  100. io_uring_prep_files_update(sqe, fds, 10, 0);
  101. ret = io_uring_submit(ring);
  102. if (ret != 1) {
  103. fprintf(stderr, "submit: %d\n", ret);
  104. return 1;
  105. }
  106. ret = io_uring_wait_cqe(ring, &cqe);
  107. if (ret) {
  108. fprintf(stderr, "wait: %d\n", ret);
  109. return 1;
  110. }
  111. ret = cqe->res;
  112. io_uring_cqe_seen(ring, cqe);
  113. free(fds);
  114. if (ret == -EINVAL) {
  115. fprintf(stdout, "IORING_OP_FILES_UPDATE not supported, skipping\n");
  116. return T_EXIT_SKIP;
  117. }
  118. return ret != 10;
  119. }
  120. static int test_update_no_table(void)
  121. {
  122. int up_fd, fds[4] = {-1, 0, 1, 4};
  123. struct io_uring_sqe *sqe;
  124. struct io_uring_cqe *cqe;
  125. struct io_uring ring;
  126. int ret;
  127. ret = t_create_ring(2, &ring, 0);
  128. if (ret == T_SETUP_SKIP)
  129. return T_EXIT_SKIP;
  130. else if (ret != T_SETUP_OK)
  131. return ret;
  132. ret = io_uring_register_files(&ring, fds, 4);
  133. /* ignore other failures */
  134. if (ret && ret != -EBADF) {
  135. fprintf(stderr, "Failed registering file table: %d\n", ret);
  136. goto fail;
  137. }
  138. sqe = io_uring_get_sqe(&ring);
  139. up_fd = ring.ring_fd;
  140. io_uring_prep_files_update(sqe, &up_fd, 1, -1); //offset = -1
  141. ret = io_uring_submit(&ring);
  142. if (ret != 1) {
  143. fprintf(stderr, "Failed submit: %d\n", ret);
  144. goto fail;
  145. }
  146. ret = io_uring_wait_cqe(&ring, &cqe);
  147. if (ret) {
  148. fprintf(stderr, "Failed wait: %d\n", ret);
  149. goto fail;
  150. }
  151. ret = cqe->res;
  152. io_uring_cqe_seen(&ring, cqe);
  153. if (ret != -EMFILE && ret != -EINVAL && ret != -EOVERFLOW &&
  154. ret != -ENXIO && ret != -EBADF) {
  155. fprintf(stderr, "Bad cqe res: %d\n", ret);
  156. goto fail;
  157. }
  158. io_uring_queue_exit(&ring);
  159. return T_EXIT_PASS;
  160. fail:
  161. io_uring_queue_exit(&ring);
  162. return T_EXIT_FAIL;
  163. }
  164. int main(int argc, char *argv[])
  165. {
  166. struct io_uring r1, r2, r3;
  167. int ret;
  168. if (argc > 1)
  169. return T_EXIT_SKIP;
  170. if (io_uring_queue_init(8, &r1, 0) ||
  171. io_uring_queue_init(8, &r2, 0) ||
  172. io_uring_queue_init(8, &r3, 0)) {
  173. fprintf(stderr, "ring setup failed\n");
  174. return 1;
  175. }
  176. ret = test_update_multiring(&r1, &r2, &r3, 1);
  177. if (ret) {
  178. fprintf(stderr, "test_update_multiring w/unreg\n");
  179. return ret;
  180. }
  181. ret = test_update_multiring(&r1, &r2, &r3, 0);
  182. if (ret) {
  183. fprintf(stderr, "test_update_multiring wo/unreg\n");
  184. return ret;
  185. }
  186. ret = test_sqe_update(&r1);
  187. if (ret) {
  188. if (ret != T_EXIT_SKIP)
  189. fprintf(stderr, "test_sqe_update failed\n");
  190. return ret;
  191. }
  192. ret = test_update_no_table();
  193. if (ret) {
  194. if (ret != T_EXIT_SKIP)
  195. fprintf(stderr, "test_sqe_update failed\n");
  196. return ret;
  197. }
  198. return T_EXIT_PASS;
  199. }