1f44eb013SEnji Cooper /*-
2f44eb013SEnji Cooper * Copyright (c) 2004 Robert N. M. Watson
3f44eb013SEnji Cooper * All rights reserved.
4f44eb013SEnji Cooper *
5f44eb013SEnji Cooper * Redistribution and use in source and binary forms, with or without
6f44eb013SEnji Cooper * modification, are permitted provided that the following conditions
7f44eb013SEnji Cooper * are met:
8f44eb013SEnji Cooper * 1. Redistributions of source code must retain the above copyright
9f44eb013SEnji Cooper * notice, this list of conditions and the following disclaimer.
10f44eb013SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
11f44eb013SEnji Cooper * notice, this list of conditions and the following disclaimer in the
12f44eb013SEnji Cooper * documentation and/or other materials provided with the distribution.
13f44eb013SEnji Cooper *
14f44eb013SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15f44eb013SEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16f44eb013SEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17f44eb013SEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18f44eb013SEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19f44eb013SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20f44eb013SEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21f44eb013SEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22f44eb013SEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23f44eb013SEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24f44eb013SEnji Cooper * SUCH DAMAGE.
25f44eb013SEnji Cooper */
26f44eb013SEnji Cooper
27f44eb013SEnji Cooper /*
28f44eb013SEnji Cooper * Regression test to do some very basic AIO exercising on several types of
29f44eb013SEnji Cooper * file descriptors. Currently, the tests consist of initializing a fixed
30f44eb013SEnji Cooper * size buffer with pseudo-random data, writing it to one fd using AIO, then
31f44eb013SEnji Cooper * reading it from a second descriptor using AIO. For some targets, the same
32f44eb013SEnji Cooper * fd is used for write and read (i.e., file, md device), but for others the
33d600f474SAlan Somers * operation is performed on a peer (pty, socket, fifo, etc). For each file
34d600f474SAlan Somers * descriptor type, several completion methods are tested. This test program
35d600f474SAlan Somers * does not attempt to exercise error cases or more subtle asynchronous
36d600f474SAlan Somers * behavior, just make sure that the basic operations work on some basic object
37d600f474SAlan Somers * types.
38f44eb013SEnji Cooper */
39f44eb013SEnji Cooper
40f44eb013SEnji Cooper #include <sys/param.h>
4157082ce8SAlan Somers #include <sys/event.h>
42141fe2dcSMark Johnston #include <sys/mdioctl.h>
43f44eb013SEnji Cooper #include <sys/module.h>
44b1012d80SJohn Baldwin #include <sys/resource.h>
45f44eb013SEnji Cooper #include <sys/socket.h>
46f44eb013SEnji Cooper #include <sys/stat.h>
47141fe2dcSMark Johnston #include <sys/un.h>
48f44eb013SEnji Cooper
49f44eb013SEnji Cooper #include <aio.h>
50f44eb013SEnji Cooper #include <err.h>
51f44eb013SEnji Cooper #include <errno.h>
52f44eb013SEnji Cooper #include <fcntl.h>
53f44eb013SEnji Cooper #include <libutil.h>
54f44eb013SEnji Cooper #include <limits.h>
55314b447fSAlan Somers #include <semaphore.h>
56c13f6dd7SMark Johnston #include <signal.h>
57f44eb013SEnji Cooper #include <stdint.h>
58f44eb013SEnji Cooper #include <stdio.h>
59f44eb013SEnji Cooper #include <stdlib.h>
60f44eb013SEnji Cooper #include <string.h>
61f44eb013SEnji Cooper #include <termios.h>
62f44eb013SEnji Cooper #include <unistd.h>
63f44eb013SEnji Cooper
64f44eb013SEnji Cooper #include <atf-c.h>
65f44eb013SEnji Cooper
66c5dfa43aSEnji Cooper #include "freebsd_test_suite/macros.h"
67f3215338SJohn Baldwin #include "local.h"
68c5dfa43aSEnji Cooper
69f44eb013SEnji Cooper /*
70f44eb013SEnji Cooper * GLOBAL_MAX sets the largest usable buffer size to be read and written, as
71f44eb013SEnji Cooper * it sizes ac_buffer in the aio_context structure. It is also the default
72f44eb013SEnji Cooper * size for file I/O. For other types, we use smaller blocks or we risk
73f44eb013SEnji Cooper * blocking (and we run in a single process/thread so that would be bad).
74f44eb013SEnji Cooper */
75f44eb013SEnji Cooper #define GLOBAL_MAX 16384
76f44eb013SEnji Cooper
77f44eb013SEnji Cooper #define BUFFER_MAX GLOBAL_MAX
78740a9bfaSAlan Somers
79740a9bfaSAlan Somers /*
80740a9bfaSAlan Somers * A completion function will block until the aio has completed, then return
81740a9bfaSAlan Somers * the result of the aio. errno will be set appropriately.
82740a9bfaSAlan Somers */
83740a9bfaSAlan Somers typedef ssize_t (*completion)(struct aiocb*);
84740a9bfaSAlan Somers
85f44eb013SEnji Cooper struct aio_context {
86f44eb013SEnji Cooper int ac_read_fd, ac_write_fd;
87f44eb013SEnji Cooper long ac_seed;
88f44eb013SEnji Cooper char ac_buffer[GLOBAL_MAX];
89f44eb013SEnji Cooper int ac_buflen;
90f44eb013SEnji Cooper int ac_seconds;
91f44eb013SEnji Cooper };
92f44eb013SEnji Cooper
93314b447fSAlan Somers static sem_t completions;
94314b447fSAlan Somers
95f44eb013SEnji Cooper /*
96f44eb013SEnji Cooper * Fill a buffer given a seed that can be fed into srandom() to initialize
97f44eb013SEnji Cooper * the PRNG in a repeatable manner.
98f44eb013SEnji Cooper */
99f44eb013SEnji Cooper static void
aio_fill_buffer(char * buffer,int len,long seed)100f44eb013SEnji Cooper aio_fill_buffer(char *buffer, int len, long seed)
101f44eb013SEnji Cooper {
102f44eb013SEnji Cooper char ch;
103f44eb013SEnji Cooper int i;
104f44eb013SEnji Cooper
105f44eb013SEnji Cooper srandom(seed);
106f44eb013SEnji Cooper for (i = 0; i < len; i++) {
107f44eb013SEnji Cooper ch = random() & 0xff;
108f44eb013SEnji Cooper buffer[i] = ch;
109f44eb013SEnji Cooper }
110f44eb013SEnji Cooper }
111f44eb013SEnji Cooper
112f44eb013SEnji Cooper /*
113f44eb013SEnji Cooper * Test that a buffer matches a given seed. See aio_fill_buffer(). Return
114f44eb013SEnji Cooper * (1) on a match, (0) on a mismatch.
115f44eb013SEnji Cooper */
116f44eb013SEnji Cooper static int
aio_test_buffer(char * buffer,int len,long seed)117f44eb013SEnji Cooper aio_test_buffer(char *buffer, int len, long seed)
118f44eb013SEnji Cooper {
119f44eb013SEnji Cooper char ch;
120f44eb013SEnji Cooper int i;
121f44eb013SEnji Cooper
122f44eb013SEnji Cooper srandom(seed);
123f44eb013SEnji Cooper for (i = 0; i < len; i++) {
124f44eb013SEnji Cooper ch = random() & 0xff;
125f44eb013SEnji Cooper if (buffer[i] != ch)
126f44eb013SEnji Cooper return (0);
127f44eb013SEnji Cooper }
128f44eb013SEnji Cooper return (1);
129f44eb013SEnji Cooper }
130f44eb013SEnji Cooper
131f44eb013SEnji Cooper /*
132f44eb013SEnji Cooper * Initialize a testing context given the file descriptors provided by the
133f44eb013SEnji Cooper * test setup.
134f44eb013SEnji Cooper */
135f44eb013SEnji Cooper static void
aio_context_init(struct aio_context * ac,int read_fd,int write_fd,int buflen)136f44eb013SEnji Cooper aio_context_init(struct aio_context *ac, int read_fd,
137d600f474SAlan Somers int write_fd, int buflen)
138f44eb013SEnji Cooper {
139f44eb013SEnji Cooper
140f44eb013SEnji Cooper ATF_REQUIRE_MSG(buflen <= BUFFER_MAX,
141f44eb013SEnji Cooper "aio_context_init: buffer too large (%d > %d)",
142f44eb013SEnji Cooper buflen, BUFFER_MAX);
143f44eb013SEnji Cooper bzero(ac, sizeof(*ac));
144f44eb013SEnji Cooper ac->ac_read_fd = read_fd;
145f44eb013SEnji Cooper ac->ac_write_fd = write_fd;
146f44eb013SEnji Cooper ac->ac_buflen = buflen;
147f44eb013SEnji Cooper srandomdev();
148f44eb013SEnji Cooper ac->ac_seed = random();
149f44eb013SEnji Cooper aio_fill_buffer(ac->ac_buffer, buflen, ac->ac_seed);
150f44eb013SEnji Cooper ATF_REQUIRE_MSG(aio_test_buffer(ac->ac_buffer, buflen,
151f44eb013SEnji Cooper ac->ac_seed) != 0, "aio_test_buffer: internal error");
152f44eb013SEnji Cooper }
153f44eb013SEnji Cooper
154740a9bfaSAlan Somers static ssize_t
poll(struct aiocb * aio)155e9b7132bSEnji Cooper poll(struct aiocb *aio)
156e9b7132bSEnji Cooper {
15755e0d88aSRobert Watson int error;
158740a9bfaSAlan Somers
159d600f474SAlan Somers while ((error = aio_error(aio)) == EINPROGRESS)
160740a9bfaSAlan Somers usleep(25000);
1610eafa707SAlan Somers if (error)
16255e0d88aSRobert Watson return (error);
1630eafa707SAlan Somers else
1640eafa707SAlan Somers return (aio_return(aio));
165740a9bfaSAlan Somers }
166740a9bfaSAlan Somers
167314b447fSAlan Somers static void
sigusr1_handler(int sig __unused)168314b447fSAlan Somers sigusr1_handler(int sig __unused)
169314b447fSAlan Somers {
170314b447fSAlan Somers ATF_REQUIRE_EQ(0, sem_post(&completions));
171314b447fSAlan Somers }
172314b447fSAlan Somers
173314b447fSAlan Somers static void
thr_handler(union sigval sv __unused)174314b447fSAlan Somers thr_handler(union sigval sv __unused)
175314b447fSAlan Somers {
176314b447fSAlan Somers ATF_REQUIRE_EQ(0, sem_post(&completions));
177314b447fSAlan Somers }
178314b447fSAlan Somers
179314b447fSAlan Somers static ssize_t
poll_signaled(struct aiocb * aio)180314b447fSAlan Somers poll_signaled(struct aiocb *aio)
181314b447fSAlan Somers {
182314b447fSAlan Somers int error;
183314b447fSAlan Somers
184314b447fSAlan Somers ATF_REQUIRE_EQ(0, sem_wait(&completions));
185314b447fSAlan Somers error = aio_error(aio);
186314b447fSAlan Somers switch (error) {
187314b447fSAlan Somers case EINPROGRESS:
188314b447fSAlan Somers errno = EINTR;
189314b447fSAlan Somers return (-1);
190314b447fSAlan Somers case 0:
191314b447fSAlan Somers return (aio_return(aio));
192314b447fSAlan Somers default:
193314b447fSAlan Somers return (error);
194314b447fSAlan Somers }
195314b447fSAlan Somers }
196314b447fSAlan Somers
197314b447fSAlan Somers /*
198314b447fSAlan Somers * Setup a signal handler for signal delivery tests
199314b447fSAlan Somers * This isn't thread safe, but it's ok since ATF runs each testcase in a
200314b447fSAlan Somers * separate process
201314b447fSAlan Somers */
202314b447fSAlan Somers static struct sigevent*
setup_signal(void)203314b447fSAlan Somers setup_signal(void)
204314b447fSAlan Somers {
205314b447fSAlan Somers static struct sigevent sev;
206314b447fSAlan Somers
207314b447fSAlan Somers ATF_REQUIRE_EQ(0, sem_init(&completions, false, 0));
208314b447fSAlan Somers sev.sigev_notify = SIGEV_SIGNAL;
209314b447fSAlan Somers sev.sigev_signo = SIGUSR1;
210314b447fSAlan Somers ATF_REQUIRE(SIG_ERR != signal(SIGUSR1, sigusr1_handler));
211314b447fSAlan Somers return (&sev);
212314b447fSAlan Somers }
213314b447fSAlan Somers
214314b447fSAlan Somers /*
215314b447fSAlan Somers * Setup a thread for thread delivery tests
216314b447fSAlan Somers * This isn't thread safe, but it's ok since ATF runs each testcase in a
217314b447fSAlan Somers * separate process
218314b447fSAlan Somers */
219314b447fSAlan Somers static struct sigevent*
setup_thread(void)220a4ea52aaSAlan Somers setup_thread(void)
221314b447fSAlan Somers {
222314b447fSAlan Somers static struct sigevent sev;
223314b447fSAlan Somers
224314b447fSAlan Somers ATF_REQUIRE_EQ(0, sem_init(&completions, false, 0));
225314b447fSAlan Somers sev.sigev_notify = SIGEV_THREAD;
226314b447fSAlan Somers sev.sigev_notify_function = thr_handler;
227314b447fSAlan Somers sev.sigev_notify_attributes = NULL;
228314b447fSAlan Somers return (&sev);
229314b447fSAlan Somers }
230314b447fSAlan Somers
231740a9bfaSAlan Somers static ssize_t
suspend(struct aiocb * aio)232e9b7132bSEnji Cooper suspend(struct aiocb *aio)
233e9b7132bSEnji Cooper {
234740a9bfaSAlan Somers const struct aiocb *const iocbs[] = {aio};
23555e0d88aSRobert Watson int error;
236740a9bfaSAlan Somers
23755e0d88aSRobert Watson error = aio_suspend(iocbs, 1, NULL);
23855e0d88aSRobert Watson if (error == 0)
239740a9bfaSAlan Somers return (aio_return(aio));
240740a9bfaSAlan Somers else
24155e0d88aSRobert Watson return (error);
242740a9bfaSAlan Somers }
243740a9bfaSAlan Somers
244740a9bfaSAlan Somers static ssize_t
waitcomplete(struct aiocb * aio)245e9b7132bSEnji Cooper waitcomplete(struct aiocb *aio)
246e9b7132bSEnji Cooper {
247740a9bfaSAlan Somers struct aiocb *aiop;
248740a9bfaSAlan Somers ssize_t ret;
249740a9bfaSAlan Somers
250740a9bfaSAlan Somers ret = aio_waitcomplete(&aiop, NULL);
251740a9bfaSAlan Somers ATF_REQUIRE_EQ(aio, aiop);
252740a9bfaSAlan Somers return (ret);
253740a9bfaSAlan Somers }
254740a9bfaSAlan Somers
255f44eb013SEnji Cooper /*
25657082ce8SAlan Somers * Setup an iocb for kqueue notification. This isn't thread
25757082ce8SAlan Somers * safe, but it's ok because ATF runs every test case in a separate process.
25857082ce8SAlan Somers */
25957082ce8SAlan Somers static struct sigevent*
setup_kqueue(void)26057082ce8SAlan Somers setup_kqueue(void)
26157082ce8SAlan Somers {
26257082ce8SAlan Somers static struct sigevent sev;
26357082ce8SAlan Somers static int kq;
26457082ce8SAlan Somers
26557082ce8SAlan Somers kq = kqueue();
26657082ce8SAlan Somers ATF_REQUIRE(kq >= 0);
26757082ce8SAlan Somers
26857082ce8SAlan Somers memset(&sev, 0, sizeof(sev));
26957082ce8SAlan Somers sev.sigev_notify_kqueue = kq;
27057082ce8SAlan Somers sev.sigev_value.sival_ptr = (void*)0xdeadbeef;
27157082ce8SAlan Somers sev.sigev_notify = SIGEV_KEVENT;
27257082ce8SAlan Somers
27357082ce8SAlan Somers return (&sev);
27457082ce8SAlan Somers }
27557082ce8SAlan Somers
27657082ce8SAlan Somers static ssize_t
poll_kqueue(struct aiocb * aio)27757082ce8SAlan Somers poll_kqueue(struct aiocb *aio)
27857082ce8SAlan Somers {
27957082ce8SAlan Somers int kq, nevents;
28057082ce8SAlan Somers struct kevent events[1];
28157082ce8SAlan Somers
28257082ce8SAlan Somers kq = aio->aio_sigevent.sigev_notify_kqueue;
28357082ce8SAlan Somers
28457082ce8SAlan Somers nevents = kevent(kq, NULL, 0, events, 1, NULL);
28557082ce8SAlan Somers ATF_CHECK_EQ(1, nevents);
28657082ce8SAlan Somers ATF_CHECK_EQ(events[0].ident, (uintptr_t) aio);
28757082ce8SAlan Somers ATF_CHECK_EQ(events[0].filter, EVFILT_AIO);
28857082ce8SAlan Somers ATF_CHECK_EQ(events[0].flags, EV_EOF);
28957082ce8SAlan Somers ATF_CHECK_EQ(events[0].fflags, 0);
29057082ce8SAlan Somers ATF_CHECK_EQ(events[0].data, 0);
29157082ce8SAlan Somers ATF_CHECK_EQ((uintptr_t)events[0].udata, 0xdeadbeef);
29257082ce8SAlan Somers
29357082ce8SAlan Somers return (aio_return(aio));
29457082ce8SAlan Somers }
29557082ce8SAlan Somers
29657082ce8SAlan Somers /*
297f44eb013SEnji Cooper * Perform a simple write test of our initialized data buffer to the provided
298f44eb013SEnji Cooper * file descriptor.
299f44eb013SEnji Cooper */
300f44eb013SEnji Cooper static void
aio_write_test(struct aio_context * ac,completion comp,struct sigevent * sev)301314b447fSAlan Somers aio_write_test(struct aio_context *ac, completion comp, struct sigevent *sev)
302f44eb013SEnji Cooper {
303740a9bfaSAlan Somers struct aiocb aio;
304f44eb013SEnji Cooper ssize_t len;
305f44eb013SEnji Cooper
306f44eb013SEnji Cooper bzero(&aio, sizeof(aio));
307f44eb013SEnji Cooper aio.aio_buf = ac->ac_buffer;
308f44eb013SEnji Cooper aio.aio_nbytes = ac->ac_buflen;
309f44eb013SEnji Cooper aio.aio_fildes = ac->ac_write_fd;
310f44eb013SEnji Cooper aio.aio_offset = 0;
311314b447fSAlan Somers if (sev)
312314b447fSAlan Somers aio.aio_sigevent = *sev;
313f44eb013SEnji Cooper
314d600f474SAlan Somers if (aio_write(&aio) < 0)
315f44eb013SEnji Cooper atf_tc_fail("aio_write failed: %s", strerror(errno));
316f44eb013SEnji Cooper
317740a9bfaSAlan Somers len = comp(&aio);
318d600f474SAlan Somers if (len < 0)
319740a9bfaSAlan Somers atf_tc_fail("aio failed: %s", strerror(errno));
320f44eb013SEnji Cooper
321d600f474SAlan Somers if (len != ac->ac_buflen)
322740a9bfaSAlan Somers atf_tc_fail("aio short write (%jd)", (intmax_t)len);
323f44eb013SEnji Cooper }
324f44eb013SEnji Cooper
325f44eb013SEnji Cooper /*
326022ca2fcSAlan Somers * Perform a vectored I/O test of our initialized data buffer to the provided
327022ca2fcSAlan Somers * file descriptor.
328022ca2fcSAlan Somers *
329022ca2fcSAlan Somers * To vectorize the linear buffer, chop it up into two pieces of dissimilar
330022ca2fcSAlan Somers * size, and swap their offsets.
331022ca2fcSAlan Somers */
332022ca2fcSAlan Somers static void
aio_writev_test(struct aio_context * ac,completion comp,struct sigevent * sev)333022ca2fcSAlan Somers aio_writev_test(struct aio_context *ac, completion comp, struct sigevent *sev)
334022ca2fcSAlan Somers {
335022ca2fcSAlan Somers struct aiocb aio;
336022ca2fcSAlan Somers struct iovec iov[2];
337022ca2fcSAlan Somers size_t len0, len1;
338022ca2fcSAlan Somers ssize_t len;
339022ca2fcSAlan Somers
340022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
341022ca2fcSAlan Somers
342022ca2fcSAlan Somers aio.aio_fildes = ac->ac_write_fd;
343022ca2fcSAlan Somers aio.aio_offset = 0;
344022ca2fcSAlan Somers len0 = ac->ac_buflen * 3 / 4;
345022ca2fcSAlan Somers len1 = ac->ac_buflen / 4;
346022ca2fcSAlan Somers iov[0].iov_base = ac->ac_buffer + len1;
347022ca2fcSAlan Somers iov[0].iov_len = len0;
348022ca2fcSAlan Somers iov[1].iov_base = ac->ac_buffer;
349022ca2fcSAlan Somers iov[1].iov_len = len1;
350022ca2fcSAlan Somers aio.aio_iov = iov;
351022ca2fcSAlan Somers aio.aio_iovcnt = 2;
352022ca2fcSAlan Somers if (sev)
353022ca2fcSAlan Somers aio.aio_sigevent = *sev;
354022ca2fcSAlan Somers
355022ca2fcSAlan Somers if (aio_writev(&aio) < 0)
356022ca2fcSAlan Somers atf_tc_fail("aio_writev failed: %s", strerror(errno));
357022ca2fcSAlan Somers
358022ca2fcSAlan Somers len = comp(&aio);
359022ca2fcSAlan Somers if (len < 0)
360022ca2fcSAlan Somers atf_tc_fail("aio failed: %s", strerror(errno));
361022ca2fcSAlan Somers
362022ca2fcSAlan Somers if (len != ac->ac_buflen)
363022ca2fcSAlan Somers atf_tc_fail("aio short write (%jd)", (intmax_t)len);
364022ca2fcSAlan Somers }
365022ca2fcSAlan Somers
366022ca2fcSAlan Somers /*
367f44eb013SEnji Cooper * Perform a simple read test of our initialized data buffer from the
368f44eb013SEnji Cooper * provided file descriptor.
369f44eb013SEnji Cooper */
370f44eb013SEnji Cooper static void
aio_read_test(struct aio_context * ac,completion comp,struct sigevent * sev)371314b447fSAlan Somers aio_read_test(struct aio_context *ac, completion comp, struct sigevent *sev)
372f44eb013SEnji Cooper {
373740a9bfaSAlan Somers struct aiocb aio;
374f44eb013SEnji Cooper ssize_t len;
375f44eb013SEnji Cooper
376f44eb013SEnji Cooper bzero(ac->ac_buffer, ac->ac_buflen);
377f44eb013SEnji Cooper bzero(&aio, sizeof(aio));
378f44eb013SEnji Cooper aio.aio_buf = ac->ac_buffer;
379f44eb013SEnji Cooper aio.aio_nbytes = ac->ac_buflen;
380f44eb013SEnji Cooper aio.aio_fildes = ac->ac_read_fd;
381f44eb013SEnji Cooper aio.aio_offset = 0;
382314b447fSAlan Somers if (sev)
383314b447fSAlan Somers aio.aio_sigevent = *sev;
384f44eb013SEnji Cooper
385d600f474SAlan Somers if (aio_read(&aio) < 0)
386f44eb013SEnji Cooper atf_tc_fail("aio_read failed: %s", strerror(errno));
387f44eb013SEnji Cooper
388740a9bfaSAlan Somers len = comp(&aio);
389d600f474SAlan Somers if (len < 0)
390740a9bfaSAlan Somers atf_tc_fail("aio failed: %s", strerror(errno));
391f44eb013SEnji Cooper
392d600f474SAlan Somers ATF_REQUIRE_EQ_MSG(len, ac->ac_buflen,
393d600f474SAlan Somers "aio short read (%jd)", (intmax_t)len);
394f44eb013SEnji Cooper
395d600f474SAlan Somers if (aio_test_buffer(ac->ac_buffer, ac->ac_buflen, ac->ac_seed) == 0)
396f44eb013SEnji Cooper atf_tc_fail("buffer mismatched");
397f44eb013SEnji Cooper }
398f44eb013SEnji Cooper
399022ca2fcSAlan Somers static void
aio_readv_test(struct aio_context * ac,completion comp,struct sigevent * sev)400022ca2fcSAlan Somers aio_readv_test(struct aio_context *ac, completion comp, struct sigevent *sev)
401022ca2fcSAlan Somers {
402022ca2fcSAlan Somers struct aiocb aio;
403022ca2fcSAlan Somers struct iovec iov[2];
404022ca2fcSAlan Somers size_t len0, len1;
405022ca2fcSAlan Somers ssize_t len;
406022ca2fcSAlan Somers
407022ca2fcSAlan Somers bzero(ac->ac_buffer, ac->ac_buflen);
408022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
409022ca2fcSAlan Somers aio.aio_fildes = ac->ac_read_fd;
410022ca2fcSAlan Somers aio.aio_offset = 0;
411022ca2fcSAlan Somers len0 = ac->ac_buflen * 3 / 4;
412022ca2fcSAlan Somers len1 = ac->ac_buflen / 4;
413022ca2fcSAlan Somers iov[0].iov_base = ac->ac_buffer + len1;
414022ca2fcSAlan Somers iov[0].iov_len = len0;
415022ca2fcSAlan Somers iov[1].iov_base = ac->ac_buffer;
416022ca2fcSAlan Somers iov[1].iov_len = len1;
417022ca2fcSAlan Somers aio.aio_iov = iov;
418022ca2fcSAlan Somers aio.aio_iovcnt = 2;
419022ca2fcSAlan Somers if (sev)
420022ca2fcSAlan Somers aio.aio_sigevent = *sev;
421022ca2fcSAlan Somers
422022ca2fcSAlan Somers if (aio_readv(&aio) < 0)
423022ca2fcSAlan Somers atf_tc_fail("aio_read failed: %s", strerror(errno));
424022ca2fcSAlan Somers
425022ca2fcSAlan Somers len = comp(&aio);
426022ca2fcSAlan Somers if (len < 0)
427022ca2fcSAlan Somers atf_tc_fail("aio failed: %s", strerror(errno));
428022ca2fcSAlan Somers
429022ca2fcSAlan Somers ATF_REQUIRE_EQ_MSG(len, ac->ac_buflen,
430022ca2fcSAlan Somers "aio short read (%jd)", (intmax_t)len);
431022ca2fcSAlan Somers
432022ca2fcSAlan Somers if (aio_test_buffer(ac->ac_buffer, ac->ac_buflen, ac->ac_seed) == 0)
433022ca2fcSAlan Somers atf_tc_fail("buffer mismatched");
434022ca2fcSAlan Somers }
435022ca2fcSAlan Somers
436f44eb013SEnji Cooper /*
437f44eb013SEnji Cooper * Series of type-specific tests for AIO. For now, we just make sure we can
438f44eb013SEnji Cooper * issue a write and then a read to each type. We assume that once a write
439f44eb013SEnji Cooper * is issued, a read can follow.
440f44eb013SEnji Cooper */
441f44eb013SEnji Cooper
442f44eb013SEnji Cooper /*
443f44eb013SEnji Cooper * Test with a classic file. Assumes we can create a moderate size temporary
444f44eb013SEnji Cooper * file.
445f44eb013SEnji Cooper */
446740a9bfaSAlan Somers #define FILE_LEN GLOBAL_MAX
447740a9bfaSAlan Somers #define FILE_PATHNAME "testfile"
448f44eb013SEnji Cooper
449740a9bfaSAlan Somers static void
aio_file_test(completion comp,struct sigevent * sev,bool vectored)450022ca2fcSAlan Somers aio_file_test(completion comp, struct sigevent *sev, bool vectored)
451f44eb013SEnji Cooper {
452f44eb013SEnji Cooper struct aio_context ac;
453f44eb013SEnji Cooper int fd;
454f44eb013SEnji Cooper
455c5dfa43aSEnji Cooper ATF_REQUIRE_KERNEL_MODULE("aio");
456f3215338SJohn Baldwin ATF_REQUIRE_UNSAFE_AIO();
457f44eb013SEnji Cooper
4589086b30bSJilles Tjoelker fd = open(FILE_PATHNAME, O_RDWR | O_CREAT, 0600);
459740a9bfaSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
460f44eb013SEnji Cooper
461d600f474SAlan Somers aio_context_init(&ac, fd, fd, FILE_LEN);
462022ca2fcSAlan Somers if (vectored) {
463022ca2fcSAlan Somers aio_writev_test(&ac, comp, sev);
464022ca2fcSAlan Somers aio_readv_test(&ac, comp, sev);
465022ca2fcSAlan Somers } else {
466314b447fSAlan Somers aio_write_test(&ac, comp, sev);
467314b447fSAlan Somers aio_read_test(&ac, comp, sev);
468022ca2fcSAlan Somers }
469d600f474SAlan Somers close(fd);
470f44eb013SEnji Cooper }
471f44eb013SEnji Cooper
47257082ce8SAlan Somers ATF_TC_WITHOUT_HEAD(file_kq);
ATF_TC_BODY(file_kq,tc)47357082ce8SAlan Somers ATF_TC_BODY(file_kq, tc)
47457082ce8SAlan Somers {
47557082ce8SAlan Somers aio_file_test(poll_kqueue, setup_kqueue(), false);
47657082ce8SAlan Somers }
47757082ce8SAlan Somers
478740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(file_poll);
ATF_TC_BODY(file_poll,tc)479740a9bfaSAlan Somers ATF_TC_BODY(file_poll, tc)
480740a9bfaSAlan Somers {
481022ca2fcSAlan Somers aio_file_test(poll, NULL, false);
482314b447fSAlan Somers }
483314b447fSAlan Somers
484314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(file_signal);
ATF_TC_BODY(file_signal,tc)485314b447fSAlan Somers ATF_TC_BODY(file_signal, tc)
486314b447fSAlan Somers {
487022ca2fcSAlan Somers aio_file_test(poll_signaled, setup_signal(), false);
488740a9bfaSAlan Somers }
489740a9bfaSAlan Somers
490740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(file_suspend);
ATF_TC_BODY(file_suspend,tc)491740a9bfaSAlan Somers ATF_TC_BODY(file_suspend, tc)
492740a9bfaSAlan Somers {
493022ca2fcSAlan Somers aio_file_test(suspend, NULL, false);
494314b447fSAlan Somers }
495314b447fSAlan Somers
496314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(file_thread);
ATF_TC_BODY(file_thread,tc)497314b447fSAlan Somers ATF_TC_BODY(file_thread, tc)
498314b447fSAlan Somers {
499022ca2fcSAlan Somers aio_file_test(poll_signaled, setup_thread(), false);
500740a9bfaSAlan Somers }
501740a9bfaSAlan Somers
502740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(file_waitcomplete);
ATF_TC_BODY(file_waitcomplete,tc)503740a9bfaSAlan Somers ATF_TC_BODY(file_waitcomplete, tc)
504740a9bfaSAlan Somers {
505022ca2fcSAlan Somers aio_file_test(waitcomplete, NULL, false);
506740a9bfaSAlan Somers }
507740a9bfaSAlan Somers
508740a9bfaSAlan Somers #define FIFO_LEN 256
509740a9bfaSAlan Somers #define FIFO_PATHNAME "testfifo"
510f44eb013SEnji Cooper
511740a9bfaSAlan Somers static void
aio_fifo_test(completion comp,struct sigevent * sev)512314b447fSAlan Somers aio_fifo_test(completion comp, struct sigevent *sev)
513f44eb013SEnji Cooper {
514f44eb013SEnji Cooper int error, read_fd = -1, write_fd = -1;
515f44eb013SEnji Cooper struct aio_context ac;
516f44eb013SEnji Cooper
517c5dfa43aSEnji Cooper ATF_REQUIRE_KERNEL_MODULE("aio");
518f3215338SJohn Baldwin ATF_REQUIRE_UNSAFE_AIO();
519f44eb013SEnji Cooper
520740a9bfaSAlan Somers ATF_REQUIRE_MSG(mkfifo(FIFO_PATHNAME, 0600) != -1,
521f44eb013SEnji Cooper "mkfifo failed: %s", strerror(errno));
522f44eb013SEnji Cooper
523740a9bfaSAlan Somers read_fd = open(FIFO_PATHNAME, O_RDONLY | O_NONBLOCK);
524f44eb013SEnji Cooper if (read_fd == -1) {
525f44eb013SEnji Cooper error = errno;
526f44eb013SEnji Cooper errno = error;
527f44eb013SEnji Cooper atf_tc_fail("read_fd open failed: %s",
528f44eb013SEnji Cooper strerror(errno));
529f44eb013SEnji Cooper }
530f44eb013SEnji Cooper
531740a9bfaSAlan Somers write_fd = open(FIFO_PATHNAME, O_WRONLY);
532f44eb013SEnji Cooper if (write_fd == -1) {
533f44eb013SEnji Cooper error = errno;
534f44eb013SEnji Cooper errno = error;
535f44eb013SEnji Cooper atf_tc_fail("write_fd open failed: %s",
536f44eb013SEnji Cooper strerror(errno));
537f44eb013SEnji Cooper }
538f44eb013SEnji Cooper
539d600f474SAlan Somers aio_context_init(&ac, read_fd, write_fd, FIFO_LEN);
540314b447fSAlan Somers aio_write_test(&ac, comp, sev);
541314b447fSAlan Somers aio_read_test(&ac, comp, sev);
542f44eb013SEnji Cooper
543d600f474SAlan Somers close(read_fd);
544d600f474SAlan Somers close(write_fd);
545f44eb013SEnji Cooper }
546f44eb013SEnji Cooper
54757082ce8SAlan Somers ATF_TC_WITHOUT_HEAD(fifo_kq);
ATF_TC_BODY(fifo_kq,tc)54857082ce8SAlan Somers ATF_TC_BODY(fifo_kq, tc)
54957082ce8SAlan Somers {
55057082ce8SAlan Somers aio_fifo_test(poll_kqueue, setup_kqueue());
55157082ce8SAlan Somers }
55257082ce8SAlan Somers
553740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(fifo_poll);
ATF_TC_BODY(fifo_poll,tc)554740a9bfaSAlan Somers ATF_TC_BODY(fifo_poll, tc)
555740a9bfaSAlan Somers {
556314b447fSAlan Somers aio_fifo_test(poll, NULL);
557314b447fSAlan Somers }
558314b447fSAlan Somers
559314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(fifo_signal);
ATF_TC_BODY(fifo_signal,tc)560314b447fSAlan Somers ATF_TC_BODY(fifo_signal, tc)
561314b447fSAlan Somers {
562314b447fSAlan Somers aio_fifo_test(poll_signaled, setup_signal());
563740a9bfaSAlan Somers }
564740a9bfaSAlan Somers
565740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(fifo_suspend);
ATF_TC_BODY(fifo_suspend,tc)566740a9bfaSAlan Somers ATF_TC_BODY(fifo_suspend, tc)
567740a9bfaSAlan Somers {
568314b447fSAlan Somers aio_fifo_test(suspend, NULL);
569314b447fSAlan Somers }
570314b447fSAlan Somers
571314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(fifo_thread);
ATF_TC_BODY(fifo_thread,tc)572314b447fSAlan Somers ATF_TC_BODY(fifo_thread, tc)
573314b447fSAlan Somers {
574314b447fSAlan Somers aio_fifo_test(poll_signaled, setup_thread());
575740a9bfaSAlan Somers }
576740a9bfaSAlan Somers
577740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(fifo_waitcomplete);
ATF_TC_BODY(fifo_waitcomplete,tc)578740a9bfaSAlan Somers ATF_TC_BODY(fifo_waitcomplete, tc)
579740a9bfaSAlan Somers {
580314b447fSAlan Somers aio_fifo_test(waitcomplete, NULL);
581740a9bfaSAlan Somers }
582740a9bfaSAlan Somers
583f44eb013SEnji Cooper #define UNIX_SOCKETPAIR_LEN 256
584740a9bfaSAlan Somers static void
aio_unix_socketpair_test(completion comp,struct sigevent * sev,bool vectored)585022ca2fcSAlan Somers aio_unix_socketpair_test(completion comp, struct sigevent *sev, bool vectored)
586f44eb013SEnji Cooper {
587f44eb013SEnji Cooper struct aio_context ac;
588b1012d80SJohn Baldwin struct rusage ru_before, ru_after;
589f44eb013SEnji Cooper int sockets[2];
590f44eb013SEnji Cooper
591c5dfa43aSEnji Cooper ATF_REQUIRE_KERNEL_MODULE("aio");
592f44eb013SEnji Cooper
593f44eb013SEnji Cooper ATF_REQUIRE_MSG(socketpair(PF_UNIX, SOCK_STREAM, 0, sockets) != -1,
594f44eb013SEnji Cooper "socketpair failed: %s", strerror(errno));
595f44eb013SEnji Cooper
596d600f474SAlan Somers aio_context_init(&ac, sockets[0], sockets[1], UNIX_SOCKETPAIR_LEN);
597b1012d80SJohn Baldwin ATF_REQUIRE_MSG(getrusage(RUSAGE_SELF, &ru_before) != -1,
598b1012d80SJohn Baldwin "getrusage failed: %s", strerror(errno));
599022ca2fcSAlan Somers if (vectored) {
600022ca2fcSAlan Somers aio_writev_test(&ac, comp, sev);
601022ca2fcSAlan Somers aio_readv_test(&ac, comp, sev);
602022ca2fcSAlan Somers } else {
603314b447fSAlan Somers aio_write_test(&ac, comp, sev);
604022ca2fcSAlan Somers aio_read_test(&ac, comp, sev);
605022ca2fcSAlan Somers }
606b1012d80SJohn Baldwin ATF_REQUIRE_MSG(getrusage(RUSAGE_SELF, &ru_after) != -1,
607b1012d80SJohn Baldwin "getrusage failed: %s", strerror(errno));
608b1012d80SJohn Baldwin ATF_REQUIRE(ru_after.ru_msgsnd == ru_before.ru_msgsnd + 1);
609b1012d80SJohn Baldwin ATF_REQUIRE(ru_after.ru_msgrcv == ru_before.ru_msgrcv + 1);
610f44eb013SEnji Cooper
611d600f474SAlan Somers close(sockets[0]);
612d600f474SAlan Somers close(sockets[1]);
613f44eb013SEnji Cooper }
614f44eb013SEnji Cooper
61557082ce8SAlan Somers ATF_TC_WITHOUT_HEAD(socket_kq);
ATF_TC_BODY(socket_kq,tc)61657082ce8SAlan Somers ATF_TC_BODY(socket_kq, tc)
61757082ce8SAlan Somers {
61857082ce8SAlan Somers aio_unix_socketpair_test(poll_kqueue, setup_kqueue(), false);
61957082ce8SAlan Somers }
62057082ce8SAlan Somers
621740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(socket_poll);
ATF_TC_BODY(socket_poll,tc)622740a9bfaSAlan Somers ATF_TC_BODY(socket_poll, tc)
623740a9bfaSAlan Somers {
624022ca2fcSAlan Somers aio_unix_socketpair_test(poll, NULL, false);
625314b447fSAlan Somers }
626314b447fSAlan Somers
627314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(socket_signal);
ATF_TC_BODY(socket_signal,tc)628314b447fSAlan Somers ATF_TC_BODY(socket_signal, tc)
629314b447fSAlan Somers {
630022ca2fcSAlan Somers aio_unix_socketpair_test(poll_signaled, setup_signal(), false);
631740a9bfaSAlan Somers }
632740a9bfaSAlan Somers
633740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(socket_suspend);
ATF_TC_BODY(socket_suspend,tc)634740a9bfaSAlan Somers ATF_TC_BODY(socket_suspend, tc)
635740a9bfaSAlan Somers {
636022ca2fcSAlan Somers aio_unix_socketpair_test(suspend, NULL, false);
637314b447fSAlan Somers }
638314b447fSAlan Somers
639314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(socket_thread);
ATF_TC_BODY(socket_thread,tc)640314b447fSAlan Somers ATF_TC_BODY(socket_thread, tc)
641314b447fSAlan Somers {
642022ca2fcSAlan Somers aio_unix_socketpair_test(poll_signaled, setup_thread(), false);
643740a9bfaSAlan Somers }
644740a9bfaSAlan Somers
645740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(socket_waitcomplete);
ATF_TC_BODY(socket_waitcomplete,tc)646740a9bfaSAlan Somers ATF_TC_BODY(socket_waitcomplete, tc)
647740a9bfaSAlan Somers {
648022ca2fcSAlan Somers aio_unix_socketpair_test(waitcomplete, NULL, false);
649740a9bfaSAlan Somers }
650740a9bfaSAlan Somers
651f44eb013SEnji Cooper struct aio_pty_arg {
652f44eb013SEnji Cooper int apa_read_fd;
653f44eb013SEnji Cooper int apa_write_fd;
654f44eb013SEnji Cooper };
655f44eb013SEnji Cooper
656f44eb013SEnji Cooper #define PTY_LEN 256
657740a9bfaSAlan Somers static void
aio_pty_test(completion comp,struct sigevent * sev)658314b447fSAlan Somers aio_pty_test(completion comp, struct sigevent *sev)
659f44eb013SEnji Cooper {
660f44eb013SEnji Cooper struct aio_context ac;
661f44eb013SEnji Cooper int read_fd, write_fd;
662f44eb013SEnji Cooper struct termios ts;
663f44eb013SEnji Cooper int error;
664f44eb013SEnji Cooper
665c5dfa43aSEnji Cooper ATF_REQUIRE_KERNEL_MODULE("aio");
666f3215338SJohn Baldwin ATF_REQUIRE_UNSAFE_AIO();
667f44eb013SEnji Cooper
668f44eb013SEnji Cooper ATF_REQUIRE_MSG(openpty(&read_fd, &write_fd, NULL, NULL, NULL) == 0,
669f44eb013SEnji Cooper "openpty failed: %s", strerror(errno));
670f44eb013SEnji Cooper
671f44eb013SEnji Cooper
672f44eb013SEnji Cooper if (tcgetattr(write_fd, &ts) < 0) {
673f44eb013SEnji Cooper error = errno;
674f44eb013SEnji Cooper errno = error;
675f44eb013SEnji Cooper atf_tc_fail("tcgetattr failed: %s", strerror(errno));
676f44eb013SEnji Cooper }
677f44eb013SEnji Cooper cfmakeraw(&ts);
678f44eb013SEnji Cooper if (tcsetattr(write_fd, TCSANOW, &ts) < 0) {
679f44eb013SEnji Cooper error = errno;
680f44eb013SEnji Cooper errno = error;
681f44eb013SEnji Cooper atf_tc_fail("tcsetattr failed: %s", strerror(errno));
682f44eb013SEnji Cooper }
683d600f474SAlan Somers aio_context_init(&ac, read_fd, write_fd, PTY_LEN);
684f44eb013SEnji Cooper
685314b447fSAlan Somers aio_write_test(&ac, comp, sev);
686314b447fSAlan Somers aio_read_test(&ac, comp, sev);
687f44eb013SEnji Cooper
688d600f474SAlan Somers close(read_fd);
689d600f474SAlan Somers close(write_fd);
690f44eb013SEnji Cooper }
691f44eb013SEnji Cooper
69257082ce8SAlan Somers ATF_TC_WITHOUT_HEAD(pty_kq);
ATF_TC_BODY(pty_kq,tc)69357082ce8SAlan Somers ATF_TC_BODY(pty_kq, tc)
69457082ce8SAlan Somers {
69557082ce8SAlan Somers aio_pty_test(poll_kqueue, setup_kqueue());
69657082ce8SAlan Somers }
69757082ce8SAlan Somers
698740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(pty_poll);
ATF_TC_BODY(pty_poll,tc)699740a9bfaSAlan Somers ATF_TC_BODY(pty_poll, tc)
700740a9bfaSAlan Somers {
701314b447fSAlan Somers aio_pty_test(poll, NULL);
702314b447fSAlan Somers }
703314b447fSAlan Somers
704314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(pty_signal);
ATF_TC_BODY(pty_signal,tc)705314b447fSAlan Somers ATF_TC_BODY(pty_signal, tc)
706314b447fSAlan Somers {
707314b447fSAlan Somers aio_pty_test(poll_signaled, setup_signal());
708740a9bfaSAlan Somers }
709740a9bfaSAlan Somers
710740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(pty_suspend);
ATF_TC_BODY(pty_suspend,tc)711740a9bfaSAlan Somers ATF_TC_BODY(pty_suspend, tc)
712740a9bfaSAlan Somers {
713314b447fSAlan Somers aio_pty_test(suspend, NULL);
714314b447fSAlan Somers }
715314b447fSAlan Somers
716314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(pty_thread);
ATF_TC_BODY(pty_thread,tc)717314b447fSAlan Somers ATF_TC_BODY(pty_thread, tc)
718314b447fSAlan Somers {
719314b447fSAlan Somers aio_pty_test(poll_signaled, setup_thread());
720740a9bfaSAlan Somers }
721740a9bfaSAlan Somers
722740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(pty_waitcomplete);
ATF_TC_BODY(pty_waitcomplete,tc)723740a9bfaSAlan Somers ATF_TC_BODY(pty_waitcomplete, tc)
724740a9bfaSAlan Somers {
725314b447fSAlan Somers aio_pty_test(waitcomplete, NULL);
726740a9bfaSAlan Somers }
727740a9bfaSAlan Somers
728f44eb013SEnji Cooper #define PIPE_LEN 256
729740a9bfaSAlan Somers static void
aio_pipe_test(completion comp,struct sigevent * sev)730314b447fSAlan Somers aio_pipe_test(completion comp, struct sigevent *sev)
731f44eb013SEnji Cooper {
732f44eb013SEnji Cooper struct aio_context ac;
733f44eb013SEnji Cooper int pipes[2];
734f44eb013SEnji Cooper
735c5dfa43aSEnji Cooper ATF_REQUIRE_KERNEL_MODULE("aio");
736f3215338SJohn Baldwin ATF_REQUIRE_UNSAFE_AIO();
737f44eb013SEnji Cooper
738f44eb013SEnji Cooper ATF_REQUIRE_MSG(pipe(pipes) != -1,
739f44eb013SEnji Cooper "pipe failed: %s", strerror(errno));
740f44eb013SEnji Cooper
741d600f474SAlan Somers aio_context_init(&ac, pipes[0], pipes[1], PIPE_LEN);
742314b447fSAlan Somers aio_write_test(&ac, comp, sev);
743314b447fSAlan Somers aio_read_test(&ac, comp, sev);
744f44eb013SEnji Cooper
745d600f474SAlan Somers close(pipes[0]);
746d600f474SAlan Somers close(pipes[1]);
747f44eb013SEnji Cooper }
748f44eb013SEnji Cooper
74957082ce8SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_kq);
ATF_TC_BODY(pipe_kq,tc)75057082ce8SAlan Somers ATF_TC_BODY(pipe_kq, tc)
75157082ce8SAlan Somers {
75257082ce8SAlan Somers aio_pipe_test(poll_kqueue, setup_kqueue());
75357082ce8SAlan Somers }
75457082ce8SAlan Somers
755740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(pipe_poll);
ATF_TC_BODY(pipe_poll,tc)756740a9bfaSAlan Somers ATF_TC_BODY(pipe_poll, tc)
757740a9bfaSAlan Somers {
758314b447fSAlan Somers aio_pipe_test(poll, NULL);
759314b447fSAlan Somers }
760314b447fSAlan Somers
761314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(pipe_signal);
ATF_TC_BODY(pipe_signal,tc)762314b447fSAlan Somers ATF_TC_BODY(pipe_signal, tc)
763314b447fSAlan Somers {
764314b447fSAlan Somers aio_pipe_test(poll_signaled, setup_signal());
765740a9bfaSAlan Somers }
766740a9bfaSAlan Somers
767740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(pipe_suspend);
ATF_TC_BODY(pipe_suspend,tc)768740a9bfaSAlan Somers ATF_TC_BODY(pipe_suspend, tc)
769740a9bfaSAlan Somers {
770314b447fSAlan Somers aio_pipe_test(suspend, NULL);
771314b447fSAlan Somers }
772314b447fSAlan Somers
773314b447fSAlan Somers ATF_TC_WITHOUT_HEAD(pipe_thread);
ATF_TC_BODY(pipe_thread,tc)774314b447fSAlan Somers ATF_TC_BODY(pipe_thread, tc)
775314b447fSAlan Somers {
776314b447fSAlan Somers aio_pipe_test(poll_signaled, setup_thread());
777740a9bfaSAlan Somers }
778740a9bfaSAlan Somers
779740a9bfaSAlan Somers ATF_TC_WITHOUT_HEAD(pipe_waitcomplete);
ATF_TC_BODY(pipe_waitcomplete,tc)780740a9bfaSAlan Somers ATF_TC_BODY(pipe_waitcomplete, tc)
781740a9bfaSAlan Somers {
782314b447fSAlan Somers aio_pipe_test(waitcomplete, NULL);
783740a9bfaSAlan Somers }
784740a9bfaSAlan Somers
785d600f474SAlan Somers #define MD_LEN GLOBAL_MAX
786d600f474SAlan Somers #define MDUNIT_LINK "mdunit_link"
787f44eb013SEnji Cooper
788022ca2fcSAlan Somers static int
aio_md_setup(void)789022ca2fcSAlan Somers aio_md_setup(void)
790f44eb013SEnji Cooper {
791f44eb013SEnji Cooper int error, fd, mdctl_fd, unit;
792f44eb013SEnji Cooper char pathname[PATH_MAX];
793f44eb013SEnji Cooper struct md_ioctl mdio;
794d600f474SAlan Somers char buf[80];
795f44eb013SEnji Cooper
796c5dfa43aSEnji Cooper ATF_REQUIRE_KERNEL_MODULE("aio");
797f44eb013SEnji Cooper
798f44eb013SEnji Cooper mdctl_fd = open("/dev/" MDCTL_NAME, O_RDWR, 0);
799f44eb013SEnji Cooper ATF_REQUIRE_MSG(mdctl_fd != -1,
800f44eb013SEnji Cooper "opening /dev/%s failed: %s", MDCTL_NAME, strerror(errno));
801f44eb013SEnji Cooper
802f44eb013SEnji Cooper bzero(&mdio, sizeof(mdio));
803f44eb013SEnji Cooper mdio.md_version = MDIOVERSION;
804f44eb013SEnji Cooper mdio.md_type = MD_MALLOC;
805f44eb013SEnji Cooper mdio.md_options = MD_AUTOUNIT | MD_COMPRESS;
806f44eb013SEnji Cooper mdio.md_mediasize = GLOBAL_MAX;
807f44eb013SEnji Cooper mdio.md_sectorsize = 512;
8089666cda9SEric van Gyzen strlcpy(buf, __func__, sizeof(buf));
8099666cda9SEric van Gyzen mdio.md_label = buf;
810f44eb013SEnji Cooper
811f44eb013SEnji Cooper if (ioctl(mdctl_fd, MDIOCATTACH, &mdio) < 0) {
812f44eb013SEnji Cooper error = errno;
813f44eb013SEnji Cooper errno = error;
814f44eb013SEnji Cooper atf_tc_fail("ioctl MDIOCATTACH failed: %s", strerror(errno));
815f44eb013SEnji Cooper }
816d600f474SAlan Somers close(mdctl_fd);
817f44eb013SEnji Cooper
818d600f474SAlan Somers /* Store the md unit number in a symlink for future cleanup */
819d600f474SAlan Somers unit = mdio.md_unit;
820d600f474SAlan Somers snprintf(buf, sizeof(buf), "%d", unit);
821d600f474SAlan Somers ATF_REQUIRE_EQ(0, symlink(buf, MDUNIT_LINK));
822f44eb013SEnji Cooper snprintf(pathname, PATH_MAX, "/dev/md%d", unit);
823f44eb013SEnji Cooper fd = open(pathname, O_RDWR);
824f44eb013SEnji Cooper ATF_REQUIRE_MSG(fd != -1,
825f44eb013SEnji Cooper "opening %s failed: %s", pathname, strerror(errno));
826f44eb013SEnji Cooper
827022ca2fcSAlan Somers return (fd);
828022ca2fcSAlan Somers }
829022ca2fcSAlan Somers
830022ca2fcSAlan Somers static void
aio_md_cleanup(void)831022ca2fcSAlan Somers aio_md_cleanup(void)
832022ca2fcSAlan Somers {
833022ca2fcSAlan Somers struct md_ioctl mdio;
834c6f92e64SEric van Gyzen int mdctl_fd, n, unit;
835022ca2fcSAlan Somers char buf[80];
836022ca2fcSAlan Somers
837022ca2fcSAlan Somers mdctl_fd = open("/dev/" MDCTL_NAME, O_RDWR, 0);
838c6f92e64SEric van Gyzen if (mdctl_fd < 0) {
839c6f92e64SEric van Gyzen fprintf(stderr, "opening /dev/%s failed: %s\n", MDCTL_NAME,
840c6f92e64SEric van Gyzen strerror(errno));
841c6f92e64SEric van Gyzen return;
842c6f92e64SEric van Gyzen }
843ea0e1b19SEric van Gyzen n = readlink(MDUNIT_LINK, buf, sizeof(buf) - 1);
844022ca2fcSAlan Somers if (n > 0) {
845ea0e1b19SEric van Gyzen buf[n] = '\0';
846022ca2fcSAlan Somers if (sscanf(buf, "%d", &unit) == 1 && unit >= 0) {
847022ca2fcSAlan Somers bzero(&mdio, sizeof(mdio));
848022ca2fcSAlan Somers mdio.md_version = MDIOVERSION;
849022ca2fcSAlan Somers mdio.md_unit = unit;
850022ca2fcSAlan Somers if (ioctl(mdctl_fd, MDIOCDETACH, &mdio) == -1) {
851c6f92e64SEric van Gyzen fprintf(stderr,
852c6f92e64SEric van Gyzen "ioctl MDIOCDETACH unit %d failed: %s\n",
853c6f92e64SEric van Gyzen unit, strerror(errno));
854022ca2fcSAlan Somers }
855022ca2fcSAlan Somers }
856022ca2fcSAlan Somers }
857022ca2fcSAlan Somers
858022ca2fcSAlan Somers close(mdctl_fd);
859022ca2fcSAlan Somers }
860022ca2fcSAlan Somers
861022ca2fcSAlan Somers static void
aio_md_test(completion comp,struct sigevent * sev,bool vectored)862022ca2fcSAlan Somers aio_md_test(completion comp, struct sigevent *sev, bool vectored)
863022ca2fcSAlan Somers {
864022ca2fcSAlan Somers struct aio_context ac;
865022ca2fcSAlan Somers int fd;
866022ca2fcSAlan Somers
867022ca2fcSAlan Somers fd = aio_md_setup();
868d600f474SAlan Somers aio_context_init(&ac, fd, fd, MD_LEN);
869022ca2fcSAlan Somers if (vectored) {
870022ca2fcSAlan Somers aio_writev_test(&ac, comp, sev);
871022ca2fcSAlan Somers aio_readv_test(&ac, comp, sev);
872022ca2fcSAlan Somers } else {
873314b447fSAlan Somers aio_write_test(&ac, comp, sev);
874314b447fSAlan Somers aio_read_test(&ac, comp, sev);
875022ca2fcSAlan Somers }
876f44eb013SEnji Cooper
877d600f474SAlan Somers close(fd);
878f44eb013SEnji Cooper }
879f44eb013SEnji Cooper
88057082ce8SAlan Somers ATF_TC_WITH_CLEANUP(md_kq);
ATF_TC_HEAD(md_kq,tc)88157082ce8SAlan Somers ATF_TC_HEAD(md_kq, tc)
88257082ce8SAlan Somers {
88357082ce8SAlan Somers
88457082ce8SAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
88557082ce8SAlan Somers }
ATF_TC_BODY(md_kq,tc)88657082ce8SAlan Somers ATF_TC_BODY(md_kq, tc)
88757082ce8SAlan Somers {
88857082ce8SAlan Somers aio_md_test(poll_kqueue, setup_kqueue(), false);
88957082ce8SAlan Somers }
ATF_TC_CLEANUP(md_kq,tc)89057082ce8SAlan Somers ATF_TC_CLEANUP(md_kq, tc)
89157082ce8SAlan Somers {
89257082ce8SAlan Somers aio_md_cleanup();
89357082ce8SAlan Somers }
89457082ce8SAlan Somers
895d600f474SAlan Somers ATF_TC_WITH_CLEANUP(md_poll);
ATF_TC_HEAD(md_poll,tc)896740a9bfaSAlan Somers ATF_TC_HEAD(md_poll, tc)
897740a9bfaSAlan Somers {
898740a9bfaSAlan Somers
899740a9bfaSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
900740a9bfaSAlan Somers }
ATF_TC_BODY(md_poll,tc)901740a9bfaSAlan Somers ATF_TC_BODY(md_poll, tc)
902740a9bfaSAlan Somers {
903022ca2fcSAlan Somers aio_md_test(poll, NULL, false);
904740a9bfaSAlan Somers }
ATF_TC_CLEANUP(md_poll,tc)905d600f474SAlan Somers ATF_TC_CLEANUP(md_poll, tc)
906d600f474SAlan Somers {
907d600f474SAlan Somers aio_md_cleanup();
908d600f474SAlan Somers }
909740a9bfaSAlan Somers
910314b447fSAlan Somers ATF_TC_WITH_CLEANUP(md_signal);
ATF_TC_HEAD(md_signal,tc)911314b447fSAlan Somers ATF_TC_HEAD(md_signal, tc)
912314b447fSAlan Somers {
913314b447fSAlan Somers
914314b447fSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
915314b447fSAlan Somers }
ATF_TC_BODY(md_signal,tc)916314b447fSAlan Somers ATF_TC_BODY(md_signal, tc)
917314b447fSAlan Somers {
918022ca2fcSAlan Somers aio_md_test(poll_signaled, setup_signal(), false);
919314b447fSAlan Somers }
ATF_TC_CLEANUP(md_signal,tc)920314b447fSAlan Somers ATF_TC_CLEANUP(md_signal, tc)
921314b447fSAlan Somers {
922314b447fSAlan Somers aio_md_cleanup();
923314b447fSAlan Somers }
924314b447fSAlan Somers
925d600f474SAlan Somers ATF_TC_WITH_CLEANUP(md_suspend);
ATF_TC_HEAD(md_suspend,tc)926740a9bfaSAlan Somers ATF_TC_HEAD(md_suspend, tc)
927740a9bfaSAlan Somers {
928740a9bfaSAlan Somers
929740a9bfaSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
930740a9bfaSAlan Somers }
ATF_TC_BODY(md_suspend,tc)931740a9bfaSAlan Somers ATF_TC_BODY(md_suspend, tc)
932740a9bfaSAlan Somers {
933022ca2fcSAlan Somers aio_md_test(suspend, NULL, false);
934740a9bfaSAlan Somers }
ATF_TC_CLEANUP(md_suspend,tc)935d600f474SAlan Somers ATF_TC_CLEANUP(md_suspend, tc)
936d600f474SAlan Somers {
937d600f474SAlan Somers aio_md_cleanup();
938d600f474SAlan Somers }
939740a9bfaSAlan Somers
940314b447fSAlan Somers ATF_TC_WITH_CLEANUP(md_thread);
ATF_TC_HEAD(md_thread,tc)941314b447fSAlan Somers ATF_TC_HEAD(md_thread, tc)
942314b447fSAlan Somers {
943314b447fSAlan Somers
944314b447fSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
945314b447fSAlan Somers }
ATF_TC_BODY(md_thread,tc)946314b447fSAlan Somers ATF_TC_BODY(md_thread, tc)
947314b447fSAlan Somers {
948022ca2fcSAlan Somers aio_md_test(poll_signaled, setup_thread(), false);
949314b447fSAlan Somers }
ATF_TC_CLEANUP(md_thread,tc)950314b447fSAlan Somers ATF_TC_CLEANUP(md_thread, tc)
951314b447fSAlan Somers {
952314b447fSAlan Somers aio_md_cleanup();
953314b447fSAlan Somers }
954314b447fSAlan Somers
955d600f474SAlan Somers ATF_TC_WITH_CLEANUP(md_waitcomplete);
ATF_TC_HEAD(md_waitcomplete,tc)956740a9bfaSAlan Somers ATF_TC_HEAD(md_waitcomplete, tc)
957740a9bfaSAlan Somers {
958740a9bfaSAlan Somers
959740a9bfaSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
960740a9bfaSAlan Somers }
ATF_TC_BODY(md_waitcomplete,tc)961740a9bfaSAlan Somers ATF_TC_BODY(md_waitcomplete, tc)
962740a9bfaSAlan Somers {
963022ca2fcSAlan Somers aio_md_test(waitcomplete, NULL, false);
964740a9bfaSAlan Somers }
ATF_TC_CLEANUP(md_waitcomplete,tc)965d600f474SAlan Somers ATF_TC_CLEANUP(md_waitcomplete, tc)
966d600f474SAlan Somers {
967d600f474SAlan Somers aio_md_cleanup();
968d600f474SAlan Somers }
969740a9bfaSAlan Somers
970022ca2fcSAlan Somers #define ZVOL_VDEV_PATHNAME "test_vdev"
971022ca2fcSAlan Somers #define POOL_SIZE (1 << 28) /* 256 MB */
972022ca2fcSAlan Somers #define ZVOL_SIZE "64m"
973022ca2fcSAlan Somers #define POOL_NAME "aio_testpool"
974022ca2fcSAlan Somers #define ZVOL_NAME "aio_testvol"
975022ca2fcSAlan Somers
976022ca2fcSAlan Somers static int
aio_zvol_setup(const char * unique)977*9cefc0fbSMark Johnston aio_zvol_setup(const char *unique)
978022ca2fcSAlan Somers {
979022ca2fcSAlan Somers FILE *pidfile;
980022ca2fcSAlan Somers int fd;
981022ca2fcSAlan Somers pid_t pid;
982*9cefc0fbSMark Johnston char vdev_name[160];
983022ca2fcSAlan Somers char pool_name[80];
984022ca2fcSAlan Somers char cmd[160];
985022ca2fcSAlan Somers char zvol_name[160];
986022ca2fcSAlan Somers char devname[160];
987022ca2fcSAlan Somers
988022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
989022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("zfs");
990022ca2fcSAlan Somers
991*9cefc0fbSMark Johnston pid = getpid();
992*9cefc0fbSMark Johnston snprintf(vdev_name, sizeof(vdev_name), "%s", ZVOL_VDEV_PATHNAME);
993*9cefc0fbSMark Johnston snprintf(pool_name, sizeof(pool_name), "%s_%s.%d", POOL_NAME, unique,
994*9cefc0fbSMark Johnston pid);
995*9cefc0fbSMark Johnston snprintf(zvol_name, sizeof(zvol_name), "%s/%s_%s", pool_name, ZVOL_NAME,
996*9cefc0fbSMark Johnston unique);
997*9cefc0fbSMark Johnston
998*9cefc0fbSMark Johnston fd = open(vdev_name, O_RDWR | O_CREAT, 0600);
999022ca2fcSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1000022ca2fcSAlan Somers ATF_REQUIRE_EQ_MSG(0,
1001022ca2fcSAlan Somers ftruncate(fd, POOL_SIZE), "ftruncate failed: %s", strerror(errno));
1002022ca2fcSAlan Somers close(fd);
1003022ca2fcSAlan Somers
1004022ca2fcSAlan Somers pidfile = fopen("pidfile", "w");
1005022ca2fcSAlan Somers ATF_REQUIRE_MSG(NULL != pidfile, "fopen: %s", strerror(errno));
1006022ca2fcSAlan Somers fprintf(pidfile, "%d", pid);
1007022ca2fcSAlan Somers fclose(pidfile);
1008022ca2fcSAlan Somers
1009*9cefc0fbSMark Johnston snprintf(cmd, sizeof(cmd), "zpool create %s $PWD/%s", pool_name,
1010*9cefc0fbSMark Johnston vdev_name);
1011022ca2fcSAlan Somers ATF_REQUIRE_EQ_MSG(0, system(cmd),
1012022ca2fcSAlan Somers "zpool create failed: %s", strerror(errno));
1013022ca2fcSAlan Somers snprintf(cmd, sizeof(cmd),
1014*9cefc0fbSMark Johnston "zfs create -o volblocksize=8192 -o volmode=dev -V %s %s",
1015*9cefc0fbSMark Johnston ZVOL_SIZE, zvol_name);
1016022ca2fcSAlan Somers ATF_REQUIRE_EQ_MSG(0, system(cmd),
1017022ca2fcSAlan Somers "zfs create failed: %s", strerror(errno));
1018022ca2fcSAlan Somers
1019022ca2fcSAlan Somers snprintf(devname, sizeof(devname), "/dev/zvol/%s", zvol_name);
1020022ca2fcSAlan Somers do {
1021022ca2fcSAlan Somers fd = open(devname, O_RDWR);
1022022ca2fcSAlan Somers } while (fd == -1 && errno == EINTR);
1023022ca2fcSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1024022ca2fcSAlan Somers return (fd);
1025022ca2fcSAlan Somers }
1026022ca2fcSAlan Somers
1027022ca2fcSAlan Somers static void
aio_zvol_cleanup(const char * unique)1028*9cefc0fbSMark Johnston aio_zvol_cleanup(const char *unique)
1029022ca2fcSAlan Somers {
1030022ca2fcSAlan Somers FILE *pidfile;
1031022ca2fcSAlan Somers pid_t testpid;
1032022ca2fcSAlan Somers char cmd[160];
1033022ca2fcSAlan Somers
1034022ca2fcSAlan Somers pidfile = fopen("pidfile", "r");
103519cca0b9SAlan Somers if (pidfile == NULL && errno == ENOENT) {
103619cca0b9SAlan Somers /* Setup probably failed */
103719cca0b9SAlan Somers return;
103819cca0b9SAlan Somers }
1039022ca2fcSAlan Somers ATF_REQUIRE_MSG(NULL != pidfile, "fopen: %s", strerror(errno));
1040022ca2fcSAlan Somers ATF_REQUIRE_EQ(1, fscanf(pidfile, "%d", &testpid));
1041022ca2fcSAlan Somers fclose(pidfile);
1042022ca2fcSAlan Somers
1043*9cefc0fbSMark Johnston snprintf(cmd, sizeof(cmd), "zpool destroy %s_%s.%d", POOL_NAME, unique,
1044*9cefc0fbSMark Johnston testpid);
1045022ca2fcSAlan Somers system(cmd);
1046022ca2fcSAlan Somers }
1047022ca2fcSAlan Somers
1048022ca2fcSAlan Somers
1049bb430bc7SJohn Baldwin ATF_TC_WITHOUT_HEAD(aio_large_read_test);
ATF_TC_BODY(aio_large_read_test,tc)1050bb430bc7SJohn Baldwin ATF_TC_BODY(aio_large_read_test, tc)
1051bb430bc7SJohn Baldwin {
1052bb430bc7SJohn Baldwin struct aiocb cb, *cbp;
1053bb430bc7SJohn Baldwin ssize_t nread;
1054bb430bc7SJohn Baldwin size_t len;
1055bb430bc7SJohn Baldwin int fd;
1056bb430bc7SJohn Baldwin #ifdef __LP64__
1057bb430bc7SJohn Baldwin int clamped;
1058bb430bc7SJohn Baldwin #endif
1059bb430bc7SJohn Baldwin
1060bb430bc7SJohn Baldwin ATF_REQUIRE_KERNEL_MODULE("aio");
1061bb430bc7SJohn Baldwin ATF_REQUIRE_UNSAFE_AIO();
1062bb430bc7SJohn Baldwin
1063bb430bc7SJohn Baldwin #ifdef __LP64__
1064bb430bc7SJohn Baldwin len = sizeof(clamped);
1065bb430bc7SJohn Baldwin if (sysctlbyname("debug.iosize_max_clamp", &clamped, &len, NULL, 0) ==
1066bb430bc7SJohn Baldwin -1)
1067bb430bc7SJohn Baldwin atf_libc_error(errno, "Failed to read debug.iosize_max_clamp");
1068bb430bc7SJohn Baldwin #endif
1069bb430bc7SJohn Baldwin
1070bb430bc7SJohn Baldwin /* Determine the maximum supported read(2) size. */
1071bb430bc7SJohn Baldwin len = SSIZE_MAX;
1072bb430bc7SJohn Baldwin #ifdef __LP64__
1073bb430bc7SJohn Baldwin if (clamped)
1074bb430bc7SJohn Baldwin len = INT_MAX;
1075bb430bc7SJohn Baldwin #endif
1076bb430bc7SJohn Baldwin
10779086b30bSJilles Tjoelker fd = open(FILE_PATHNAME, O_RDWR | O_CREAT, 0600);
1078740a9bfaSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1079bb430bc7SJohn Baldwin
1080740a9bfaSAlan Somers unlink(FILE_PATHNAME);
1081bb430bc7SJohn Baldwin
1082bb430bc7SJohn Baldwin memset(&cb, 0, sizeof(cb));
1083bb430bc7SJohn Baldwin cb.aio_nbytes = len;
1084bb430bc7SJohn Baldwin cb.aio_fildes = fd;
1085bb430bc7SJohn Baldwin cb.aio_buf = NULL;
1086bb430bc7SJohn Baldwin if (aio_read(&cb) == -1)
1087bb430bc7SJohn Baldwin atf_tc_fail("aio_read() of maximum read size failed: %s",
1088bb430bc7SJohn Baldwin strerror(errno));
1089bb430bc7SJohn Baldwin
1090bb430bc7SJohn Baldwin nread = aio_waitcomplete(&cbp, NULL);
1091bb430bc7SJohn Baldwin if (nread == -1)
1092bb430bc7SJohn Baldwin atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
1093bb430bc7SJohn Baldwin if (nread != 0)
1094c03094a4SJohn Baldwin atf_tc_fail("aio_read() from empty file returned data: %zd",
1095bb430bc7SJohn Baldwin nread);
1096bb430bc7SJohn Baldwin
1097bb430bc7SJohn Baldwin memset(&cb, 0, sizeof(cb));
1098bb430bc7SJohn Baldwin cb.aio_nbytes = len + 1;
1099bb430bc7SJohn Baldwin cb.aio_fildes = fd;
1100bb430bc7SJohn Baldwin cb.aio_buf = NULL;
1101bb430bc7SJohn Baldwin if (aio_read(&cb) == -1) {
1102bb430bc7SJohn Baldwin if (errno == EINVAL)
1103bb430bc7SJohn Baldwin goto finished;
1104bb430bc7SJohn Baldwin atf_tc_fail("aio_read() of too large read size failed: %s",
1105bb430bc7SJohn Baldwin strerror(errno));
1106bb430bc7SJohn Baldwin }
1107bb430bc7SJohn Baldwin
1108bb430bc7SJohn Baldwin nread = aio_waitcomplete(&cbp, NULL);
1109bb430bc7SJohn Baldwin if (nread == -1) {
1110bb430bc7SJohn Baldwin if (errno == EINVAL)
1111bb430bc7SJohn Baldwin goto finished;
1112bb430bc7SJohn Baldwin atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
1113bb430bc7SJohn Baldwin }
1114c03094a4SJohn Baldwin atf_tc_fail("aio_read() of too large read size returned: %zd", nread);
1115bb430bc7SJohn Baldwin
1116bb430bc7SJohn Baldwin finished:
1117bb430bc7SJohn Baldwin close(fd);
1118bb430bc7SJohn Baldwin }
1119bb430bc7SJohn Baldwin
1120d1ad1a73SJohn Baldwin /*
1121d1ad1a73SJohn Baldwin * This tests for a bug where arriving socket data can wakeup multiple
1122d1ad1a73SJohn Baldwin * AIO read requests resulting in an uncancellable request.
1123d1ad1a73SJohn Baldwin */
1124d1ad1a73SJohn Baldwin ATF_TC_WITHOUT_HEAD(aio_socket_two_reads);
ATF_TC_BODY(aio_socket_two_reads,tc)1125d1ad1a73SJohn Baldwin ATF_TC_BODY(aio_socket_two_reads, tc)
1126d1ad1a73SJohn Baldwin {
1127d1ad1a73SJohn Baldwin struct ioreq {
1128d1ad1a73SJohn Baldwin struct aiocb iocb;
1129d1ad1a73SJohn Baldwin char buffer[1024];
1130d1ad1a73SJohn Baldwin } ioreq[2];
1131d1ad1a73SJohn Baldwin struct aiocb *iocb;
1132d1ad1a73SJohn Baldwin unsigned i;
1133d1ad1a73SJohn Baldwin int s[2];
1134d1ad1a73SJohn Baldwin char c;
1135d1ad1a73SJohn Baldwin
1136d1ad1a73SJohn Baldwin ATF_REQUIRE_KERNEL_MODULE("aio");
1137d1ad1a73SJohn Baldwin #if __FreeBSD_version < 1100101
1138d1ad1a73SJohn Baldwin aft_tc_skip("kernel version %d is too old (%d required)",
1139d1ad1a73SJohn Baldwin __FreeBSD_version, 1100101);
1140d1ad1a73SJohn Baldwin #endif
1141d1ad1a73SJohn Baldwin
1142d1ad1a73SJohn Baldwin ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, s) != -1);
1143d1ad1a73SJohn Baldwin
1144d1ad1a73SJohn Baldwin /* Queue two read requests. */
1145d1ad1a73SJohn Baldwin memset(&ioreq, 0, sizeof(ioreq));
1146d1ad1a73SJohn Baldwin for (i = 0; i < nitems(ioreq); i++) {
1147d1ad1a73SJohn Baldwin ioreq[i].iocb.aio_nbytes = sizeof(ioreq[i].buffer);
1148d1ad1a73SJohn Baldwin ioreq[i].iocb.aio_fildes = s[0];
1149d1ad1a73SJohn Baldwin ioreq[i].iocb.aio_buf = ioreq[i].buffer;
1150d1ad1a73SJohn Baldwin ATF_REQUIRE(aio_read(&ioreq[i].iocb) == 0);
1151d1ad1a73SJohn Baldwin }
1152d1ad1a73SJohn Baldwin
1153d1ad1a73SJohn Baldwin /* Send a single byte. This should complete one request. */
1154d1ad1a73SJohn Baldwin c = 0xc3;
1155d1ad1a73SJohn Baldwin ATF_REQUIRE(write(s[1], &c, sizeof(c)) == 1);
1156d1ad1a73SJohn Baldwin
1157d1ad1a73SJohn Baldwin ATF_REQUIRE(aio_waitcomplete(&iocb, NULL) == 1);
1158d1ad1a73SJohn Baldwin
1159d1ad1a73SJohn Baldwin /* Determine which request completed and verify the data was read. */
1160d1ad1a73SJohn Baldwin if (iocb == &ioreq[0].iocb)
1161d1ad1a73SJohn Baldwin i = 0;
1162d1ad1a73SJohn Baldwin else
1163d1ad1a73SJohn Baldwin i = 1;
1164d1ad1a73SJohn Baldwin ATF_REQUIRE(ioreq[i].buffer[0] == c);
1165d1ad1a73SJohn Baldwin
1166d1ad1a73SJohn Baldwin i ^= 1;
1167d1ad1a73SJohn Baldwin
1168d1ad1a73SJohn Baldwin /*
1169d1ad1a73SJohn Baldwin * Try to cancel the other request. On broken systems this
1170d1ad1a73SJohn Baldwin * will fail and the process will hang on exit.
1171d1ad1a73SJohn Baldwin */
1172d1ad1a73SJohn Baldwin ATF_REQUIRE(aio_error(&ioreq[i].iocb) == EINPROGRESS);
1173d1ad1a73SJohn Baldwin ATF_REQUIRE(aio_cancel(s[0], &ioreq[i].iocb) == AIO_CANCELED);
1174d1ad1a73SJohn Baldwin
1175d1ad1a73SJohn Baldwin close(s[1]);
1176d1ad1a73SJohn Baldwin close(s[0]);
1177d1ad1a73SJohn Baldwin }
1178d1ad1a73SJohn Baldwin
1179022ca2fcSAlan Somers static void
aio_socket_blocking_short_write_test(bool vectored)1180022ca2fcSAlan Somers aio_socket_blocking_short_write_test(bool vectored)
11811717b68aSJohn Baldwin {
11821717b68aSJohn Baldwin struct aiocb iocb, *iocbp;
1183022ca2fcSAlan Somers struct iovec iov[2];
11841717b68aSJohn Baldwin char *buffer[2];
1185022ca2fcSAlan Somers ssize_t done, r;
11861717b68aSJohn Baldwin int buffer_size, sb_size;
11871717b68aSJohn Baldwin socklen_t len;
11881717b68aSJohn Baldwin int s[2];
11891717b68aSJohn Baldwin
11901717b68aSJohn Baldwin ATF_REQUIRE_KERNEL_MODULE("aio");
11911717b68aSJohn Baldwin
11921717b68aSJohn Baldwin ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, s) != -1);
11931717b68aSJohn Baldwin
11941717b68aSJohn Baldwin len = sizeof(sb_size);
11951717b68aSJohn Baldwin ATF_REQUIRE(getsockopt(s[0], SOL_SOCKET, SO_RCVBUF, &sb_size, &len) !=
11961717b68aSJohn Baldwin -1);
11971717b68aSJohn Baldwin ATF_REQUIRE(len == sizeof(sb_size));
11981717b68aSJohn Baldwin buffer_size = sb_size;
11991717b68aSJohn Baldwin
12001717b68aSJohn Baldwin ATF_REQUIRE(getsockopt(s[1], SOL_SOCKET, SO_SNDBUF, &sb_size, &len) !=
12011717b68aSJohn Baldwin -1);
12021717b68aSJohn Baldwin ATF_REQUIRE(len == sizeof(sb_size));
12031717b68aSJohn Baldwin if (sb_size > buffer_size)
12041717b68aSJohn Baldwin buffer_size = sb_size;
12051717b68aSJohn Baldwin
12061717b68aSJohn Baldwin /*
12071717b68aSJohn Baldwin * Use twice the size of the MAX(receive buffer, send buffer)
12081717b68aSJohn Baldwin * to ensure that the write is split up into multiple writes
12091717b68aSJohn Baldwin * internally.
12101717b68aSJohn Baldwin */
12111717b68aSJohn Baldwin buffer_size *= 2;
12121717b68aSJohn Baldwin
12131717b68aSJohn Baldwin buffer[0] = malloc(buffer_size);
12141717b68aSJohn Baldwin ATF_REQUIRE(buffer[0] != NULL);
12151717b68aSJohn Baldwin buffer[1] = malloc(buffer_size);
12161717b68aSJohn Baldwin ATF_REQUIRE(buffer[1] != NULL);
12171717b68aSJohn Baldwin
12181717b68aSJohn Baldwin srandomdev();
12191717b68aSJohn Baldwin aio_fill_buffer(buffer[1], buffer_size, random());
12201717b68aSJohn Baldwin
12211717b68aSJohn Baldwin memset(&iocb, 0, sizeof(iocb));
12221717b68aSJohn Baldwin iocb.aio_fildes = s[1];
1223022ca2fcSAlan Somers if (vectored) {
1224022ca2fcSAlan Somers iov[0].iov_base = buffer[1];
1225022ca2fcSAlan Somers iov[0].iov_len = buffer_size / 2 + 1;
1226022ca2fcSAlan Somers iov[1].iov_base = buffer[1] + buffer_size / 2 + 1;
1227022ca2fcSAlan Somers iov[1].iov_len = buffer_size / 2 - 1;
1228022ca2fcSAlan Somers iocb.aio_iov = iov;
1229022ca2fcSAlan Somers iocb.aio_iovcnt = 2;
1230022ca2fcSAlan Somers r = aio_writev(&iocb);
1231022ca2fcSAlan Somers ATF_CHECK_EQ_MSG(0, r, "aio_writev returned %zd", r);
1232022ca2fcSAlan Somers } else {
12331717b68aSJohn Baldwin iocb.aio_buf = buffer[1];
12341717b68aSJohn Baldwin iocb.aio_nbytes = buffer_size;
1235022ca2fcSAlan Somers r = aio_write(&iocb);
1236022ca2fcSAlan Somers ATF_CHECK_EQ_MSG(0, r, "aio_writev returned %zd", r);
1237022ca2fcSAlan Somers }
12381717b68aSJohn Baldwin
12391717b68aSJohn Baldwin done = recv(s[0], buffer[0], buffer_size, MSG_WAITALL);
12401717b68aSJohn Baldwin ATF_REQUIRE(done == buffer_size);
12411717b68aSJohn Baldwin
12421717b68aSJohn Baldwin done = aio_waitcomplete(&iocbp, NULL);
12431717b68aSJohn Baldwin ATF_REQUIRE(iocbp == &iocb);
12441717b68aSJohn Baldwin ATF_REQUIRE(done == buffer_size);
12451717b68aSJohn Baldwin
12461717b68aSJohn Baldwin ATF_REQUIRE(memcmp(buffer[0], buffer[1], buffer_size) == 0);
12471717b68aSJohn Baldwin
12481717b68aSJohn Baldwin close(s[1]);
12491717b68aSJohn Baldwin close(s[0]);
12501717b68aSJohn Baldwin }
12511717b68aSJohn Baldwin
1252778ce4f2SJohn Baldwin /*
1253022ca2fcSAlan Somers * This test ensures that aio_write() on a blocking socket of a "large"
1254022ca2fcSAlan Somers * buffer does not return a short completion.
1255022ca2fcSAlan Somers */
1256022ca2fcSAlan Somers ATF_TC_WITHOUT_HEAD(aio_socket_blocking_short_write);
ATF_TC_BODY(aio_socket_blocking_short_write,tc)1257022ca2fcSAlan Somers ATF_TC_BODY(aio_socket_blocking_short_write, tc)
1258022ca2fcSAlan Somers {
1259022ca2fcSAlan Somers aio_socket_blocking_short_write_test(false);
1260022ca2fcSAlan Somers }
1261022ca2fcSAlan Somers
1262022ca2fcSAlan Somers /*
1263022ca2fcSAlan Somers * Like aio_socket_blocking_short_write, but also tests that partially
1264022ca2fcSAlan Somers * completed vectored sends can be retried correctly.
1265022ca2fcSAlan Somers */
1266022ca2fcSAlan Somers ATF_TC_WITHOUT_HEAD(aio_socket_blocking_short_write_vectored);
ATF_TC_BODY(aio_socket_blocking_short_write_vectored,tc)1267022ca2fcSAlan Somers ATF_TC_BODY(aio_socket_blocking_short_write_vectored, tc)
1268022ca2fcSAlan Somers {
1269022ca2fcSAlan Somers aio_socket_blocking_short_write_test(true);
1270022ca2fcSAlan Somers }
1271022ca2fcSAlan Somers
1272022ca2fcSAlan Somers /*
1273141fe2dcSMark Johnston * Verify that AIO requests fail when applied to a listening socket.
1274141fe2dcSMark Johnston */
1275141fe2dcSMark Johnston ATF_TC_WITHOUT_HEAD(aio_socket_listen_fail);
ATF_TC_BODY(aio_socket_listen_fail,tc)1276141fe2dcSMark Johnston ATF_TC_BODY(aio_socket_listen_fail, tc)
1277141fe2dcSMark Johnston {
1278141fe2dcSMark Johnston struct aiocb iocb;
1279141fe2dcSMark Johnston struct sockaddr_un sun;
1280141fe2dcSMark Johnston char buf[16];
1281141fe2dcSMark Johnston int s;
1282141fe2dcSMark Johnston
1283141fe2dcSMark Johnston s = socket(AF_LOCAL, SOCK_STREAM, 0);
1284141fe2dcSMark Johnston ATF_REQUIRE(s != -1);
1285141fe2dcSMark Johnston
1286141fe2dcSMark Johnston memset(&sun, 0, sizeof(sun));
1287141fe2dcSMark Johnston snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", "listen.XXXXXX");
1288141fe2dcSMark Johnston mktemp(sun.sun_path);
1289141fe2dcSMark Johnston sun.sun_family = AF_LOCAL;
1290141fe2dcSMark Johnston sun.sun_len = SUN_LEN(&sun);
1291141fe2dcSMark Johnston
1292141fe2dcSMark Johnston ATF_REQUIRE(bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0);
1293141fe2dcSMark Johnston ATF_REQUIRE(listen(s, 5) == 0);
1294141fe2dcSMark Johnston
1295141fe2dcSMark Johnston memset(buf, 0, sizeof(buf));
1296141fe2dcSMark Johnston memset(&iocb, 0, sizeof(iocb));
1297141fe2dcSMark Johnston iocb.aio_fildes = s;
1298141fe2dcSMark Johnston iocb.aio_buf = buf;
1299141fe2dcSMark Johnston iocb.aio_nbytes = sizeof(buf);
1300141fe2dcSMark Johnston
1301141fe2dcSMark Johnston ATF_REQUIRE_ERRNO(EINVAL, aio_read(&iocb) == -1);
1302141fe2dcSMark Johnston ATF_REQUIRE_ERRNO(EINVAL, aio_write(&iocb) == -1);
1303141fe2dcSMark Johnston
1304141fe2dcSMark Johnston ATF_REQUIRE(unlink(sun.sun_path) == 0);
1305141fe2dcSMark Johnston close(s);
1306141fe2dcSMark Johnston }
1307141fe2dcSMark Johnston
1308141fe2dcSMark Johnston /*
1309141fe2dcSMark Johnston * Verify that listen(2) fails if a socket has pending AIO requests.
1310141fe2dcSMark Johnston */
1311141fe2dcSMark Johnston ATF_TC_WITHOUT_HEAD(aio_socket_listen_pending);
ATF_TC_BODY(aio_socket_listen_pending,tc)1312141fe2dcSMark Johnston ATF_TC_BODY(aio_socket_listen_pending, tc)
1313141fe2dcSMark Johnston {
1314141fe2dcSMark Johnston struct aiocb iocb;
1315141fe2dcSMark Johnston struct sockaddr_un sun;
1316141fe2dcSMark Johnston char buf[16];
1317141fe2dcSMark Johnston int s;
1318141fe2dcSMark Johnston
1319141fe2dcSMark Johnston s = socket(AF_LOCAL, SOCK_STREAM, 0);
1320141fe2dcSMark Johnston ATF_REQUIRE(s != -1);
1321141fe2dcSMark Johnston
1322141fe2dcSMark Johnston memset(&sun, 0, sizeof(sun));
1323141fe2dcSMark Johnston snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", "listen.XXXXXX");
1324141fe2dcSMark Johnston mktemp(sun.sun_path);
1325141fe2dcSMark Johnston sun.sun_family = AF_LOCAL;
1326141fe2dcSMark Johnston sun.sun_len = SUN_LEN(&sun);
1327141fe2dcSMark Johnston
1328141fe2dcSMark Johnston ATF_REQUIRE(bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0);
1329141fe2dcSMark Johnston
1330141fe2dcSMark Johnston memset(buf, 0, sizeof(buf));
1331141fe2dcSMark Johnston memset(&iocb, 0, sizeof(iocb));
1332141fe2dcSMark Johnston iocb.aio_fildes = s;
1333141fe2dcSMark Johnston iocb.aio_buf = buf;
1334141fe2dcSMark Johnston iocb.aio_nbytes = sizeof(buf);
1335141fe2dcSMark Johnston ATF_REQUIRE(aio_read(&iocb) == 0);
1336141fe2dcSMark Johnston
1337141fe2dcSMark Johnston ATF_REQUIRE_ERRNO(EINVAL, listen(s, 5) == -1);
1338141fe2dcSMark Johnston
1339141fe2dcSMark Johnston ATF_REQUIRE(aio_cancel(s, &iocb) != -1);
1340141fe2dcSMark Johnston
1341141fe2dcSMark Johnston ATF_REQUIRE(unlink(sun.sun_path) == 0);
1342141fe2dcSMark Johnston close(s);
1343141fe2dcSMark Johnston }
1344141fe2dcSMark Johnston
1345141fe2dcSMark Johnston /*
1346778ce4f2SJohn Baldwin * This test verifies that cancelling a partially completed socket write
1347778ce4f2SJohn Baldwin * returns a short write rather than ECANCELED.
1348778ce4f2SJohn Baldwin */
1349778ce4f2SJohn Baldwin ATF_TC_WITHOUT_HEAD(aio_socket_short_write_cancel);
ATF_TC_BODY(aio_socket_short_write_cancel,tc)1350778ce4f2SJohn Baldwin ATF_TC_BODY(aio_socket_short_write_cancel, tc)
1351778ce4f2SJohn Baldwin {
1352778ce4f2SJohn Baldwin struct aiocb iocb, *iocbp;
1353778ce4f2SJohn Baldwin char *buffer[2];
1354778ce4f2SJohn Baldwin ssize_t done;
1355778ce4f2SJohn Baldwin int buffer_size, sb_size;
1356778ce4f2SJohn Baldwin socklen_t len;
1357778ce4f2SJohn Baldwin int s[2];
1358778ce4f2SJohn Baldwin
1359778ce4f2SJohn Baldwin ATF_REQUIRE_KERNEL_MODULE("aio");
1360778ce4f2SJohn Baldwin
1361778ce4f2SJohn Baldwin ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, s) != -1);
1362778ce4f2SJohn Baldwin
1363778ce4f2SJohn Baldwin len = sizeof(sb_size);
1364778ce4f2SJohn Baldwin ATF_REQUIRE(getsockopt(s[0], SOL_SOCKET, SO_RCVBUF, &sb_size, &len) !=
1365778ce4f2SJohn Baldwin -1);
1366778ce4f2SJohn Baldwin ATF_REQUIRE(len == sizeof(sb_size));
1367778ce4f2SJohn Baldwin buffer_size = sb_size;
1368778ce4f2SJohn Baldwin
1369778ce4f2SJohn Baldwin ATF_REQUIRE(getsockopt(s[1], SOL_SOCKET, SO_SNDBUF, &sb_size, &len) !=
1370778ce4f2SJohn Baldwin -1);
1371778ce4f2SJohn Baldwin ATF_REQUIRE(len == sizeof(sb_size));
1372778ce4f2SJohn Baldwin if (sb_size > buffer_size)
1373778ce4f2SJohn Baldwin buffer_size = sb_size;
1374778ce4f2SJohn Baldwin
1375778ce4f2SJohn Baldwin /*
1376778ce4f2SJohn Baldwin * Use three times the size of the MAX(receive buffer, send
1377778ce4f2SJohn Baldwin * buffer) for the write to ensure that the write is split up
1378778ce4f2SJohn Baldwin * into multiple writes internally. The recv() ensures that
1379778ce4f2SJohn Baldwin * the write has partially completed, but a remaining size of
1380778ce4f2SJohn Baldwin * two buffers should ensure that the write has not completed
1381778ce4f2SJohn Baldwin * fully when it is cancelled.
1382778ce4f2SJohn Baldwin */
1383778ce4f2SJohn Baldwin buffer[0] = malloc(buffer_size);
1384778ce4f2SJohn Baldwin ATF_REQUIRE(buffer[0] != NULL);
1385778ce4f2SJohn Baldwin buffer[1] = malloc(buffer_size * 3);
1386778ce4f2SJohn Baldwin ATF_REQUIRE(buffer[1] != NULL);
1387778ce4f2SJohn Baldwin
1388778ce4f2SJohn Baldwin srandomdev();
1389778ce4f2SJohn Baldwin aio_fill_buffer(buffer[1], buffer_size * 3, random());
1390778ce4f2SJohn Baldwin
1391778ce4f2SJohn Baldwin memset(&iocb, 0, sizeof(iocb));
1392778ce4f2SJohn Baldwin iocb.aio_fildes = s[1];
1393778ce4f2SJohn Baldwin iocb.aio_buf = buffer[1];
1394778ce4f2SJohn Baldwin iocb.aio_nbytes = buffer_size * 3;
1395778ce4f2SJohn Baldwin ATF_REQUIRE(aio_write(&iocb) == 0);
1396778ce4f2SJohn Baldwin
1397778ce4f2SJohn Baldwin done = recv(s[0], buffer[0], buffer_size, MSG_WAITALL);
1398778ce4f2SJohn Baldwin ATF_REQUIRE(done == buffer_size);
1399778ce4f2SJohn Baldwin
1400778ce4f2SJohn Baldwin ATF_REQUIRE(aio_error(&iocb) == EINPROGRESS);
1401778ce4f2SJohn Baldwin ATF_REQUIRE(aio_cancel(s[1], &iocb) == AIO_NOTCANCELED);
1402778ce4f2SJohn Baldwin
1403778ce4f2SJohn Baldwin done = aio_waitcomplete(&iocbp, NULL);
1404778ce4f2SJohn Baldwin ATF_REQUIRE(iocbp == &iocb);
1405778ce4f2SJohn Baldwin ATF_REQUIRE(done >= buffer_size && done <= buffer_size * 2);
1406778ce4f2SJohn Baldwin
1407778ce4f2SJohn Baldwin ATF_REQUIRE(memcmp(buffer[0], buffer[1], buffer_size) == 0);
1408778ce4f2SJohn Baldwin
1409778ce4f2SJohn Baldwin close(s[1]);
1410778ce4f2SJohn Baldwin close(s[0]);
1411778ce4f2SJohn Baldwin }
1412778ce4f2SJohn Baldwin
1413005ce8e4SJohn Baldwin /*
1414c13f6dd7SMark Johnston * Test handling of aio_read() and aio_write() on shut-down sockets.
1415c13f6dd7SMark Johnston */
1416c13f6dd7SMark Johnston ATF_TC_WITHOUT_HEAD(aio_socket_shutdown);
ATF_TC_BODY(aio_socket_shutdown,tc)1417c13f6dd7SMark Johnston ATF_TC_BODY(aio_socket_shutdown, tc)
1418c13f6dd7SMark Johnston {
1419c13f6dd7SMark Johnston struct aiocb iocb;
1420c13f6dd7SMark Johnston sigset_t set;
1421c13f6dd7SMark Johnston char *buffer;
1422c13f6dd7SMark Johnston ssize_t len;
1423c13f6dd7SMark Johnston size_t bsz;
1424c13f6dd7SMark Johnston int error, s[2];
1425c13f6dd7SMark Johnston
1426c13f6dd7SMark Johnston ATF_REQUIRE_KERNEL_MODULE("aio");
1427c13f6dd7SMark Johnston
1428c13f6dd7SMark Johnston ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, s) != -1);
1429c13f6dd7SMark Johnston
1430c13f6dd7SMark Johnston bsz = 1024;
1431c13f6dd7SMark Johnston buffer = malloc(bsz);
1432c13f6dd7SMark Johnston memset(buffer, 0, bsz);
1433c13f6dd7SMark Johnston
1434c13f6dd7SMark Johnston /* Put some data in s[0]'s recv buffer. */
1435c13f6dd7SMark Johnston ATF_REQUIRE(send(s[1], buffer, bsz, 0) == (ssize_t)bsz);
1436c13f6dd7SMark Johnston
1437c13f6dd7SMark Johnston /* No more reading from s[0]. */
1438c13f6dd7SMark Johnston ATF_REQUIRE(shutdown(s[0], SHUT_RD) != -1);
1439c13f6dd7SMark Johnston
1440c13f6dd7SMark Johnston ATF_REQUIRE(buffer != NULL);
1441c13f6dd7SMark Johnston
1442c13f6dd7SMark Johnston memset(&iocb, 0, sizeof(iocb));
1443c13f6dd7SMark Johnston iocb.aio_fildes = s[0];
1444c13f6dd7SMark Johnston iocb.aio_buf = buffer;
1445c13f6dd7SMark Johnston iocb.aio_nbytes = bsz;
1446c13f6dd7SMark Johnston ATF_REQUIRE(aio_read(&iocb) == 0);
1447c13f6dd7SMark Johnston
1448c13f6dd7SMark Johnston /* Expect to see zero bytes, analogous to recv(2). */
1449c13f6dd7SMark Johnston while ((error = aio_error(&iocb)) == EINPROGRESS)
1450c13f6dd7SMark Johnston usleep(25000);
1451c13f6dd7SMark Johnston ATF_REQUIRE_MSG(error == 0, "aio_error() returned %d", error);
1452c13f6dd7SMark Johnston len = aio_return(&iocb);
1453c13f6dd7SMark Johnston ATF_REQUIRE_MSG(len == 0, "read job returned %zd bytes", len);
1454c13f6dd7SMark Johnston
1455c13f6dd7SMark Johnston /* No more writing to s[1]. */
1456c13f6dd7SMark Johnston ATF_REQUIRE(shutdown(s[1], SHUT_WR) != -1);
1457c13f6dd7SMark Johnston
1458c13f6dd7SMark Johnston /* Block SIGPIPE so that we can detect the error in-band. */
1459c13f6dd7SMark Johnston sigemptyset(&set);
1460c13f6dd7SMark Johnston sigaddset(&set, SIGPIPE);
1461c13f6dd7SMark Johnston ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) == 0);
1462c13f6dd7SMark Johnston
1463c13f6dd7SMark Johnston memset(&iocb, 0, sizeof(iocb));
1464c13f6dd7SMark Johnston iocb.aio_fildes = s[1];
1465c13f6dd7SMark Johnston iocb.aio_buf = buffer;
1466c13f6dd7SMark Johnston iocb.aio_nbytes = bsz;
1467c13f6dd7SMark Johnston ATF_REQUIRE(aio_write(&iocb) == 0);
1468c13f6dd7SMark Johnston
1469c13f6dd7SMark Johnston /* Expect an error, analogous to send(2). */
1470c13f6dd7SMark Johnston while ((error = aio_error(&iocb)) == EINPROGRESS)
1471c13f6dd7SMark Johnston usleep(25000);
1472c13f6dd7SMark Johnston ATF_REQUIRE_MSG(error == EPIPE, "aio_error() returned %d", error);
1473c13f6dd7SMark Johnston
1474c13f6dd7SMark Johnston ATF_REQUIRE(close(s[0]) != -1);
1475c13f6dd7SMark Johnston ATF_REQUIRE(close(s[1]) != -1);
1476c13f6dd7SMark Johnston free(buffer);
1477c13f6dd7SMark Johnston }
1478c13f6dd7SMark Johnston
1479c13f6dd7SMark Johnston /*
1480604bbb3fSAlan Somers * test aio_fsync's behavior with bad inputs
1481604bbb3fSAlan Somers */
1482604bbb3fSAlan Somers ATF_TC_WITHOUT_HEAD(aio_fsync_errors);
ATF_TC_BODY(aio_fsync_errors,tc)1483604bbb3fSAlan Somers ATF_TC_BODY(aio_fsync_errors, tc)
1484604bbb3fSAlan Somers {
1485604bbb3fSAlan Somers int fd;
1486604bbb3fSAlan Somers struct aiocb iocb;
1487604bbb3fSAlan Somers
1488604bbb3fSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
1489604bbb3fSAlan Somers ATF_REQUIRE_UNSAFE_AIO();
1490604bbb3fSAlan Somers
1491604bbb3fSAlan Somers fd = open(FILE_PATHNAME, O_RDWR | O_CREAT, 0600);
1492604bbb3fSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1493604bbb3fSAlan Somers unlink(FILE_PATHNAME);
1494604bbb3fSAlan Somers
1495801ac943SThomas Munro /* aio_fsync should return EINVAL unless op is O_SYNC or O_DSYNC */
1496604bbb3fSAlan Somers memset(&iocb, 0, sizeof(iocb));
1497604bbb3fSAlan Somers iocb.aio_fildes = fd;
1498604bbb3fSAlan Somers ATF_CHECK_EQ(-1, aio_fsync(666, &iocb));
1499604bbb3fSAlan Somers ATF_CHECK_EQ(EINVAL, errno);
1500604bbb3fSAlan Somers
1501604bbb3fSAlan Somers /* aio_fsync should return EBADF if fd is not a valid descriptor */
1502604bbb3fSAlan Somers memset(&iocb, 0, sizeof(iocb));
1503604bbb3fSAlan Somers iocb.aio_fildes = 666;
1504604bbb3fSAlan Somers ATF_CHECK_EQ(-1, aio_fsync(O_SYNC, &iocb));
1505604bbb3fSAlan Somers ATF_CHECK_EQ(EBADF, errno);
1506604bbb3fSAlan Somers
1507604bbb3fSAlan Somers /* aio_fsync should return EINVAL if sigev_notify is invalid */
1508604bbb3fSAlan Somers memset(&iocb, 0, sizeof(iocb));
1509604bbb3fSAlan Somers iocb.aio_fildes = fd;
1510604bbb3fSAlan Somers iocb.aio_sigevent.sigev_notify = 666;
1511604bbb3fSAlan Somers ATF_CHECK_EQ(-1, aio_fsync(666, &iocb));
1512604bbb3fSAlan Somers ATF_CHECK_EQ(EINVAL, errno);
1513604bbb3fSAlan Somers }
1514604bbb3fSAlan Somers
1515604bbb3fSAlan Somers /*
1516005ce8e4SJohn Baldwin * This test just performs a basic test of aio_fsync().
1517005ce8e4SJohn Baldwin */
1518801ac943SThomas Munro static void
aio_fsync_test(int op)1519801ac943SThomas Munro aio_fsync_test(int op)
1520005ce8e4SJohn Baldwin {
1521005ce8e4SJohn Baldwin struct aiocb synccb, *iocbp;
1522005ce8e4SJohn Baldwin struct {
1523005ce8e4SJohn Baldwin struct aiocb iocb;
1524005ce8e4SJohn Baldwin bool done;
1525005ce8e4SJohn Baldwin char *buffer;
1526005ce8e4SJohn Baldwin } buffers[16];
1527005ce8e4SJohn Baldwin struct stat sb;
1528005ce8e4SJohn Baldwin ssize_t rval;
1529005ce8e4SJohn Baldwin unsigned i;
1530005ce8e4SJohn Baldwin int fd;
1531005ce8e4SJohn Baldwin
1532005ce8e4SJohn Baldwin ATF_REQUIRE_KERNEL_MODULE("aio");
1533005ce8e4SJohn Baldwin ATF_REQUIRE_UNSAFE_AIO();
1534005ce8e4SJohn Baldwin
15359086b30bSJilles Tjoelker fd = open(FILE_PATHNAME, O_RDWR | O_CREAT, 0600);
1536740a9bfaSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1537740a9bfaSAlan Somers unlink(FILE_PATHNAME);
1538005ce8e4SJohn Baldwin
1539005ce8e4SJohn Baldwin ATF_REQUIRE(fstat(fd, &sb) == 0);
1540005ce8e4SJohn Baldwin ATF_REQUIRE(sb.st_blksize != 0);
1541005ce8e4SJohn Baldwin ATF_REQUIRE(ftruncate(fd, sb.st_blksize * nitems(buffers)) == 0);
1542005ce8e4SJohn Baldwin
1543005ce8e4SJohn Baldwin /*
1544005ce8e4SJohn Baldwin * Queue several asynchronous write requests. Hopefully this
1545005ce8e4SJohn Baldwin * forces the aio_fsync() request to be deferred. There is no
1546005ce8e4SJohn Baldwin * reliable way to guarantee that however.
1547005ce8e4SJohn Baldwin */
1548005ce8e4SJohn Baldwin srandomdev();
1549005ce8e4SJohn Baldwin for (i = 0; i < nitems(buffers); i++) {
1550005ce8e4SJohn Baldwin buffers[i].done = false;
1551005ce8e4SJohn Baldwin memset(&buffers[i].iocb, 0, sizeof(buffers[i].iocb));
1552005ce8e4SJohn Baldwin buffers[i].buffer = malloc(sb.st_blksize);
1553005ce8e4SJohn Baldwin aio_fill_buffer(buffers[i].buffer, sb.st_blksize, random());
1554005ce8e4SJohn Baldwin buffers[i].iocb.aio_fildes = fd;
1555005ce8e4SJohn Baldwin buffers[i].iocb.aio_buf = buffers[i].buffer;
1556005ce8e4SJohn Baldwin buffers[i].iocb.aio_nbytes = sb.st_blksize;
1557005ce8e4SJohn Baldwin buffers[i].iocb.aio_offset = sb.st_blksize * i;
1558005ce8e4SJohn Baldwin ATF_REQUIRE(aio_write(&buffers[i].iocb) == 0);
1559005ce8e4SJohn Baldwin }
1560005ce8e4SJohn Baldwin
1561005ce8e4SJohn Baldwin /* Queue the aio_fsync request. */
1562005ce8e4SJohn Baldwin memset(&synccb, 0, sizeof(synccb));
1563005ce8e4SJohn Baldwin synccb.aio_fildes = fd;
1564801ac943SThomas Munro ATF_REQUIRE(aio_fsync(op, &synccb) == 0);
1565005ce8e4SJohn Baldwin
1566005ce8e4SJohn Baldwin /* Wait for requests to complete. */
1567005ce8e4SJohn Baldwin for (;;) {
1568005ce8e4SJohn Baldwin next:
1569005ce8e4SJohn Baldwin rval = aio_waitcomplete(&iocbp, NULL);
1570005ce8e4SJohn Baldwin ATF_REQUIRE(iocbp != NULL);
1571005ce8e4SJohn Baldwin if (iocbp == &synccb) {
1572005ce8e4SJohn Baldwin ATF_REQUIRE(rval == 0);
1573005ce8e4SJohn Baldwin break;
1574005ce8e4SJohn Baldwin }
1575005ce8e4SJohn Baldwin
1576005ce8e4SJohn Baldwin for (i = 0; i < nitems(buffers); i++) {
1577005ce8e4SJohn Baldwin if (iocbp == &buffers[i].iocb) {
1578005ce8e4SJohn Baldwin ATF_REQUIRE(buffers[i].done == false);
1579005ce8e4SJohn Baldwin ATF_REQUIRE(rval == sb.st_blksize);
1580005ce8e4SJohn Baldwin buffers[i].done = true;
1581005ce8e4SJohn Baldwin goto next;
1582005ce8e4SJohn Baldwin }
1583005ce8e4SJohn Baldwin }
1584005ce8e4SJohn Baldwin
1585005ce8e4SJohn Baldwin ATF_REQUIRE_MSG(false, "unmatched AIO request");
1586005ce8e4SJohn Baldwin }
1587005ce8e4SJohn Baldwin
1588005ce8e4SJohn Baldwin for (i = 0; i < nitems(buffers); i++)
1589005ce8e4SJohn Baldwin ATF_REQUIRE_MSG(buffers[i].done,
1590005ce8e4SJohn Baldwin "AIO request %u did not complete", i);
1591005ce8e4SJohn Baldwin
1592005ce8e4SJohn Baldwin close(fd);
1593005ce8e4SJohn Baldwin }
1594005ce8e4SJohn Baldwin
1595801ac943SThomas Munro ATF_TC_WITHOUT_HEAD(aio_fsync_sync_test);
ATF_TC_BODY(aio_fsync_sync_test,tc)1596801ac943SThomas Munro ATF_TC_BODY(aio_fsync_sync_test, tc)
1597801ac943SThomas Munro {
1598801ac943SThomas Munro aio_fsync_test(O_SYNC);
1599801ac943SThomas Munro }
1600801ac943SThomas Munro
1601801ac943SThomas Munro ATF_TC_WITHOUT_HEAD(aio_fsync_dsync_test);
ATF_TC_BODY(aio_fsync_dsync_test,tc)1602801ac943SThomas Munro ATF_TC_BODY(aio_fsync_dsync_test, tc)
1603801ac943SThomas Munro {
1604801ac943SThomas Munro aio_fsync_test(O_DSYNC);
1605801ac943SThomas Munro }
1606801ac943SThomas Munro
1607022ca2fcSAlan Somers /*
1608022ca2fcSAlan Somers * We shouldn't be able to DoS the system by setting iov_len to an insane
1609022ca2fcSAlan Somers * value
1610022ca2fcSAlan Somers */
1611022ca2fcSAlan Somers ATF_TC_WITHOUT_HEAD(aio_writev_dos_iov_len);
ATF_TC_BODY(aio_writev_dos_iov_len,tc)1612022ca2fcSAlan Somers ATF_TC_BODY(aio_writev_dos_iov_len, tc)
1613022ca2fcSAlan Somers {
1614022ca2fcSAlan Somers struct aiocb aio;
1615022ca2fcSAlan Somers const struct aiocb *const iocbs[] = {&aio};
1616022ca2fcSAlan Somers const char *wbuf = "Hello, world!";
1617022ca2fcSAlan Somers struct iovec iov[1];
161857082ce8SAlan Somers ssize_t r;
1619022ca2fcSAlan Somers int fd;
1620022ca2fcSAlan Somers
1621022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
1622022ca2fcSAlan Somers ATF_REQUIRE_UNSAFE_AIO();
1623022ca2fcSAlan Somers
1624022ca2fcSAlan Somers fd = open("testfile", O_RDWR | O_CREAT, 0600);
1625022ca2fcSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1626022ca2fcSAlan Somers
1627022ca2fcSAlan Somers iov[0].iov_base = __DECONST(void*, wbuf);
1628022ca2fcSAlan Somers iov[0].iov_len = 1 << 30;
1629022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
1630022ca2fcSAlan Somers aio.aio_fildes = fd;
1631022ca2fcSAlan Somers aio.aio_offset = 0;
1632022ca2fcSAlan Somers aio.aio_iov = iov;
1633022ca2fcSAlan Somers aio.aio_iovcnt = 1;
1634022ca2fcSAlan Somers
1635022ca2fcSAlan Somers r = aio_writev(&aio);
1636022ca2fcSAlan Somers ATF_CHECK_EQ_MSG(0, r, "aio_writev returned %zd", r);
1637022ca2fcSAlan Somers ATF_REQUIRE_EQ(0, aio_suspend(iocbs, 1, NULL));
1638022ca2fcSAlan Somers r = aio_return(&aio);
1639022ca2fcSAlan Somers ATF_CHECK_EQ_MSG(-1, r, "aio_return returned %zd", r);
1640022ca2fcSAlan Somers ATF_CHECK_MSG(errno == EFAULT || errno == EINVAL,
1641022ca2fcSAlan Somers "aio_writev: %s", strerror(errno));
1642022ca2fcSAlan Somers
1643022ca2fcSAlan Somers close(fd);
1644022ca2fcSAlan Somers }
1645022ca2fcSAlan Somers
1646022ca2fcSAlan Somers /*
1647022ca2fcSAlan Somers * We shouldn't be able to DoS the system by setting aio_iovcnt to an insane
1648022ca2fcSAlan Somers * value
1649022ca2fcSAlan Somers */
1650022ca2fcSAlan Somers ATF_TC_WITHOUT_HEAD(aio_writev_dos_iovcnt);
ATF_TC_BODY(aio_writev_dos_iovcnt,tc)1651022ca2fcSAlan Somers ATF_TC_BODY(aio_writev_dos_iovcnt, tc)
1652022ca2fcSAlan Somers {
1653022ca2fcSAlan Somers struct aiocb aio;
1654022ca2fcSAlan Somers const char *wbuf = "Hello, world!";
1655022ca2fcSAlan Somers struct iovec iov[1];
1656022ca2fcSAlan Somers ssize_t len;
1657022ca2fcSAlan Somers int fd;
1658022ca2fcSAlan Somers
1659022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
1660022ca2fcSAlan Somers ATF_REQUIRE_UNSAFE_AIO();
1661022ca2fcSAlan Somers
1662022ca2fcSAlan Somers fd = open("testfile", O_RDWR | O_CREAT, 0600);
1663022ca2fcSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1664022ca2fcSAlan Somers
1665022ca2fcSAlan Somers len = strlen(wbuf);
1666022ca2fcSAlan Somers iov[0].iov_base = __DECONST(void*, wbuf);
1667022ca2fcSAlan Somers iov[0].iov_len = len;
1668022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
1669022ca2fcSAlan Somers aio.aio_fildes = fd;
1670022ca2fcSAlan Somers aio.aio_offset = 0;
1671022ca2fcSAlan Somers aio.aio_iov = iov;
1672022ca2fcSAlan Somers aio.aio_iovcnt = 1 << 30;
1673022ca2fcSAlan Somers
1674022ca2fcSAlan Somers ATF_REQUIRE_EQ(-1, aio_writev(&aio));
1675022ca2fcSAlan Somers ATF_CHECK_EQ(EINVAL, errno);
1676022ca2fcSAlan Somers
1677022ca2fcSAlan Somers close(fd);
1678022ca2fcSAlan Somers }
1679022ca2fcSAlan Somers
1680022ca2fcSAlan Somers ATF_TC_WITH_CLEANUP(aio_writev_efault);
ATF_TC_HEAD(aio_writev_efault,tc)1681022ca2fcSAlan Somers ATF_TC_HEAD(aio_writev_efault, tc)
1682022ca2fcSAlan Somers {
1683022ca2fcSAlan Somers atf_tc_set_md_var(tc, "descr",
1684022ca2fcSAlan Somers "Vectored AIO should gracefully handle invalid addresses");
1685022ca2fcSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
1686022ca2fcSAlan Somers }
ATF_TC_BODY(aio_writev_efault,tc)1687022ca2fcSAlan Somers ATF_TC_BODY(aio_writev_efault, tc)
1688022ca2fcSAlan Somers {
1689022ca2fcSAlan Somers struct aiocb aio;
1690022ca2fcSAlan Somers ssize_t buflen;
1691022ca2fcSAlan Somers char *buffer;
1692022ca2fcSAlan Somers struct iovec iov[2];
1693022ca2fcSAlan Somers long seed;
1694022ca2fcSAlan Somers int fd;
1695022ca2fcSAlan Somers
1696022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
1697022ca2fcSAlan Somers ATF_REQUIRE_UNSAFE_AIO();
1698022ca2fcSAlan Somers
1699022ca2fcSAlan Somers fd = aio_md_setup();
1700022ca2fcSAlan Somers
1701022ca2fcSAlan Somers seed = random();
1702022ca2fcSAlan Somers buflen = 4096;
1703022ca2fcSAlan Somers buffer = malloc(buflen);
1704022ca2fcSAlan Somers aio_fill_buffer(buffer, buflen, seed);
1705022ca2fcSAlan Somers iov[0].iov_base = buffer;
1706022ca2fcSAlan Somers iov[0].iov_len = buflen;
1707022ca2fcSAlan Somers iov[1].iov_base = (void*)-1; /* Invalid! */
1708022ca2fcSAlan Somers iov[1].iov_len = buflen;
1709022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
1710022ca2fcSAlan Somers aio.aio_fildes = fd;
1711022ca2fcSAlan Somers aio.aio_offset = 0;
1712022ca2fcSAlan Somers aio.aio_iov = iov;
1713022ca2fcSAlan Somers aio.aio_iovcnt = nitems(iov);
1714022ca2fcSAlan Somers
1715022ca2fcSAlan Somers ATF_REQUIRE_EQ(-1, aio_writev(&aio));
1716022ca2fcSAlan Somers ATF_CHECK_EQ(EFAULT, errno);
1717022ca2fcSAlan Somers
1718022ca2fcSAlan Somers close(fd);
1719022ca2fcSAlan Somers }
ATF_TC_CLEANUP(aio_writev_efault,tc)1720022ca2fcSAlan Somers ATF_TC_CLEANUP(aio_writev_efault, tc)
1721022ca2fcSAlan Somers {
1722022ca2fcSAlan Somers aio_md_cleanup();
1723022ca2fcSAlan Somers }
1724022ca2fcSAlan Somers
1725022ca2fcSAlan Somers ATF_TC_WITHOUT_HEAD(aio_writev_empty_file_poll);
ATF_TC_BODY(aio_writev_empty_file_poll,tc)1726022ca2fcSAlan Somers ATF_TC_BODY(aio_writev_empty_file_poll, tc)
1727022ca2fcSAlan Somers {
1728022ca2fcSAlan Somers struct aiocb aio;
1729022ca2fcSAlan Somers int fd;
1730022ca2fcSAlan Somers
1731022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
1732022ca2fcSAlan Somers ATF_REQUIRE_UNSAFE_AIO();
1733022ca2fcSAlan Somers
1734022ca2fcSAlan Somers fd = open("testfile", O_RDWR | O_CREAT, 0600);
1735022ca2fcSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1736022ca2fcSAlan Somers
1737022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
1738022ca2fcSAlan Somers aio.aio_fildes = fd;
1739022ca2fcSAlan Somers aio.aio_offset = 0;
1740022ca2fcSAlan Somers aio.aio_iovcnt = 0;
1741022ca2fcSAlan Somers
1742022ca2fcSAlan Somers ATF_REQUIRE_EQ(0, aio_writev(&aio));
1743022ca2fcSAlan Somers ATF_REQUIRE_EQ(0, suspend(&aio));
1744022ca2fcSAlan Somers
1745022ca2fcSAlan Somers close(fd);
1746022ca2fcSAlan Somers }
1747022ca2fcSAlan Somers
1748022ca2fcSAlan Somers ATF_TC_WITHOUT_HEAD(aio_writev_empty_file_signal);
ATF_TC_BODY(aio_writev_empty_file_signal,tc)1749022ca2fcSAlan Somers ATF_TC_BODY(aio_writev_empty_file_signal, tc)
1750022ca2fcSAlan Somers {
1751022ca2fcSAlan Somers struct aiocb aio;
1752022ca2fcSAlan Somers int fd;
1753022ca2fcSAlan Somers
1754022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
1755022ca2fcSAlan Somers ATF_REQUIRE_UNSAFE_AIO();
1756022ca2fcSAlan Somers
1757022ca2fcSAlan Somers fd = open("testfile", O_RDWR | O_CREAT, 0600);
1758022ca2fcSAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
1759022ca2fcSAlan Somers
1760022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
1761022ca2fcSAlan Somers aio.aio_fildes = fd;
1762022ca2fcSAlan Somers aio.aio_offset = 0;
1763022ca2fcSAlan Somers aio.aio_iovcnt = 0;
1764022ca2fcSAlan Somers aio.aio_sigevent = *setup_signal();
1765022ca2fcSAlan Somers
1766022ca2fcSAlan Somers ATF_REQUIRE_EQ(0, aio_writev(&aio));
1767022ca2fcSAlan Somers ATF_REQUIRE_EQ(0, poll_signaled(&aio));
1768022ca2fcSAlan Somers
1769022ca2fcSAlan Somers close(fd);
1770022ca2fcSAlan Somers }
1771022ca2fcSAlan Somers
177257082ce8SAlan Somers /*
177357082ce8SAlan Somers * Use an aiocb with kqueue and EV_ONESHOT. kqueue should deliver the event
177457082ce8SAlan Somers * only once, even if the user doesn't promptly call aio_return.
177557082ce8SAlan Somers */
177657082ce8SAlan Somers ATF_TC_WITHOUT_HEAD(ev_oneshot);
ATF_TC_BODY(ev_oneshot,tc)177757082ce8SAlan Somers ATF_TC_BODY(ev_oneshot, tc)
177857082ce8SAlan Somers {
177957082ce8SAlan Somers int fd, kq, nevents;
178057082ce8SAlan Somers struct aiocb iocb;
178157082ce8SAlan Somers struct kevent events[1];
178257082ce8SAlan Somers struct timespec timeout;
178357082ce8SAlan Somers
178457082ce8SAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
178557082ce8SAlan Somers
178657082ce8SAlan Somers kq = kqueue();
178757082ce8SAlan Somers ATF_REQUIRE(kq >= 0);
178857082ce8SAlan Somers
178957082ce8SAlan Somers fd = open(FILE_PATHNAME, O_RDWR | O_CREAT, 0600);
179057082ce8SAlan Somers ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno));
179157082ce8SAlan Somers
179257082ce8SAlan Somers memset(&iocb, 0, sizeof(iocb));
179357082ce8SAlan Somers iocb.aio_fildes = fd;
179457082ce8SAlan Somers iocb.aio_sigevent.sigev_notify_kqueue = kq;
179557082ce8SAlan Somers iocb.aio_sigevent.sigev_value.sival_ptr = (void*)0xdeadbeef;
179657082ce8SAlan Somers iocb.aio_sigevent.sigev_notify_kevent_flags = EV_ONESHOT;
179757082ce8SAlan Somers iocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
179857082ce8SAlan Somers
179957082ce8SAlan Somers ATF_CHECK_EQ(0, aio_fsync(O_SYNC, &iocb));
180057082ce8SAlan Somers
180157082ce8SAlan Somers nevents = kevent(kq, NULL, 0, events, 1, NULL);
180257082ce8SAlan Somers ATF_CHECK_EQ(1, nevents);
180357082ce8SAlan Somers ATF_CHECK_EQ(events[0].ident, (uintptr_t) &iocb);
180457082ce8SAlan Somers ATF_CHECK_EQ(events[0].filter, EVFILT_AIO);
180557082ce8SAlan Somers ATF_CHECK_EQ(events[0].flags, EV_EOF | EV_ONESHOT);
180657082ce8SAlan Somers ATF_CHECK_EQ(events[0].fflags, 0);
180757082ce8SAlan Somers ATF_CHECK_EQ(events[0].data, 0);
180857082ce8SAlan Somers ATF_CHECK_EQ((uintptr_t)events[0].udata, 0xdeadbeef);
180957082ce8SAlan Somers
181057082ce8SAlan Somers /*
181157082ce8SAlan Somers * Even though we haven't called aio_return, kevent will not return the
181257082ce8SAlan Somers * event again due to EV_ONESHOT.
181357082ce8SAlan Somers */
181457082ce8SAlan Somers timeout.tv_sec = 0;
181557082ce8SAlan Somers timeout.tv_nsec = 100000000;
181657082ce8SAlan Somers nevents = kevent(kq, NULL, 0, events, 1, &timeout);
181757082ce8SAlan Somers ATF_CHECK_EQ(0, nevents);
181857082ce8SAlan Somers
181957082ce8SAlan Somers ATF_CHECK_EQ(0, aio_return(&iocb));
182057082ce8SAlan Somers close(fd);
182157082ce8SAlan Somers close(kq);
182257082ce8SAlan Somers }
182357082ce8SAlan Somers
182457082ce8SAlan Somers
1825022ca2fcSAlan Somers // aio_writev and aio_readv should still work even if the iovcnt is greater
1826022ca2fcSAlan Somers // than the number of buffered AIO operations permitted per process.
1827022ca2fcSAlan Somers ATF_TC_WITH_CLEANUP(vectored_big_iovcnt);
ATF_TC_HEAD(vectored_big_iovcnt,tc)1828022ca2fcSAlan Somers ATF_TC_HEAD(vectored_big_iovcnt, tc)
1829022ca2fcSAlan Somers {
1830022ca2fcSAlan Somers atf_tc_set_md_var(tc, "descr",
1831022ca2fcSAlan Somers "Vectored AIO should still work even if the iovcnt is greater than "
1832022ca2fcSAlan Somers "the number of buffered AIO operations permitted by the process");
1833022ca2fcSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
1834022ca2fcSAlan Somers }
ATF_TC_BODY(vectored_big_iovcnt,tc)1835022ca2fcSAlan Somers ATF_TC_BODY(vectored_big_iovcnt, tc)
1836022ca2fcSAlan Somers {
1837022ca2fcSAlan Somers struct aiocb aio;
1838022ca2fcSAlan Somers struct iovec *iov;
1839022ca2fcSAlan Somers ssize_t len, buflen;
1840022ca2fcSAlan Somers char *buffer;
1841022ca2fcSAlan Somers const char *oid = "vfs.aio.max_buf_aio";
1842022ca2fcSAlan Somers long seed;
1843022ca2fcSAlan Somers int max_buf_aio;
1844022ca2fcSAlan Somers int fd, i;
1845022ca2fcSAlan Somers ssize_t sysctl_len = sizeof(max_buf_aio);
1846022ca2fcSAlan Somers
1847022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
1848022ca2fcSAlan Somers ATF_REQUIRE_UNSAFE_AIO();
1849022ca2fcSAlan Somers
1850022ca2fcSAlan Somers if (sysctlbyname(oid, &max_buf_aio, &sysctl_len, NULL, 0) == -1)
1851022ca2fcSAlan Somers atf_libc_error(errno, "Failed to read %s", oid);
1852022ca2fcSAlan Somers
1853022ca2fcSAlan Somers seed = random();
1854022ca2fcSAlan Somers buflen = 512 * (max_buf_aio + 1);
1855022ca2fcSAlan Somers buffer = malloc(buflen);
1856022ca2fcSAlan Somers aio_fill_buffer(buffer, buflen, seed);
1857022ca2fcSAlan Somers iov = calloc(max_buf_aio + 1, sizeof(struct iovec));
1858022ca2fcSAlan Somers
1859022ca2fcSAlan Somers fd = aio_md_setup();
1860022ca2fcSAlan Somers
1861022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
1862022ca2fcSAlan Somers aio.aio_fildes = fd;
1863022ca2fcSAlan Somers aio.aio_offset = 0;
1864022ca2fcSAlan Somers for (i = 0; i < max_buf_aio + 1; i++) {
1865022ca2fcSAlan Somers iov[i].iov_base = &buffer[i * 512];
1866022ca2fcSAlan Somers iov[i].iov_len = 512;
1867022ca2fcSAlan Somers }
1868022ca2fcSAlan Somers aio.aio_iov = iov;
1869022ca2fcSAlan Somers aio.aio_iovcnt = max_buf_aio + 1;
1870022ca2fcSAlan Somers
1871022ca2fcSAlan Somers if (aio_writev(&aio) < 0)
1872022ca2fcSAlan Somers atf_tc_fail("aio_writev failed: %s", strerror(errno));
1873022ca2fcSAlan Somers
1874022ca2fcSAlan Somers len = poll(&aio);
1875022ca2fcSAlan Somers if (len < 0)
1876022ca2fcSAlan Somers atf_tc_fail("aio failed: %s", strerror(errno));
1877022ca2fcSAlan Somers
1878022ca2fcSAlan Somers if (len != buflen)
1879022ca2fcSAlan Somers atf_tc_fail("aio short write (%jd)", (intmax_t)len);
1880022ca2fcSAlan Somers
1881022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
1882022ca2fcSAlan Somers aio.aio_fildes = fd;
1883022ca2fcSAlan Somers aio.aio_offset = 0;
1884022ca2fcSAlan Somers aio.aio_iov = iov;
1885022ca2fcSAlan Somers aio.aio_iovcnt = max_buf_aio + 1;
1886022ca2fcSAlan Somers
1887022ca2fcSAlan Somers if (aio_readv(&aio) < 0)
1888022ca2fcSAlan Somers atf_tc_fail("aio_readv failed: %s", strerror(errno));
1889022ca2fcSAlan Somers
1890022ca2fcSAlan Somers len = poll(&aio);
1891022ca2fcSAlan Somers if (len < 0)
1892022ca2fcSAlan Somers atf_tc_fail("aio failed: %s", strerror(errno));
1893022ca2fcSAlan Somers
1894022ca2fcSAlan Somers if (len != buflen)
1895022ca2fcSAlan Somers atf_tc_fail("aio short read (%jd)", (intmax_t)len);
1896022ca2fcSAlan Somers
1897022ca2fcSAlan Somers if (aio_test_buffer(buffer, buflen, seed) == 0)
1898022ca2fcSAlan Somers atf_tc_fail("buffer mismatched");
1899022ca2fcSAlan Somers
1900022ca2fcSAlan Somers close(fd);
1901022ca2fcSAlan Somers }
ATF_TC_CLEANUP(vectored_big_iovcnt,tc)1902022ca2fcSAlan Somers ATF_TC_CLEANUP(vectored_big_iovcnt, tc)
1903022ca2fcSAlan Somers {
1904022ca2fcSAlan Somers aio_md_cleanup();
1905022ca2fcSAlan Somers }
1906022ca2fcSAlan Somers
1907022ca2fcSAlan Somers ATF_TC_WITHOUT_HEAD(vectored_file_poll);
ATF_TC_BODY(vectored_file_poll,tc)1908022ca2fcSAlan Somers ATF_TC_BODY(vectored_file_poll, tc)
1909022ca2fcSAlan Somers {
1910022ca2fcSAlan Somers aio_file_test(poll, NULL, true);
1911022ca2fcSAlan Somers }
1912022ca2fcSAlan Somers
19133904e796SThomas Munro ATF_TC_WITHOUT_HEAD(vectored_thread);
ATF_TC_BODY(vectored_thread,tc)19143904e796SThomas Munro ATF_TC_BODY(vectored_thread, tc)
19153904e796SThomas Munro {
19163904e796SThomas Munro aio_file_test(poll_signaled, setup_thread(), true);
19173904e796SThomas Munro }
19183904e796SThomas Munro
1919022ca2fcSAlan Somers ATF_TC_WITH_CLEANUP(vectored_md_poll);
ATF_TC_HEAD(vectored_md_poll,tc)1920022ca2fcSAlan Somers ATF_TC_HEAD(vectored_md_poll, tc)
1921022ca2fcSAlan Somers {
1922022ca2fcSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
1923022ca2fcSAlan Somers }
ATF_TC_BODY(vectored_md_poll,tc)1924022ca2fcSAlan Somers ATF_TC_BODY(vectored_md_poll, tc)
1925022ca2fcSAlan Somers {
1926022ca2fcSAlan Somers aio_md_test(poll, NULL, true);
1927022ca2fcSAlan Somers }
ATF_TC_CLEANUP(vectored_md_poll,tc)1928022ca2fcSAlan Somers ATF_TC_CLEANUP(vectored_md_poll, tc)
1929022ca2fcSAlan Somers {
1930022ca2fcSAlan Somers aio_md_cleanup();
1931022ca2fcSAlan Somers }
1932022ca2fcSAlan Somers
1933022ca2fcSAlan Somers ATF_TC_WITHOUT_HEAD(vectored_socket_poll);
ATF_TC_BODY(vectored_socket_poll,tc)1934022ca2fcSAlan Somers ATF_TC_BODY(vectored_socket_poll, tc)
1935022ca2fcSAlan Somers {
1936022ca2fcSAlan Somers aio_unix_socketpair_test(poll, NULL, true);
1937022ca2fcSAlan Somers }
1938022ca2fcSAlan Somers
1939022ca2fcSAlan Somers // aio_writev and aio_readv should still work even if the iov contains elements
1940022ca2fcSAlan Somers // that aren't a multiple of the device's sector size, and even if the total
1941022ca2fcSAlan Somers // amount if I/O _is_ a multiple of the device's sector size.
1942022ca2fcSAlan Somers ATF_TC_WITH_CLEANUP(vectored_unaligned);
ATF_TC_HEAD(vectored_unaligned,tc)1943022ca2fcSAlan Somers ATF_TC_HEAD(vectored_unaligned, tc)
1944022ca2fcSAlan Somers {
1945022ca2fcSAlan Somers atf_tc_set_md_var(tc, "descr",
1946022ca2fcSAlan Somers "Vectored AIO should still work even if the iov contains elements "
1947022ca2fcSAlan Somers "that aren't a multiple of the sector size.");
1948022ca2fcSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
1949022ca2fcSAlan Somers }
ATF_TC_BODY(vectored_unaligned,tc)1950022ca2fcSAlan Somers ATF_TC_BODY(vectored_unaligned, tc)
1951022ca2fcSAlan Somers {
1952022ca2fcSAlan Somers struct aio_context ac;
1953022ca2fcSAlan Somers struct aiocb aio;
1954022ca2fcSAlan Somers struct iovec iov[3];
1955022ca2fcSAlan Somers ssize_t len, total_len;
1956022ca2fcSAlan Somers int fd;
1957022ca2fcSAlan Somers
19580b159faaSLi-Wen Hsu if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
19590b159faaSLi-Wen Hsu atf_tc_skip("https://bugs.freebsd.org/258766");
19600b159faaSLi-Wen Hsu
1961022ca2fcSAlan Somers ATF_REQUIRE_KERNEL_MODULE("aio");
1962022ca2fcSAlan Somers ATF_REQUIRE_UNSAFE_AIO();
1963022ca2fcSAlan Somers
1964022ca2fcSAlan Somers /*
1965022ca2fcSAlan Somers * Use a zvol with volmode=dev, so it will allow .d_write with
1966022ca2fcSAlan Somers * unaligned uio. geom devices use physio, which doesn't allow that.
1967022ca2fcSAlan Somers */
1968*9cefc0fbSMark Johnston fd = aio_zvol_setup(atf_tc_get_ident(tc));
1969022ca2fcSAlan Somers aio_context_init(&ac, fd, fd, FILE_LEN);
1970022ca2fcSAlan Somers
1971022ca2fcSAlan Somers /* Break the buffer into 3 parts:
1972022ca2fcSAlan Somers * * A 4kB part, aligned to 4kB
1973022ca2fcSAlan Somers * * Two other parts that add up to 4kB:
1974022ca2fcSAlan Somers * - 256B
1975022ca2fcSAlan Somers * - 4kB - 256B
1976022ca2fcSAlan Somers */
1977022ca2fcSAlan Somers iov[0].iov_base = ac.ac_buffer;
1978022ca2fcSAlan Somers iov[0].iov_len = 4096;
1979022ca2fcSAlan Somers iov[1].iov_base = (void*)((uintptr_t)iov[0].iov_base + iov[0].iov_len);
1980022ca2fcSAlan Somers iov[1].iov_len = 256;
1981022ca2fcSAlan Somers iov[2].iov_base = (void*)((uintptr_t)iov[1].iov_base + iov[1].iov_len);
1982022ca2fcSAlan Somers iov[2].iov_len = 4096 - iov[1].iov_len;
1983022ca2fcSAlan Somers total_len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
1984022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
1985022ca2fcSAlan Somers aio.aio_fildes = ac.ac_write_fd;
1986022ca2fcSAlan Somers aio.aio_offset = 0;
1987022ca2fcSAlan Somers aio.aio_iov = iov;
1988022ca2fcSAlan Somers aio.aio_iovcnt = 3;
1989022ca2fcSAlan Somers
1990022ca2fcSAlan Somers if (aio_writev(&aio) < 0)
1991022ca2fcSAlan Somers atf_tc_fail("aio_writev failed: %s", strerror(errno));
1992022ca2fcSAlan Somers
1993022ca2fcSAlan Somers len = poll(&aio);
1994022ca2fcSAlan Somers if (len < 0)
1995022ca2fcSAlan Somers atf_tc_fail("aio failed: %s", strerror(errno));
1996022ca2fcSAlan Somers
1997022ca2fcSAlan Somers if (len != total_len)
1998022ca2fcSAlan Somers atf_tc_fail("aio short write (%jd)", (intmax_t)len);
1999022ca2fcSAlan Somers
2000022ca2fcSAlan Somers bzero(&aio, sizeof(aio));
2001022ca2fcSAlan Somers aio.aio_fildes = ac.ac_read_fd;
2002022ca2fcSAlan Somers aio.aio_offset = 0;
2003022ca2fcSAlan Somers aio.aio_iov = iov;
2004022ca2fcSAlan Somers aio.aio_iovcnt = 3;
2005022ca2fcSAlan Somers
2006022ca2fcSAlan Somers if (aio_readv(&aio) < 0)
2007022ca2fcSAlan Somers atf_tc_fail("aio_readv failed: %s", strerror(errno));
2008022ca2fcSAlan Somers len = poll(&aio);
2009022ca2fcSAlan Somers
2010022ca2fcSAlan Somers ATF_REQUIRE_MSG(aio_test_buffer(ac.ac_buffer, total_len,
2011022ca2fcSAlan Somers ac.ac_seed) != 0, "aio_test_buffer: internal error");
2012022ca2fcSAlan Somers
2013022ca2fcSAlan Somers close(fd);
2014022ca2fcSAlan Somers }
ATF_TC_CLEANUP(vectored_unaligned,tc)2015022ca2fcSAlan Somers ATF_TC_CLEANUP(vectored_unaligned, tc)
2016022ca2fcSAlan Somers {
2017*9cefc0fbSMark Johnston aio_zvol_cleanup(atf_tc_get_ident(tc));
2018022ca2fcSAlan Somers }
2019022ca2fcSAlan Somers
2020022ca2fcSAlan Somers static void
aio_zvol_test(completion comp,struct sigevent * sev,bool vectored,const char * unique)2021*9cefc0fbSMark Johnston aio_zvol_test(completion comp, struct sigevent *sev, bool vectored,
2022*9cefc0fbSMark Johnston const char *unique)
2023022ca2fcSAlan Somers {
2024022ca2fcSAlan Somers struct aio_context ac;
2025022ca2fcSAlan Somers int fd;
2026022ca2fcSAlan Somers
2027*9cefc0fbSMark Johnston fd = aio_zvol_setup(unique);
2028022ca2fcSAlan Somers aio_context_init(&ac, fd, fd, MD_LEN);
2029022ca2fcSAlan Somers if (vectored) {
2030022ca2fcSAlan Somers aio_writev_test(&ac, comp, sev);
2031022ca2fcSAlan Somers aio_readv_test(&ac, comp, sev);
2032022ca2fcSAlan Somers } else {
2033022ca2fcSAlan Somers aio_write_test(&ac, comp, sev);
2034022ca2fcSAlan Somers aio_read_test(&ac, comp, sev);
2035022ca2fcSAlan Somers }
2036022ca2fcSAlan Somers
2037022ca2fcSAlan Somers close(fd);
2038022ca2fcSAlan Somers }
2039022ca2fcSAlan Somers
2040022ca2fcSAlan Somers /*
2041022ca2fcSAlan Somers * Note that unlike md, the zvol is not a geom device, does not allow unmapped
2042022ca2fcSAlan Somers * buffers, and does not use physio.
2043022ca2fcSAlan Somers */
2044022ca2fcSAlan Somers ATF_TC_WITH_CLEANUP(vectored_zvol_poll);
ATF_TC_HEAD(vectored_zvol_poll,tc)2045022ca2fcSAlan Somers ATF_TC_HEAD(vectored_zvol_poll, tc)
2046022ca2fcSAlan Somers {
2047022ca2fcSAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
2048022ca2fcSAlan Somers }
ATF_TC_BODY(vectored_zvol_poll,tc)2049022ca2fcSAlan Somers ATF_TC_BODY(vectored_zvol_poll, tc)
2050022ca2fcSAlan Somers {
20510b159faaSLi-Wen Hsu if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
20520b159faaSLi-Wen Hsu atf_tc_skip("https://bugs.freebsd.org/258766");
2053*9cefc0fbSMark Johnston aio_zvol_test(poll, NULL, true, atf_tc_get_ident(tc));
2054022ca2fcSAlan Somers }
ATF_TC_CLEANUP(vectored_zvol_poll,tc)2055022ca2fcSAlan Somers ATF_TC_CLEANUP(vectored_zvol_poll, tc)
2056022ca2fcSAlan Somers {
2057*9cefc0fbSMark Johnston aio_zvol_cleanup(atf_tc_get_ident(tc));
2058022ca2fcSAlan Somers }
2059022ca2fcSAlan Somers
ATF_TP_ADD_TCS(tp)2060f44eb013SEnji Cooper ATF_TP_ADD_TCS(tp)
2061f44eb013SEnji Cooper {
2062f44eb013SEnji Cooper
206357082ce8SAlan Somers /* Test every file type with every completion method */
206457082ce8SAlan Somers ATF_TP_ADD_TC(tp, file_kq);
2065740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, file_poll);
2066314b447fSAlan Somers ATF_TP_ADD_TC(tp, file_signal);
2067740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, file_suspend);
2068314b447fSAlan Somers ATF_TP_ADD_TC(tp, file_thread);
2069740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, file_waitcomplete);
207057082ce8SAlan Somers ATF_TP_ADD_TC(tp, fifo_kq);
2071740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, fifo_poll);
2072314b447fSAlan Somers ATF_TP_ADD_TC(tp, fifo_signal);
2073740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, fifo_suspend);
2074314b447fSAlan Somers ATF_TP_ADD_TC(tp, fifo_thread);
2075740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, fifo_waitcomplete);
207657082ce8SAlan Somers ATF_TP_ADD_TC(tp, socket_kq);
2077740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, socket_poll);
2078314b447fSAlan Somers ATF_TP_ADD_TC(tp, socket_signal);
2079740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, socket_suspend);
2080314b447fSAlan Somers ATF_TP_ADD_TC(tp, socket_thread);
2081740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, socket_waitcomplete);
208257082ce8SAlan Somers ATF_TP_ADD_TC(tp, pty_kq);
2083740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, pty_poll);
2084314b447fSAlan Somers ATF_TP_ADD_TC(tp, pty_signal);
2085740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, pty_suspend);
2086314b447fSAlan Somers ATF_TP_ADD_TC(tp, pty_thread);
2087740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, pty_waitcomplete);
208857082ce8SAlan Somers ATF_TP_ADD_TC(tp, pipe_kq);
2089740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, pipe_poll);
2090314b447fSAlan Somers ATF_TP_ADD_TC(tp, pipe_signal);
2091740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, pipe_suspend);
2092314b447fSAlan Somers ATF_TP_ADD_TC(tp, pipe_thread);
2093740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, pipe_waitcomplete);
209457082ce8SAlan Somers ATF_TP_ADD_TC(tp, md_kq);
2095740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, md_poll);
2096314b447fSAlan Somers ATF_TP_ADD_TC(tp, md_signal);
2097740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, md_suspend);
2098314b447fSAlan Somers ATF_TP_ADD_TC(tp, md_thread);
2099740a9bfaSAlan Somers ATF_TP_ADD_TC(tp, md_waitcomplete);
210057082ce8SAlan Somers
210157082ce8SAlan Somers /* Various special cases */
2102604bbb3fSAlan Somers ATF_TP_ADD_TC(tp, aio_fsync_errors);
2103801ac943SThomas Munro ATF_TP_ADD_TC(tp, aio_fsync_sync_test);
2104801ac943SThomas Munro ATF_TP_ADD_TC(tp, aio_fsync_dsync_test);
2105bb430bc7SJohn Baldwin ATF_TP_ADD_TC(tp, aio_large_read_test);
2106d1ad1a73SJohn Baldwin ATF_TP_ADD_TC(tp, aio_socket_two_reads);
21071717b68aSJohn Baldwin ATF_TP_ADD_TC(tp, aio_socket_blocking_short_write);
2108022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, aio_socket_blocking_short_write_vectored);
2109141fe2dcSMark Johnston ATF_TP_ADD_TC(tp, aio_socket_listen_fail);
2110141fe2dcSMark Johnston ATF_TP_ADD_TC(tp, aio_socket_listen_pending);
2111778ce4f2SJohn Baldwin ATF_TP_ADD_TC(tp, aio_socket_short_write_cancel);
2112c13f6dd7SMark Johnston ATF_TP_ADD_TC(tp, aio_socket_shutdown);
2113022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, aio_writev_dos_iov_len);
2114022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, aio_writev_dos_iovcnt);
2115022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, aio_writev_efault);
2116022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, aio_writev_empty_file_poll);
2117022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, aio_writev_empty_file_signal);
211857082ce8SAlan Somers ATF_TP_ADD_TC(tp, ev_oneshot);
2119022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, vectored_big_iovcnt);
2120022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, vectored_file_poll);
2121022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, vectored_md_poll);
2122022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, vectored_zvol_poll);
2123022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, vectored_unaligned);
2124022ca2fcSAlan Somers ATF_TP_ADD_TC(tp, vectored_socket_poll);
21253904e796SThomas Munro ATF_TP_ADD_TC(tp, vectored_thread);
2126f44eb013SEnji Cooper
2127f44eb013SEnji Cooper return (atf_no_error());
2128f44eb013SEnji Cooper }
2129