| 91 | } |
| 92 | |
| 93 | static int test_offsets(void) |
| 94 | { |
| 95 | struct iovec vecs[NR_VECS]; |
| 96 | struct io_uring src, dst; |
| 97 | unsigned int i, offset, nr; |
| 98 | int ret; |
| 99 | |
| 100 | ret = io_uring_queue_init(1, &src, 0); |
| 101 | if (ret) { |
| 102 | fprintf(stderr, "ring_init: %d\n", ret); |
| 103 | return T_EXIT_FAIL; |
| 104 | } |
| 105 | ret = io_uring_queue_init(1, &dst, 0); |
| 106 | if (ret) { |
| 107 | fprintf(stderr, "ring_init: %d\n", ret); |
| 108 | return T_EXIT_FAIL; |
| 109 | } |
| 110 | |
| 111 | for (i = 0; i < NR_VECS; i++) { |
| 112 | if (posix_memalign(&vecs[i].iov_base, 4096, BUF_SIZE)) |
| 113 | return T_EXIT_FAIL; |
| 114 | vecs[i].iov_len = BUF_SIZE; |
| 115 | } |
| 116 | |
| 117 | ret = io_uring_register_buffers(&src, vecs, NR_VECS); |
| 118 | if (ret < 0) { |
| 119 | if (ret == -ENOMEM) |
| 120 | return T_EXIT_SKIP; |
| 121 | return T_EXIT_FAIL; |
| 122 | } |
| 123 | |
| 124 | /* clone half the buffers, src offset 0, but ask for too many */ |
| 125 | offset = NR_VECS / 2; |
| 126 | nr = NR_VECS; |
| 127 | ret = io_uring_clone_buffers_offset(&dst, &src, 0, offset, nr, 0); |
| 128 | if (ret != -EOVERFLOW) { |
| 129 | if (ret == -EINVAL) { |
| 130 | no_buf_offset = 1; |
| 131 | return T_EXIT_SKIP; |
| 132 | } |
| 133 | fprintf(stderr, "Offset and too big total failed: %d\n", ret); |
| 134 | return T_EXIT_FAIL; |
| 135 | } |
| 136 | |
| 137 | /* ask for too many buffers */ |
| 138 | nr = NR_VECS + 1; |
| 139 | ret = io_uring_clone_buffers_offset(&dst, &src, 0, 0, nr, 0); |
| 140 | if (ret != -EINVAL) { |
| 141 | fprintf(stderr, "Too many buffers total failed: %d\n", ret); |
| 142 | return T_EXIT_FAIL; |
| 143 | } |
| 144 | |
| 145 | /* clone half the buffers into start of src offset */ |
| 146 | nr = NR_VECS / 2; |
| 147 | ret = io_uring_clone_buffers_offset(&dst, &src, 0, nr, nr, 0); |
| 148 | if (ret) { |
| 149 | fprintf(stderr, "Half clone with offset failed: %d\n", ret); |
| 150 | return T_EXIT_FAIL; |
no test coverage detected