]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/aio/aio_test.c
Add a test for cancelling an active AIO request on a socket.
[FreeBSD/FreeBSD.git] / tests / sys / aio / aio_test.c
1 /*-
2  * Copyright (c) 2004 Robert N. M. Watson
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  * $FreeBSD$
27  */
28
29 /*
30  * Regression test to do some very basic AIO exercising on several types of
31  * file descriptors.  Currently, the tests consist of initializing a fixed
32  * size buffer with pseudo-random data, writing it to one fd using AIO, then
33  * reading it from a second descriptor using AIO.  For some targets, the same
34  * fd is used for write and read (i.e., file, md device), but for others the
35  * operation is performed on a peer (pty, socket, fifo, etc).  A timeout is
36  * initiated to detect undo blocking.  This test does not attempt to exercise
37  * error cases or more subtle asynchronous behavior, just make sure that the
38  * basic operations work on some basic object types.
39  */
40
41 #include <sys/param.h>
42 #include <sys/module.h>
43 #include <sys/socket.h>
44 #include <sys/stat.h>
45 #include <sys/mdioctl.h>
46
47 #include <aio.h>
48 #include <err.h>
49 #include <errno.h>
50 #include <fcntl.h>
51 #include <libutil.h>
52 #include <limits.h>
53 #include <stdint.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <termios.h>
58 #include <unistd.h>
59
60 #include <atf-c.h>
61
62 #include "freebsd_test_suite/macros.h"
63 #include "local.h"
64
65 #define PATH_TEMPLATE   "aio.XXXXXXXXXX"
66
67 /*
68  * GLOBAL_MAX sets the largest usable buffer size to be read and written, as
69  * it sizes ac_buffer in the aio_context structure.  It is also the default
70  * size for file I/O.  For other types, we use smaller blocks or we risk
71  * blocking (and we run in a single process/thread so that would be bad).
72  */
73 #define GLOBAL_MAX      16384
74
75 #define BUFFER_MAX      GLOBAL_MAX
76 struct aio_context {
77         int              ac_read_fd, ac_write_fd;
78         long             ac_seed;
79         char             ac_buffer[GLOBAL_MAX];
80         int              ac_buflen;
81         int              ac_seconds;
82         void             (*ac_cleanup)(void *arg);
83         void            *ac_cleanup_arg;
84 };
85
86 static int      aio_timedout;
87
88 /*
89  * Each test run specifies a timeout in seconds.  Use the somewhat obsoleted
90  * signal(3) and alarm(3) APIs to set this up.
91  */
92 static void
93 aio_timeout_signal(int sig __unused)
94 {
95
96         aio_timedout = 1;
97 }
98
99 static void
100 aio_timeout_start(int seconds)
101 {
102
103         aio_timedout = 0;
104         ATF_REQUIRE_MSG(signal(SIGALRM, aio_timeout_signal) != SIG_ERR,
105             "failed to set SIGALRM handler: %s", strerror(errno));
106         alarm(seconds);
107 }
108
109 static void
110 aio_timeout_stop(void)
111 {
112
113         ATF_REQUIRE_MSG(signal(SIGALRM, NULL) != SIG_ERR,
114             "failed to reset SIGALRM handler to default: %s", strerror(errno));
115         alarm(0);
116 }
117
118 /*
119  * Fill a buffer given a seed that can be fed into srandom() to initialize
120  * the PRNG in a repeatable manner.
121  */
122 static void
123 aio_fill_buffer(char *buffer, int len, long seed)
124 {
125         char ch;
126         int i;
127
128         srandom(seed);
129         for (i = 0; i < len; i++) {
130                 ch = random() & 0xff;
131                 buffer[i] = ch;
132         }
133 }
134
135 /*
136  * Test that a buffer matches a given seed.  See aio_fill_buffer().  Return
137  * (1) on a match, (0) on a mismatch.
138  */
139 static int
140 aio_test_buffer(char *buffer, int len, long seed)
141 {
142         char ch;
143         int i;
144
145         srandom(seed);
146         for (i = 0; i < len; i++) {
147                 ch = random() & 0xff;
148                 if (buffer[i] != ch)
149                         return (0);
150         }
151         return (1);
152 }
153
154 /*
155  * Initialize a testing context given the file descriptors provided by the
156  * test setup.
157  */
158 static void
159 aio_context_init(struct aio_context *ac, int read_fd,
160     int write_fd, int buflen, int seconds, void (*cleanup)(void *),
161     void *cleanup_arg)
162 {
163
164         ATF_REQUIRE_MSG(buflen <= BUFFER_MAX,
165             "aio_context_init: buffer too large (%d > %d)",
166             buflen, BUFFER_MAX);
167         bzero(ac, sizeof(*ac));
168         ac->ac_read_fd = read_fd;
169         ac->ac_write_fd = write_fd;
170         ac->ac_buflen = buflen;
171         srandomdev();
172         ac->ac_seed = random();
173         aio_fill_buffer(ac->ac_buffer, buflen, ac->ac_seed);
174         ATF_REQUIRE_MSG(aio_test_buffer(ac->ac_buffer, buflen,
175             ac->ac_seed) != 0, "aio_test_buffer: internal error");
176         ac->ac_seconds = seconds;
177         ac->ac_cleanup = cleanup;
178         ac->ac_cleanup_arg = cleanup_arg;
179 }
180
181 /*
182  * Each tester can register a callback to clean up in the event the test
183  * fails.  Preserve the value of errno so that subsequent calls to errx()
184  * work properly.
185  */
186 static void
187 aio_cleanup(struct aio_context *ac)
188 {
189         int error;
190
191         if (ac->ac_cleanup == NULL)
192                 return;
193         error = errno;
194         (ac->ac_cleanup)(ac->ac_cleanup_arg);
195         errno = error;
196 }
197
198 /*
199  * Perform a simple write test of our initialized data buffer to the provided
200  * file descriptor.
201  */
202 static void
203 aio_write_test(struct aio_context *ac)
204 {
205         struct aiocb aio, *aiop;
206         ssize_t len;
207
208         ATF_REQUIRE_KERNEL_MODULE("aio");
209
210         bzero(&aio, sizeof(aio));
211         aio.aio_buf = ac->ac_buffer;
212         aio.aio_nbytes = ac->ac_buflen;
213         aio.aio_fildes = ac->ac_write_fd;
214         aio.aio_offset = 0;
215
216         aio_timeout_start(ac->ac_seconds);
217
218         if (aio_write(&aio) < 0) {
219                 if (errno == EINTR) {
220                         if (aio_timedout) {
221                                 aio_cleanup(ac);
222                                 atf_tc_fail("aio_write timed out");
223                         }
224                 }
225                 aio_cleanup(ac);
226                 atf_tc_fail("aio_write failed: %s", strerror(errno));
227         }
228
229         len = aio_waitcomplete(&aiop, NULL);
230         if (len < 0) {
231                 if (errno == EINTR) {
232                         if (aio_timedout) {
233                                 aio_cleanup(ac);
234                                 atf_tc_fail("aio_waitcomplete timed out");
235                         }
236                 }
237                 aio_cleanup(ac);
238                 atf_tc_fail("aio_waitcomplete failed: %s", strerror(errno));
239         }
240
241         aio_timeout_stop();
242
243         if (len != ac->ac_buflen) {
244                 aio_cleanup(ac);
245                 atf_tc_fail("aio_waitcomplete short write (%jd)",
246                     (intmax_t)len);
247         }
248 }
249
250 /*
251  * Perform a simple read test of our initialized data buffer from the
252  * provided file descriptor.
253  */
254 static void
255 aio_read_test(struct aio_context *ac)
256 {
257         struct aiocb aio, *aiop;
258         ssize_t len;
259
260         ATF_REQUIRE_KERNEL_MODULE("aio");
261
262         bzero(ac->ac_buffer, ac->ac_buflen);
263         bzero(&aio, sizeof(aio));
264         aio.aio_buf = ac->ac_buffer;
265         aio.aio_nbytes = ac->ac_buflen;
266         aio.aio_fildes = ac->ac_read_fd;
267         aio.aio_offset = 0;
268
269         aio_timeout_start(ac->ac_seconds);
270
271         if (aio_read(&aio) < 0) {
272                 if (errno == EINTR) {
273                         if (aio_timedout) {
274                                 aio_cleanup(ac);
275                                 atf_tc_fail("aio_write timed out");
276                         }
277                 }
278                 aio_cleanup(ac);
279                 atf_tc_fail("aio_read failed: %s", strerror(errno));
280         }
281
282         len = aio_waitcomplete(&aiop, NULL);
283         if (len < 0) {
284                 if (errno == EINTR) {
285                         if (aio_timedout) {
286                                 aio_cleanup(ac);
287                                 atf_tc_fail("aio_waitcomplete timed out");
288                         }
289                 }
290                 aio_cleanup(ac);
291                 atf_tc_fail("aio_waitcomplete failed: %s", strerror(errno));
292         }
293
294         aio_timeout_stop();
295
296         if (len != ac->ac_buflen) {
297                 aio_cleanup(ac);
298                 atf_tc_fail("aio_waitcomplete short read (%jd)",
299                     (intmax_t)len);
300         }
301
302         if (aio_test_buffer(ac->ac_buffer, ac->ac_buflen, ac->ac_seed) == 0) {
303                 aio_cleanup(ac);
304                 atf_tc_fail("buffer mismatched");
305         }
306 }
307
308 /*
309  * Series of type-specific tests for AIO.  For now, we just make sure we can
310  * issue a write and then a read to each type.  We assume that once a write
311  * is issued, a read can follow.
312  */
313
314 /*
315  * Test with a classic file.  Assumes we can create a moderate size temporary
316  * file.
317  */
318 struct aio_file_arg {
319         int      afa_fd;
320         char    *afa_pathname;
321 };
322
323 static void
324 aio_file_cleanup(void *arg)
325 {
326         struct aio_file_arg *afa;
327
328         afa = arg;
329         close(afa->afa_fd);
330         unlink(afa->afa_pathname);
331 }
332
333 #define FILE_LEN        GLOBAL_MAX
334 #define FILE_TIMEOUT    30
335 ATF_TC_WITHOUT_HEAD(aio_file_test);
336 ATF_TC_BODY(aio_file_test, tc)
337 {
338         char pathname[PATH_MAX];
339         struct aio_file_arg arg;
340         struct aio_context ac;
341         int fd;
342
343         ATF_REQUIRE_KERNEL_MODULE("aio");
344         ATF_REQUIRE_UNSAFE_AIO();
345
346         strcpy(pathname, PATH_TEMPLATE);
347         fd = mkstemp(pathname);
348         ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno));
349
350         arg.afa_fd = fd;
351         arg.afa_pathname = pathname;
352
353         aio_context_init(&ac, fd, fd, FILE_LEN,
354             FILE_TIMEOUT, aio_file_cleanup, &arg);
355         aio_write_test(&ac);
356         aio_read_test(&ac);
357
358         aio_file_cleanup(&arg);
359 }
360
361 struct aio_fifo_arg {
362         int      afa_read_fd;
363         int      afa_write_fd;
364         char    *afa_pathname;
365 };
366
367 static void
368 aio_fifo_cleanup(void *arg)
369 {
370         struct aio_fifo_arg *afa;
371
372         afa = arg;
373         if (afa->afa_read_fd != -1)
374                 close(afa->afa_read_fd);
375         if (afa->afa_write_fd != -1)
376                 close(afa->afa_write_fd);
377         unlink(afa->afa_pathname);
378 }
379
380 #define FIFO_LEN        256
381 #define FIFO_TIMEOUT    30
382 ATF_TC_WITHOUT_HEAD(aio_fifo_test);
383 ATF_TC_BODY(aio_fifo_test, tc)
384 {
385         int error, read_fd = -1, write_fd = -1;
386         struct aio_fifo_arg arg;
387         char pathname[PATH_MAX];
388         struct aio_context ac;
389
390         ATF_REQUIRE_KERNEL_MODULE("aio");
391         ATF_REQUIRE_UNSAFE_AIO();
392
393         /*
394          * In theory, mkstemp() can return a name that is then collided with.
395          * Because this is a regression test, we treat that as a test failure
396          * rather than retrying.
397          */
398         strcpy(pathname, PATH_TEMPLATE);
399         ATF_REQUIRE_MSG(mkstemp(pathname) != -1,
400             "mkstemp failed: %s", strerror(errno));
401         ATF_REQUIRE_MSG(unlink(pathname) == 0,
402             "unlink failed: %s", strerror(errno));
403         ATF_REQUIRE_MSG(mkfifo(pathname, 0600) != -1,
404             "mkfifo failed: %s", strerror(errno));
405         arg.afa_pathname = pathname;
406         arg.afa_read_fd = -1;
407         arg.afa_write_fd = -1;
408
409         read_fd = open(pathname, O_RDONLY | O_NONBLOCK);
410         if (read_fd == -1) {
411                 error = errno;
412                 aio_fifo_cleanup(&arg);
413                 errno = error;
414                 atf_tc_fail("read_fd open failed: %s",
415                     strerror(errno));
416         }
417         arg.afa_read_fd = read_fd;
418
419         write_fd = open(pathname, O_WRONLY);
420         if (write_fd == -1) {
421                 error = errno;
422                 aio_fifo_cleanup(&arg);
423                 errno = error;
424                 atf_tc_fail("write_fd open failed: %s",
425                     strerror(errno));
426         }
427         arg.afa_write_fd = write_fd;
428
429         aio_context_init(&ac, read_fd, write_fd, FIFO_LEN,
430             FIFO_TIMEOUT, aio_fifo_cleanup, &arg);
431         aio_write_test(&ac);
432         aio_read_test(&ac);
433
434         aio_fifo_cleanup(&arg);
435 }
436
437 struct aio_unix_socketpair_arg {
438         int     asa_sockets[2];
439 };
440
441 static void
442 aio_unix_socketpair_cleanup(void *arg)
443 {
444         struct aio_unix_socketpair_arg *asa;
445
446         asa = arg;
447         close(asa->asa_sockets[0]);
448         close(asa->asa_sockets[1]);
449 }
450
451 #define UNIX_SOCKETPAIR_LEN     256
452 #define UNIX_SOCKETPAIR_TIMEOUT 30
453 ATF_TC_WITHOUT_HEAD(aio_unix_socketpair_test);
454 ATF_TC_BODY(aio_unix_socketpair_test, tc)
455 {
456         struct aio_unix_socketpair_arg arg;
457         struct aio_context ac;
458         int sockets[2];
459
460         ATF_REQUIRE_KERNEL_MODULE("aio");
461
462         ATF_REQUIRE_MSG(socketpair(PF_UNIX, SOCK_STREAM, 0, sockets) != -1,
463             "socketpair failed: %s", strerror(errno));
464
465         arg.asa_sockets[0] = sockets[0];
466         arg.asa_sockets[1] = sockets[1];
467         aio_context_init(&ac, sockets[0],
468             sockets[1], UNIX_SOCKETPAIR_LEN, UNIX_SOCKETPAIR_TIMEOUT,
469             aio_unix_socketpair_cleanup, &arg);
470         aio_write_test(&ac);
471         aio_read_test(&ac);
472
473         aio_unix_socketpair_cleanup(&arg);
474 }
475
476 struct aio_pty_arg {
477         int     apa_read_fd;
478         int     apa_write_fd;
479 };
480
481 static void
482 aio_pty_cleanup(void *arg)
483 {
484         struct aio_pty_arg *apa;
485
486         apa = arg;
487         close(apa->apa_read_fd);
488         close(apa->apa_write_fd);
489 };
490
491 #define PTY_LEN         256
492 #define PTY_TIMEOUT     30
493 ATF_TC_WITHOUT_HEAD(aio_pty_test);
494 ATF_TC_BODY(aio_pty_test, tc)
495 {
496         struct aio_pty_arg arg;
497         struct aio_context ac;
498         int read_fd, write_fd;
499         struct termios ts;
500         int error;
501
502         ATF_REQUIRE_KERNEL_MODULE("aio");
503         ATF_REQUIRE_UNSAFE_AIO();
504
505         ATF_REQUIRE_MSG(openpty(&read_fd, &write_fd, NULL, NULL, NULL) == 0,
506             "openpty failed: %s", strerror(errno));
507
508         arg.apa_read_fd = read_fd;
509         arg.apa_write_fd = write_fd;
510
511         if (tcgetattr(write_fd, &ts) < 0) {
512                 error = errno;
513                 aio_pty_cleanup(&arg);
514                 errno = error;
515                 atf_tc_fail("tcgetattr failed: %s", strerror(errno));
516         }
517         cfmakeraw(&ts);
518         if (tcsetattr(write_fd, TCSANOW, &ts) < 0) {
519                 error = errno;
520                 aio_pty_cleanup(&arg);
521                 errno = error;
522                 atf_tc_fail("tcsetattr failed: %s", strerror(errno));
523         }
524         aio_context_init(&ac, read_fd, write_fd, PTY_LEN,
525             PTY_TIMEOUT, aio_pty_cleanup, &arg);
526
527         aio_write_test(&ac);
528         aio_read_test(&ac);
529
530         aio_pty_cleanup(&arg);
531 }
532
533 static void
534 aio_pipe_cleanup(void *arg)
535 {
536         int *pipes = arg;
537
538         close(pipes[0]);
539         close(pipes[1]);
540 }
541
542 #define PIPE_LEN        256
543 #define PIPE_TIMEOUT    30
544 ATF_TC_WITHOUT_HEAD(aio_pipe_test);
545 ATF_TC_BODY(aio_pipe_test, tc)
546 {
547         struct aio_context ac;
548         int pipes[2];
549
550         ATF_REQUIRE_KERNEL_MODULE("aio");
551         ATF_REQUIRE_UNSAFE_AIO();
552
553         ATF_REQUIRE_MSG(pipe(pipes) != -1,
554             "pipe failed: %s", strerror(errno));
555
556         aio_context_init(&ac, pipes[0], pipes[1], PIPE_LEN,
557             PIPE_TIMEOUT, aio_pipe_cleanup, pipes);
558         aio_write_test(&ac);
559         aio_read_test(&ac);
560
561         aio_pipe_cleanup(pipes);
562 }
563
564 struct aio_md_arg {
565         int     ama_mdctl_fd;
566         int     ama_unit;
567         int     ama_fd;
568 };
569
570 static void
571 aio_md_cleanup(void *arg)
572 {
573         struct aio_md_arg *ama;
574         struct md_ioctl mdio;
575         int error;
576
577         ama = arg;
578
579         if (ama->ama_fd != -1)
580                 close(ama->ama_fd);
581
582         if (ama->ama_unit != -1) {
583                 bzero(&mdio, sizeof(mdio));
584                 mdio.md_version = MDIOVERSION;
585                 mdio.md_unit = ama->ama_unit;
586                 if (ioctl(ama->ama_mdctl_fd, MDIOCDETACH, &mdio) == -1) {
587                         error = errno;
588                         close(ama->ama_mdctl_fd);
589                         errno = error;
590                         atf_tc_fail("ioctl MDIOCDETACH failed: %s",
591                             strerror(errno));
592                 }
593         }
594
595         close(ama->ama_mdctl_fd);
596 }
597
598 #define MD_LEN          GLOBAL_MAX
599 #define MD_TIMEOUT      30
600 ATF_TC(aio_md_test);
601 ATF_TC_HEAD(aio_md_test, tc)
602 {
603
604         atf_tc_set_md_var(tc, "require.user", "root");
605 }
606 ATF_TC_BODY(aio_md_test, tc)
607 {
608         int error, fd, mdctl_fd, unit;
609         char pathname[PATH_MAX];
610         struct aio_md_arg arg;
611         struct aio_context ac;
612         struct md_ioctl mdio;
613
614         ATF_REQUIRE_KERNEL_MODULE("aio");
615
616         mdctl_fd = open("/dev/" MDCTL_NAME, O_RDWR, 0);
617         ATF_REQUIRE_MSG(mdctl_fd != -1,
618             "opening /dev/%s failed: %s", MDCTL_NAME, strerror(errno));
619
620         bzero(&mdio, sizeof(mdio));
621         mdio.md_version = MDIOVERSION;
622         mdio.md_type = MD_MALLOC;
623         mdio.md_options = MD_AUTOUNIT | MD_COMPRESS;
624         mdio.md_mediasize = GLOBAL_MAX;
625         mdio.md_sectorsize = 512;
626
627         arg.ama_mdctl_fd = mdctl_fd;
628         arg.ama_unit = -1;
629         arg.ama_fd = -1;
630         if (ioctl(mdctl_fd, MDIOCATTACH, &mdio) < 0) {
631                 error = errno;
632                 aio_md_cleanup(&arg);
633                 errno = error;
634                 atf_tc_fail("ioctl MDIOCATTACH failed: %s", strerror(errno));
635         }
636
637         arg.ama_unit = unit = mdio.md_unit;
638         snprintf(pathname, PATH_MAX, "/dev/md%d", unit);
639         fd = open(pathname, O_RDWR);
640         ATF_REQUIRE_MSG(fd != -1,
641             "opening %s failed: %s", pathname, strerror(errno));
642         arg.ama_fd = fd;
643
644         aio_context_init(&ac, fd, fd, MD_LEN, MD_TIMEOUT,
645             aio_md_cleanup, &arg);
646         aio_write_test(&ac);
647         aio_read_test(&ac);
648
649         aio_md_cleanup(&arg);
650 }
651
652 ATF_TC_WITHOUT_HEAD(aio_large_read_test);
653 ATF_TC_BODY(aio_large_read_test, tc)
654 {
655         char pathname[PATH_MAX];
656         struct aiocb cb, *cbp;
657         ssize_t nread;
658         size_t len;
659         int fd;
660 #ifdef __LP64__
661         int clamped;
662 #endif
663
664         ATF_REQUIRE_KERNEL_MODULE("aio");
665         ATF_REQUIRE_UNSAFE_AIO();
666
667 #ifdef __LP64__
668         len = sizeof(clamped);
669         if (sysctlbyname("debug.iosize_max_clamp", &clamped, &len, NULL, 0) ==
670             -1)
671                 atf_libc_error(errno, "Failed to read debug.iosize_max_clamp");
672 #endif
673
674         /* Determine the maximum supported read(2) size. */
675         len = SSIZE_MAX;
676 #ifdef __LP64__
677         if (clamped)
678                 len = INT_MAX;
679 #endif
680
681         strcpy(pathname, PATH_TEMPLATE);
682         fd = mkstemp(pathname);
683         ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno));
684
685         unlink(pathname);
686
687         memset(&cb, 0, sizeof(cb));
688         cb.aio_nbytes = len;
689         cb.aio_fildes = fd;
690         cb.aio_buf = NULL;
691         if (aio_read(&cb) == -1)
692                 atf_tc_fail("aio_read() of maximum read size failed: %s",
693                     strerror(errno));
694
695         nread = aio_waitcomplete(&cbp, NULL);
696         if (nread == -1)
697                 atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
698         if (nread != 0)
699                 atf_tc_fail("aio_read() from empty file returned data: %zd",
700                     nread);
701
702         memset(&cb, 0, sizeof(cb));
703         cb.aio_nbytes = len + 1;
704         cb.aio_fildes = fd;
705         cb.aio_buf = NULL;
706         if (aio_read(&cb) == -1) {
707                 if (errno == EINVAL)
708                         goto finished;
709                 atf_tc_fail("aio_read() of too large read size failed: %s",
710                     strerror(errno));
711         }
712
713         nread = aio_waitcomplete(&cbp, NULL);
714         if (nread == -1) {
715                 if (errno == EINVAL)
716                         goto finished;
717                 atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
718         }
719         atf_tc_fail("aio_read() of too large read size returned: %zd", nread);
720
721 finished:
722         close(fd);
723 }
724
725 /*
726  * This tests for a bug where arriving socket data can wakeup multiple
727  * AIO read requests resulting in an uncancellable request.
728  */
729 ATF_TC_WITHOUT_HEAD(aio_socket_two_reads);
730 ATF_TC_BODY(aio_socket_two_reads, tc)
731 {
732         struct ioreq {
733                 struct aiocb iocb;
734                 char buffer[1024];
735         } ioreq[2];
736         struct aiocb *iocb;
737         unsigned i;
738         int s[2];
739         char c;
740
741         ATF_REQUIRE_KERNEL_MODULE("aio");
742 #if __FreeBSD_version < 1100101
743         aft_tc_skip("kernel version %d is too old (%d required)",
744             __FreeBSD_version, 1100101);
745 #endif
746
747         ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, s) != -1);
748
749         /* Queue two read requests. */
750         memset(&ioreq, 0, sizeof(ioreq));
751         for (i = 0; i < nitems(ioreq); i++) {
752                 ioreq[i].iocb.aio_nbytes = sizeof(ioreq[i].buffer);
753                 ioreq[i].iocb.aio_fildes = s[0];
754                 ioreq[i].iocb.aio_buf = ioreq[i].buffer;
755                 ATF_REQUIRE(aio_read(&ioreq[i].iocb) == 0);
756         }
757
758         /* Send a single byte.  This should complete one request. */
759         c = 0xc3;
760         ATF_REQUIRE(write(s[1], &c, sizeof(c)) == 1);
761
762         ATF_REQUIRE(aio_waitcomplete(&iocb, NULL) == 1);
763
764         /* Determine which request completed and verify the data was read. */
765         if (iocb == &ioreq[0].iocb)
766                 i = 0;
767         else
768                 i = 1;
769         ATF_REQUIRE(ioreq[i].buffer[0] == c);
770
771         i ^= 1;
772
773         /*
774          * Try to cancel the other request.  On broken systems this
775          * will fail and the process will hang on exit.
776          */
777         ATF_REQUIRE(aio_error(&ioreq[i].iocb) == EINPROGRESS);
778         ATF_REQUIRE(aio_cancel(s[0], &ioreq[i].iocb) == AIO_CANCELED);
779
780         close(s[1]);
781         close(s[0]);
782 }
783
784 ATF_TP_ADD_TCS(tp)
785 {
786
787         ATF_TP_ADD_TC(tp, aio_file_test);
788         ATF_TP_ADD_TC(tp, aio_fifo_test);
789         ATF_TP_ADD_TC(tp, aio_unix_socketpair_test);
790         ATF_TP_ADD_TC(tp, aio_pty_test);
791         ATF_TP_ADD_TC(tp, aio_pipe_test);
792         ATF_TP_ADD_TC(tp, aio_md_test);
793         ATF_TP_ADD_TC(tp, aio_large_read_test);
794         ATF_TP_ADD_TC(tp, aio_socket_two_reads);
795
796         return (atf_no_error());
797 }