1 /*- 2 * Copyright (c) 2017 Spectra Logic Corp 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #define _WANT_ALL_LIO_OPCODES 28 29 #include <sys/param.h> 30 #include <sys/event.h> 31 #include <sys/uio.h> 32 33 #include <aio.h> 34 #include <fcntl.h> 35 #include <semaphore.h> 36 #include <stdlib.h> 37 38 #include <atf-c.h> 39 40 #include "local.h" 41 #include "freebsd_test_suite/macros.h" 42 43 static sem_t completions; 44 45 46 static void 47 handler(int sig __unused) 48 { 49 ATF_REQUIRE_EQ(0, sem_post(&completions)); 50 } 51 52 static void 53 thr_handler(union sigval sv __unused) 54 { 55 ATF_REQUIRE_EQ(0, sem_post(&completions)); 56 } 57 58 /* 59 * If lio_listio is unable to enqueue any requests at all, it should return 60 * EAGAIN. 61 */ 62 ATF_TC_WITHOUT_HEAD(lio_listio_eagain_kevent); 63 ATF_TC_BODY(lio_listio_eagain_kevent, tc) 64 { 65 int fd, i, j, kq, max_queue_per_proc, ios_per_call; 66 size_t max_queue_per_proc_size; 67 struct aiocb *aiocbs[2]; 68 struct aiocb **list[2]; 69 struct sigevent sev[2]; 70 char *buffer; 71 const char *path="tempfile"; 72 void *udata[2]; 73 74 ATF_REQUIRE_KERNEL_MODULE("aio"); 75 ATF_REQUIRE_UNSAFE_AIO(); 76 77 max_queue_per_proc_size = sizeof(max_queue_per_proc); 78 ATF_REQUIRE_EQ(sysctlbyname("vfs.aio.max_aio_queue_per_proc", 79 &max_queue_per_proc, &max_queue_per_proc_size, NULL, 0), 0); 80 ios_per_call = max_queue_per_proc; 81 82 fd = open(path, O_RDWR|O_CREAT, 0666); 83 ATF_REQUIRE(fd >= 0); 84 85 kq = kqueue(); 86 ATF_REQUIRE(kq > 0); 87 88 buffer = calloc(1, 4096); 89 ATF_REQUIRE(buffer != NULL); 90 91 /* 92 * Call lio_listio twice, each with the maximum number of operations. 93 * The first call should succeed and the second should fail. 94 */ 95 for (i = 0; i < 2; i++) { 96 aiocbs[i] = calloc(ios_per_call, sizeof(struct aiocb)); 97 ATF_REQUIRE(aiocbs[i] != NULL); 98 list[i] = calloc(ios_per_call, sizeof(struct aiocb*)); 99 ATF_REQUIRE(list[i] != NULL); 100 udata[i] = (void*)((caddr_t)0xdead0000 + i); 101 sev[i].sigev_notify = SIGEV_KEVENT; 102 sev[i].sigev_notify_kqueue = kq; 103 sev[i].sigev_value.sival_ptr = udata[i]; 104 for (j = 0; j < ios_per_call; j++) { 105 aiocbs[i][j].aio_fildes = fd; 106 aiocbs[i][j].aio_offset = (i * ios_per_call + j) * 4096; 107 aiocbs[i][j].aio_buf = buffer; 108 aiocbs[i][j].aio_nbytes = 4096; 109 aiocbs[i][j].aio_lio_opcode = LIO_WRITE; 110 list[i][j] = &aiocbs[i][j]; 111 } 112 } 113 114 ATF_REQUIRE_EQ(0, lio_listio(LIO_NOWAIT, list[0], ios_per_call, &sev[0])); 115 ATF_REQUIRE_EQ(-1, lio_listio(LIO_NOWAIT, list[1], ios_per_call, &sev[1])); 116 /* 117 * The second lio_listio call should fail with EAGAIN. Bad timing may 118 * mean that some requests did get enqueued, but the result should 119 * still be EAGAIN. 120 */ 121 ATF_REQUIRE_EQ(errno, EAGAIN); 122 } 123 124 125 /* With LIO_WAIT, an empty lio_listio should return immediately */ 126 ATF_TC_WITHOUT_HEAD(lio_listio_empty_wait); 127 ATF_TC_BODY(lio_listio_empty_wait, tc) 128 { 129 struct aiocb *list = NULL; 130 131 ATF_REQUIRE_EQ(0, lio_listio(LIO_WAIT, &list, 0, NULL)); 132 } 133 134 /* With LIO_NOWAIT, an empty lio_listio should return immediately */ 135 ATF_TC_WITHOUT_HEAD(lio_listio_empty_nowait); 136 ATF_TC_BODY(lio_listio_empty_nowait, tc) 137 { 138 struct aiocb *list = NULL; 139 140 ATF_REQUIRE_EQ(0, lio_listio(LIO_NOWAIT, &list, 0, NULL)); 141 } 142 143 /* 144 * With LIO_NOWAIT, an empty lio_listio should send completion notification 145 * immediately 146 */ 147 ATF_TC_WITHOUT_HEAD(lio_listio_empty_nowait_kevent); 148 ATF_TC_BODY(lio_listio_empty_nowait_kevent, tc) 149 { 150 struct aiocb *list = NULL; 151 struct sigevent sev; 152 struct kevent kq_returned; 153 int kq, result; 154 void *udata = (void*)0xdeadbeefdeadbeef; 155 156 atf_tc_expect_timeout("Bug 251515 - lio_listio(2) never sends" 157 " kevent if nent==0"); 158 kq = kqueue(); 159 ATF_REQUIRE(kq > 0); 160 sev.sigev_notify = SIGEV_KEVENT; 161 sev.sigev_notify_kqueue = kq; 162 sev.sigev_value.sival_ptr = udata; 163 ATF_REQUIRE_EQ(0, lio_listio(LIO_NOWAIT, &list, 0, &sev)); 164 result = kevent(kq, NULL, 0, &kq_returned, 1, NULL); 165 ATF_REQUIRE_MSG(result == 1, "Never got completion notification"); 166 ATF_REQUIRE_EQ((uintptr_t)list, kq_returned.ident); 167 ATF_REQUIRE_EQ(EVFILT_LIO, kq_returned.filter); 168 ATF_REQUIRE_EQ(udata, kq_returned.udata); 169 } 170 171 /* 172 * With LIO_NOWAIT, an empty lio_listio should send completion notification 173 * immediately 174 */ 175 ATF_TC_WITHOUT_HEAD(lio_listio_empty_nowait_signal); 176 ATF_TC_BODY(lio_listio_empty_nowait_signal, tc) 177 { 178 struct aiocb *list = NULL; 179 struct sigevent sev; 180 181 ATF_REQUIRE_EQ(0, sem_init(&completions, false, 0)); 182 sev.sigev_notify = SIGEV_SIGNAL; 183 sev.sigev_signo = SIGUSR1; 184 ATF_REQUIRE(SIG_ERR != signal(SIGUSR1, handler)); 185 ATF_REQUIRE_EQ(0, lio_listio(LIO_NOWAIT, &list, 0, &sev)); 186 ATF_REQUIRE_EQ(0, sem_wait(&completions)); 187 ATF_REQUIRE_EQ(0, sem_destroy(&completions)); 188 } 189 190 /* 191 * With LIO_NOWAIT, an empty lio_listio should send completion notification 192 * immediately 193 */ 194 ATF_TC_WITHOUT_HEAD(lio_listio_empty_nowait_thread); 195 ATF_TC_BODY(lio_listio_empty_nowait_thread, tc) 196 { 197 struct aiocb *list = NULL; 198 struct sigevent sev; 199 200 ATF_REQUIRE_EQ(0, sem_init(&completions, false, 0)); 201 bzero(&sev, sizeof(sev)); 202 sev.sigev_notify = SIGEV_THREAD; 203 sev.sigev_notify_function = thr_handler; 204 sev.sigev_notify_attributes = NULL; 205 ATF_REQUIRE_MSG(0 == lio_listio(LIO_NOWAIT, &list, 0, &sev), 206 "lio_listio: %s", strerror(errno)); 207 ATF_REQUIRE_EQ(0, sem_wait(&completions)); 208 ATF_REQUIRE_EQ(0, sem_destroy(&completions)); 209 } 210 211 /* 212 * A simple check that the allowed operations work. 213 */ 214 ATF_TC_WITHOUT_HEAD(lio_listio_opcodes); 215 ATF_TC_BODY(lio_listio_opcodes, tc) 216 { 217 struct aiocb write_cb, read_cb, writev_cb, readv_cb; 218 struct aiocb *list[] = {&write_cb, &read_cb, &writev_cb, &readv_cb}; 219 struct iovec writev_iov[2]; 220 struct iovec readv_iov[2]; 221 char buffer[6]; 222 int fd; 223 224 fd = open("testfile", O_CREAT | O_RDWR, 0666); 225 ATF_REQUIRE_MSG(fd >= 0, "open: %s", strerror(errno)); 226 227 /* We start with numbers in a file and letters in memory... */ 228 ATF_CHECK_EQ(6, write(fd, "123456", 6)); 229 memcpy(buffer, "abcdef", 6); 230 231 /* a -> 1 */ 232 bzero(&write_cb, sizeof(write_cb)); 233 write_cb.aio_sigevent.sigev_notify = SIGEV_NONE; 234 write_cb.aio_fildes = fd; 235 write_cb.aio_lio_opcode = LIO_WRITE; 236 write_cb.aio_buf = &buffer[0]; 237 write_cb.aio_nbytes = 1; 238 write_cb.aio_offset = 0; 239 240 /* b <- 2 */ 241 bzero(&read_cb, sizeof(read_cb)); 242 read_cb.aio_sigevent.sigev_notify = SIGEV_NONE; 243 read_cb.aio_fildes = fd; 244 read_cb.aio_lio_opcode = LIO_READ; 245 read_cb.aio_buf = &buffer[1]; 246 read_cb.aio_nbytes = 1; 247 read_cb.aio_offset = 1; 248 249 /* d -> 3, c -> 4 */ 250 writev_iov[0].iov_base = &buffer[3]; 251 writev_iov[0].iov_len = 1; 252 writev_iov[1].iov_base = &buffer[2]; 253 writev_iov[1].iov_len = 1; 254 bzero(&writev_cb, sizeof(writev_cb)); 255 writev_cb.aio_sigevent.sigev_notify = SIGEV_NONE; 256 writev_cb.aio_fildes = fd; 257 writev_cb.aio_lio_opcode = LIO_WRITEV; 258 writev_cb.aio_iov = &writev_iov; 259 writev_cb.aio_iovcnt = 2; 260 writev_cb.aio_offset = 2; 261 262 /* f <- 5, e <- 6 */ 263 readv_iov[0].iov_base = &buffer[5]; 264 readv_iov[0].iov_len = 1; 265 readv_iov[1].iov_base = &buffer[4]; 266 readv_iov[1].iov_len = 1; 267 bzero(&readv_cb, sizeof(readv_cb)); 268 readv_cb.aio_sigevent.sigev_notify = SIGEV_NONE; 269 readv_cb.aio_fildes = fd; 270 readv_cb.aio_lio_opcode = LIO_READV; 271 readv_cb.aio_iov = &readv_iov; 272 readv_cb.aio_iovcnt = 2; 273 readv_cb.aio_offset = 4; 274 275 ATF_CHECK_EQ(0, lio_listio(LIO_WAIT, list, nitems(list), NULL)); 276 ATF_CHECK_EQ(0, aio_error(&write_cb)); 277 ATF_CHECK_EQ(1, aio_return(&write_cb)); 278 ATF_CHECK_EQ(0, aio_error(&read_cb)); 279 ATF_CHECK_EQ(1, aio_return(&read_cb)); 280 ATF_CHECK_EQ(0, aio_error(&writev_cb)); 281 ATF_CHECK_EQ(2, aio_return(&writev_cb)); 282 ATF_CHECK_EQ(0, aio_error(&readv_cb)); 283 ATF_CHECK_EQ(2, aio_return(&readv_cb)); 284 285 ATF_CHECK_EQ(0, memcmp(buffer, "a2cd65", 6)); 286 ATF_CHECK_EQ(6, pread(fd, buffer, 6, 0)); 287 ATF_CHECK_EQ(0, memcmp(buffer, "a2dc56", 6)); 288 289 close(fd); 290 } 291 292 293 /* 294 * Only select opcodes are allowed with lio_listio 295 */ 296 ATF_TC_WITHOUT_HEAD(lio_listio_invalid_opcode); 297 ATF_TC_BODY(lio_listio_invalid_opcode, tc) 298 { 299 struct aiocb sync_cb, mlock_cb; 300 struct aiocb *list[] = {&sync_cb, &mlock_cb}; 301 int fd; 302 303 fd = open("testfile", O_CREAT | O_RDWR, 0666); 304 ATF_REQUIRE_MSG(fd >= 0, "open: %s", strerror(errno)); 305 306 bzero(&sync_cb, sizeof(sync_cb)); 307 sync_cb.aio_fildes = fd; 308 sync_cb.aio_lio_opcode = LIO_SYNC; 309 310 bzero(&mlock_cb, sizeof(mlock_cb)); 311 mlock_cb.aio_lio_opcode = LIO_MLOCK; 312 313 ATF_CHECK_ERRNO(EIO, lio_listio(LIO_WAIT, list, nitems(list), NULL)); 314 ATF_CHECK_EQ(EINVAL, aio_error(&sync_cb)); 315 ATF_CHECK_ERRNO(EINVAL, aio_return(&sync_cb) < 0); 316 ATF_CHECK_EQ(EINVAL, aio_error(&mlock_cb)); 317 ATF_CHECK_ERRNO(EINVAL, aio_return(&mlock_cb) < 0); 318 319 close(fd); 320 } 321 322 323 ATF_TP_ADD_TCS(tp) 324 { 325 326 ATF_TP_ADD_TC(tp, lio_listio_eagain_kevent); 327 ATF_TP_ADD_TC(tp, lio_listio_empty_nowait); 328 ATF_TP_ADD_TC(tp, lio_listio_empty_nowait_kevent); 329 ATF_TP_ADD_TC(tp, lio_listio_empty_nowait_signal); 330 ATF_TP_ADD_TC(tp, lio_listio_empty_nowait_thread); 331 ATF_TP_ADD_TC(tp, lio_listio_empty_wait); 332 ATF_TP_ADD_TC(tp, lio_listio_opcodes); 333 ATF_TP_ADD_TC(tp, lio_listio_invalid_opcode); 334 335 return (atf_no_error()); 336 } 337