rw_merge_test.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Regression test for incorrect async_list io_should_merge() logic
  5. * Bug was fixed in 5.5 by (commit: 561fb04 io_uring: replace workqueue usage with io-wq")
  6. * Affects 5.4 lts branch, at least 5.4.106 is affected.
  7. */
  8. #include <stdio.h>
  9. #include <errno.h>
  10. #include <sys/socket.h>
  11. #include <sys/un.h>
  12. #include <assert.h>
  13. #include <fcntl.h>
  14. #include <unistd.h>
  15. #include "liburing.h"
  16. #include "helpers.h"
  17. int main(int argc, char *argv[])
  18. {
  19. struct io_uring_sqe *sqe;
  20. struct io_uring_cqe *cqe;
  21. struct io_uring ring;
  22. int ret, fd, pipe1[2];
  23. char buf[4096];
  24. struct iovec vec = {
  25. .iov_base = buf,
  26. .iov_len = sizeof(buf)
  27. };
  28. struct __kernel_timespec ts = {.tv_sec = 3, .tv_nsec = 0};
  29. if (argc > 1)
  30. return 0;
  31. ret = pipe(pipe1);
  32. assert(!ret);
  33. fd = open("testfile", O_RDWR | O_CREAT, 0644);
  34. assert(fd >= 0);
  35. unlink("testfile");
  36. ret = ftruncate(fd, 4096);
  37. assert(!ret);
  38. ret = t_create_ring(4, &ring, 0);
  39. if (ret == T_SETUP_SKIP)
  40. return 0;
  41. else if (ret < 0)
  42. return 1;
  43. /* REQ1 */
  44. sqe = io_uring_get_sqe(&ring);
  45. io_uring_prep_readv(sqe, pipe1[0], &vec, 1, 0);
  46. sqe->user_data = 1;
  47. /* REQ2 */
  48. sqe = io_uring_get_sqe(&ring);
  49. io_uring_prep_readv(sqe, fd, &vec, 1, 4096);
  50. sqe->user_data = 2;
  51. ret = io_uring_submit(&ring);
  52. assert(ret == 2);
  53. ret = io_uring_wait_cqe(&ring, &cqe);
  54. assert(!ret);
  55. assert(cqe->res == 0);
  56. assert(cqe->user_data == 2);
  57. io_uring_cqe_seen(&ring, cqe);
  58. /*
  59. * REQ3
  60. * Prepare request adjacent to previous one, so merge logic may want to
  61. * link it to previous request, but because of a bug in merge logic
  62. * it may be merged with <REQ1> request
  63. */
  64. sqe = io_uring_get_sqe(&ring);
  65. io_uring_prep_readv(sqe, fd, &vec, 1, 2048);
  66. sqe->user_data = 3;
  67. ret = io_uring_submit(&ring);
  68. assert(ret == 1);
  69. /*
  70. * Read may stuck because of bug there request was be incorrectly
  71. * merged with <REQ1> request
  72. */
  73. ret = io_uring_wait_cqe_timeout(&ring, &cqe, &ts);
  74. if (ret == -ETIME) {
  75. printf("TEST_FAIL: readv req3 stuck\n");
  76. return 1;
  77. }
  78. assert(!ret);
  79. assert(cqe->res == 2048);
  80. assert(cqe->user_data == 3);
  81. io_uring_cqe_seen(&ring, cqe);
  82. io_uring_queue_exit(&ring);
  83. return 0;
  84. }