truncate.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: run various truncate 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 <sys/stat.h>
  14. #include <sys/ioctl.h>
  15. #include "liburing.h"
  16. #include "helpers.h"
  17. #define TWO_GIG_SIZE ((loff_t)2 * 1024 * 1024 * 1024)
  18. #define ONE_GIG_SIZE ((loff_t)1024 * 1024 * 1024)
  19. #define HALF_GIG_SIZE ((loff_t)512 * 1024 * 1024)
  20. static int test_truncate(struct io_uring *ring, int fd)
  21. {
  22. struct io_uring_cqe *cqe;
  23. struct io_uring_sqe *sqe;
  24. int ret = -1;
  25. sqe = io_uring_get_sqe(ring);
  26. if (!sqe) {
  27. fprintf(stderr, "get sqe failed\n");
  28. return T_EXIT_FAIL;
  29. }
  30. memset(sqe, 0, sizeof(*sqe));
  31. io_uring_prep_rw(IORING_OP_FTRUNCATE, sqe, fd, "fail", 0, 4);
  32. ret = io_uring_submit(ring);
  33. if (ret <= 0) {
  34. fprintf(stderr, "sqe submit failed: %d\n", ret);
  35. return T_EXIT_FAIL;
  36. }
  37. ret = io_uring_wait_cqe(ring, &cqe);
  38. if (ret < 0) {
  39. fprintf(stderr, "wait completion %d\n", ret);
  40. return T_EXIT_FAIL;
  41. }
  42. ret = cqe->res;
  43. io_uring_cqe_seen(ring, cqe);
  44. if (ret == -EINVAL)
  45. return T_EXIT_PASS;
  46. fprintf(stderr, "unexpected truncate res %d\n", ret);
  47. return T_EXIT_FAIL;
  48. }
  49. static int test_ftruncate(struct io_uring *ring, int fd, loff_t len)
  50. {
  51. struct io_uring_cqe *cqe;
  52. struct io_uring_sqe *sqe;
  53. int ret;
  54. sqe = io_uring_get_sqe(ring);
  55. if (!sqe) {
  56. fprintf(stderr, "get sqe failed\n");
  57. goto err;
  58. }
  59. memset(sqe, 0, sizeof(*sqe));
  60. io_uring_prep_ftruncate(sqe, fd, len);
  61. ret = io_uring_submit(ring);
  62. if (ret <= 0) {
  63. fprintf(stderr, "sqe submit failed: %d\n", ret);
  64. goto err;
  65. }
  66. ret = io_uring_wait_cqe(ring, &cqe);
  67. if (ret < 0) {
  68. fprintf(stderr, "wait completion %d\n", ret);
  69. goto err;
  70. }
  71. ret = cqe->res;
  72. io_uring_cqe_seen(ring, cqe);
  73. return ret;
  74. err:
  75. return 1;
  76. }
  77. static int get_file_size(int fd, loff_t *size)
  78. {
  79. struct stat st;
  80. if (fstat(fd, &st) < 0) {
  81. perror("fstat");
  82. return -1;
  83. }
  84. if (S_ISREG(st.st_mode)) {
  85. *size = st.st_size;
  86. return 0;
  87. } else if (S_ISBLK(st.st_mode)) {
  88. unsigned long long bytes;
  89. if (ioctl(fd, BLKGETSIZE64, &bytes) != 0) {
  90. perror("ioctl");
  91. return -1;
  92. }
  93. *size = bytes;
  94. return 0;
  95. }
  96. return -1;
  97. }
  98. int main(int argc, char *argv[])
  99. {
  100. struct io_uring ring;
  101. char path[32] = ".truncate.XXXXXX";
  102. int ret;
  103. int fd;
  104. int i;
  105. loff_t size;
  106. loff_t test_sizes[3];
  107. if (argc > 1)
  108. return T_EXIT_SKIP;
  109. ret = io_uring_queue_init(1, &ring, 0);
  110. if (ret) {
  111. fprintf(stderr, "ring setup failed: %d\n", ret);
  112. return T_EXIT_FAIL;
  113. }
  114. fd = mkostemp(path, O_WRONLY | O_CREAT | O_TRUNC);
  115. if (fd < 0) {
  116. perror("mkostemp");
  117. return T_EXIT_FAIL;
  118. }
  119. test_sizes[0] = TWO_GIG_SIZE;
  120. test_sizes[1] = ONE_GIG_SIZE;
  121. test_sizes[2] = HALF_GIG_SIZE;
  122. for (i = 0; i < 3; i++) {
  123. ret = test_ftruncate(&ring, fd, test_sizes[i]);
  124. if (ret < 0) {
  125. if (ret == -EBADF || ret == -EINVAL) {
  126. if (i == 0) {
  127. fprintf(stdout, "Ftruncate not supported, skipping\n");
  128. ret = T_EXIT_SKIP;
  129. goto out;
  130. }
  131. goto err;
  132. }
  133. fprintf(stderr, "ftruncate: %s\n", strerror(-ret));
  134. goto err;
  135. } else if (ret) {
  136. fprintf(stderr, "unexpected cqe->res %d\n", ret);
  137. goto err;
  138. }
  139. if (get_file_size(fd, &size))
  140. goto err;
  141. if (size != test_sizes[i]) {
  142. fprintf(stderr, "fail %d size=%llu, %llu\n", i,
  143. (unsigned long long) size,
  144. (unsigned long long) test_sizes[i]);
  145. goto err;
  146. }
  147. }
  148. ret = test_truncate(&ring, fd);
  149. if (ret != T_EXIT_PASS)
  150. goto err;
  151. out:
  152. unlink(path);
  153. close(fd);
  154. return T_EXIT_PASS;
  155. err:
  156. unlink(path);
  157. close(fd);
  158. return T_EXIT_FAIL;
  159. }