From owner-svn-src-all@freebsd.org Tue May 30 03:09:02 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 8A30DAF8BDA; Tue, 30 May 2017 03:09:02 +0000 (UTC) (envelope-from ngie@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 528A67377A; Tue, 30 May 2017 03:09:02 +0000 (UTC) (envelope-from ngie@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v4U391F3053282; Tue, 30 May 2017 03:09:01 GMT (envelope-from ngie@FreeBSD.org) Received: (from ngie@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4U3911t053281; Tue, 30 May 2017 03:09:01 GMT (envelope-from ngie@FreeBSD.org) Message-Id: <201705300309.v4U3911t053281@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ngie set sender to ngie@FreeBSD.org using -f From: Ngie Cooper Date: Tue, 30 May 2017 03:09:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r319173 - stable/11/tests/sys/aio X-SVN-Group: stable-11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 30 May 2017 03:09:02 -0000 Author: ngie Date: Tue May 30 03:09:01 2017 New Revision: 319173 URL: https://svnweb.freebsd.org/changeset/base/319173 Log: MFC r312913,r318100,r318107: r312913 (by asomers): Improve the aio tests * Add tests for aio_suspend(2). * Add tests for polled completion notification. * Test the full matrix of file descriptor types and completion notification mechanisms. * Don't bother with mkstemp, because ATF runs every test in its own temp dir. * Fix some typos. * Remove extraneous ATF_REQUIRE_KERNEL_MODULE calls. r318100: style(9): move function definition curly braces to column 0 r318107: Remove unused constant (PATH_TEMPLATE) It was made unnecessary in r312913. MFC with: r312913 Modified: stable/11/tests/sys/aio/aio_test.c Directory Properties: stable/11/ (props changed) Modified: stable/11/tests/sys/aio/aio_test.c ============================================================================== --- stable/11/tests/sys/aio/aio_test.c Tue May 30 03:05:22 2017 (r319172) +++ stable/11/tests/sys/aio/aio_test.c Tue May 30 03:09:01 2017 (r319173) @@ -33,7 +33,7 @@ * reading it from a second descriptor using AIO. For some targets, the same * fd is used for write and read (i.e., file, md device), but for others the * operation is performed on a peer (pty, socket, fifo, etc). A timeout is - * initiated to detect undo blocking. This test does not attempt to exercise + * initiated to detect undue blocking. This test does not attempt to exercise * error cases or more subtle asynchronous behavior, just make sure that the * basic operations work on some basic object types. */ @@ -63,8 +63,6 @@ #include "freebsd_test_suite/macros.h" #include "local.h" -#define PATH_TEMPLATE "aio.XXXXXXXXXX" - /* * GLOBAL_MAX sets the largest usable buffer size to be read and written, as * it sizes ac_buffer in the aio_context structure. It is also the default @@ -74,6 +72,13 @@ #define GLOBAL_MAX 16384 #define BUFFER_MAX GLOBAL_MAX + +/* + * A completion function will block until the aio has completed, then return + * the result of the aio. errno will be set appropriately. + */ +typedef ssize_t (*completion)(struct aiocb*); + struct aio_context { int ac_read_fd, ac_write_fd; long ac_seed; @@ -179,6 +184,48 @@ aio_context_init(struct aio_context *ac, int read_fd, ac->ac_cleanup_arg = cleanup_arg; } +static ssize_t +poll(struct aiocb *aio) +{ + int err; + + while ((err = aio_error(aio)) == EINPROGRESS && !aio_timedout) + usleep(25000); + switch (err) { + case EINPROGRESS: + errno = EINTR; + return (-1); + case 0: + return (aio_return(aio)); + default: + return (err); + } +} + +static ssize_t +suspend(struct aiocb *aio) +{ + const struct aiocb *const iocbs[] = {aio}; + int err; + + err = aio_suspend(iocbs, 1, NULL); + if (err == 0) + return (aio_return(aio)); + else + return (err); +} + +static ssize_t +waitcomplete(struct aiocb *aio) +{ + struct aiocb *aiop; + ssize_t ret; + + ret = aio_waitcomplete(&aiop, NULL); + ATF_REQUIRE_EQ(aio, aiop); + return (ret); +} + /* * Each tester can register a callback to clean up in the event the test * fails. Preserve the value of errno so that subsequent calls to errx() @@ -201,13 +248,11 @@ aio_cleanup(struct aio_context *ac) * file descriptor. */ static void -aio_write_test(struct aio_context *ac) +aio_write_test(struct aio_context *ac, completion comp) { - struct aiocb aio, *aiop; + struct aiocb aio; ssize_t len; - ATF_REQUIRE_KERNEL_MODULE("aio"); - bzero(&aio, sizeof(aio)); aio.aio_buf = ac->ac_buffer; aio.aio_nbytes = ac->ac_buflen; @@ -227,24 +272,23 @@ aio_write_test(struct aio_context *ac) atf_tc_fail("aio_write failed: %s", strerror(errno)); } - len = aio_waitcomplete(&aiop, NULL); + len = comp(&aio); if (len < 0) { if (errno == EINTR) { if (aio_timedout) { aio_cleanup(ac); - atf_tc_fail("aio_waitcomplete timed out"); + atf_tc_fail("aio timed out"); } } aio_cleanup(ac); - atf_tc_fail("aio_waitcomplete failed: %s", strerror(errno)); + atf_tc_fail("aio failed: %s", strerror(errno)); } aio_timeout_stop(); if (len != ac->ac_buflen) { aio_cleanup(ac); - atf_tc_fail("aio_waitcomplete short write (%jd)", - (intmax_t)len); + atf_tc_fail("aio short write (%jd)", (intmax_t)len); } } @@ -253,13 +297,11 @@ aio_write_test(struct aio_context *ac) * provided file descriptor. */ static void -aio_read_test(struct aio_context *ac) +aio_read_test(struct aio_context *ac, completion comp) { - struct aiocb aio, *aiop; + struct aiocb aio; ssize_t len; - ATF_REQUIRE_KERNEL_MODULE("aio"); - bzero(ac->ac_buffer, ac->ac_buflen); bzero(&aio, sizeof(aio)); aio.aio_buf = ac->ac_buffer; @@ -273,30 +315,30 @@ aio_read_test(struct aio_context *ac) if (errno == EINTR) { if (aio_timedout) { aio_cleanup(ac); - atf_tc_fail("aio_write timed out"); + atf_tc_fail("aio_read timed out"); } } aio_cleanup(ac); atf_tc_fail("aio_read failed: %s", strerror(errno)); } - len = aio_waitcomplete(&aiop, NULL); + len = comp(&aio); if (len < 0) { if (errno == EINTR) { if (aio_timedout) { aio_cleanup(ac); - atf_tc_fail("aio_waitcomplete timed out"); + atf_tc_fail("aio timed out"); } } aio_cleanup(ac); - atf_tc_fail("aio_waitcomplete failed: %s", strerror(errno)); + atf_tc_fail("aio failed: %s", strerror(errno)); } aio_timeout_stop(); if (len != ac->ac_buflen) { aio_cleanup(ac); - atf_tc_fail("aio_waitcomplete short read (%jd)", + atf_tc_fail("aio short read (%jd)", (intmax_t)len); } @@ -316,9 +358,11 @@ aio_read_test(struct aio_context *ac) * Test with a classic file. Assumes we can create a moderate size temporary * file. */ +#define FILE_LEN GLOBAL_MAX +#define FILE_PATHNAME "testfile" +#define FILE_TIMEOUT 30 struct aio_file_arg { int afa_fd; - char *afa_pathname; }; static void @@ -328,15 +372,12 @@ aio_file_cleanup(void *arg) afa = arg; close(afa->afa_fd); - unlink(afa->afa_pathname); + unlink(FILE_PATHNAME); } -#define FILE_LEN GLOBAL_MAX -#define FILE_TIMEOUT 30 -ATF_TC_WITHOUT_HEAD(aio_file_test); -ATF_TC_BODY(aio_file_test, tc) +static void +aio_file_test(completion comp) { - char pathname[PATH_MAX]; struct aio_file_arg arg; struct aio_context ac; int fd; @@ -344,25 +385,43 @@ ATF_TC_BODY(aio_file_test, tc) ATF_REQUIRE_KERNEL_MODULE("aio"); ATF_REQUIRE_UNSAFE_AIO(); - strcpy(pathname, PATH_TEMPLATE); - fd = mkstemp(pathname); - ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno)); + fd = open(FILE_PATHNAME, O_RDWR | O_CREAT); + ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno)); arg.afa_fd = fd; - arg.afa_pathname = pathname; aio_context_init(&ac, fd, fd, FILE_LEN, FILE_TIMEOUT, aio_file_cleanup, &arg); - aio_write_test(&ac); - aio_read_test(&ac); + aio_write_test(&ac, comp); + aio_read_test(&ac, comp); aio_file_cleanup(&arg); } +ATF_TC_WITHOUT_HEAD(file_poll); +ATF_TC_BODY(file_poll, tc) +{ + aio_file_test(poll); +} + +ATF_TC_WITHOUT_HEAD(file_suspend); +ATF_TC_BODY(file_suspend, tc) +{ + aio_file_test(suspend); +} + +ATF_TC_WITHOUT_HEAD(file_waitcomplete); +ATF_TC_BODY(file_waitcomplete, tc) +{ + aio_file_test(waitcomplete); +} + +#define FIFO_LEN 256 +#define FIFO_PATHNAME "testfifo" +#define FIFO_TIMEOUT 30 struct aio_fifo_arg { int afa_read_fd; int afa_write_fd; - char *afa_pathname; }; static void @@ -375,39 +434,25 @@ aio_fifo_cleanup(void *arg) close(afa->afa_read_fd); if (afa->afa_write_fd != -1) close(afa->afa_write_fd); - unlink(afa->afa_pathname); + unlink(FIFO_PATHNAME); } -#define FIFO_LEN 256 -#define FIFO_TIMEOUT 30 -ATF_TC_WITHOUT_HEAD(aio_fifo_test); -ATF_TC_BODY(aio_fifo_test, tc) +static void +aio_fifo_test(completion comp) { int error, read_fd = -1, write_fd = -1; struct aio_fifo_arg arg; - char pathname[PATH_MAX]; struct aio_context ac; ATF_REQUIRE_KERNEL_MODULE("aio"); ATF_REQUIRE_UNSAFE_AIO(); - /* - * In theory, mkstemp() can return a name that is then collided with. - * Because this is a regression test, we treat that as a test failure - * rather than retrying. - */ - strcpy(pathname, PATH_TEMPLATE); - ATF_REQUIRE_MSG(mkstemp(pathname) != -1, - "mkstemp failed: %s", strerror(errno)); - ATF_REQUIRE_MSG(unlink(pathname) == 0, - "unlink failed: %s", strerror(errno)); - ATF_REQUIRE_MSG(mkfifo(pathname, 0600) != -1, + ATF_REQUIRE_MSG(mkfifo(FIFO_PATHNAME, 0600) != -1, "mkfifo failed: %s", strerror(errno)); - arg.afa_pathname = pathname; arg.afa_read_fd = -1; arg.afa_write_fd = -1; - read_fd = open(pathname, O_RDONLY | O_NONBLOCK); + read_fd = open(FIFO_PATHNAME, O_RDONLY | O_NONBLOCK); if (read_fd == -1) { error = errno; aio_fifo_cleanup(&arg); @@ -417,7 +462,7 @@ ATF_TC_BODY(aio_fifo_test, tc) } arg.afa_read_fd = read_fd; - write_fd = open(pathname, O_WRONLY); + write_fd = open(FIFO_PATHNAME, O_WRONLY); if (write_fd == -1) { error = errno; aio_fifo_cleanup(&arg); @@ -429,12 +474,30 @@ ATF_TC_BODY(aio_fifo_test, tc) aio_context_init(&ac, read_fd, write_fd, FIFO_LEN, FIFO_TIMEOUT, aio_fifo_cleanup, &arg); - aio_write_test(&ac); - aio_read_test(&ac); + aio_write_test(&ac, comp); + aio_read_test(&ac, comp); aio_fifo_cleanup(&arg); } +ATF_TC_WITHOUT_HEAD(fifo_poll); +ATF_TC_BODY(fifo_poll, tc) +{ + aio_fifo_test(poll); +} + +ATF_TC_WITHOUT_HEAD(fifo_suspend); +ATF_TC_BODY(fifo_suspend, tc) +{ + aio_fifo_test(waitcomplete); +} + +ATF_TC_WITHOUT_HEAD(fifo_waitcomplete); +ATF_TC_BODY(fifo_waitcomplete, tc) +{ + aio_fifo_test(waitcomplete); +} + struct aio_unix_socketpair_arg { int asa_sockets[2]; }; @@ -451,8 +514,8 @@ aio_unix_socketpair_cleanup(void *arg) #define UNIX_SOCKETPAIR_LEN 256 #define UNIX_SOCKETPAIR_TIMEOUT 30 -ATF_TC_WITHOUT_HEAD(aio_unix_socketpair_test); -ATF_TC_BODY(aio_unix_socketpair_test, tc) +static void +aio_unix_socketpair_test(completion comp) { struct aio_unix_socketpair_arg arg; struct aio_context ac; @@ -471,12 +534,12 @@ ATF_TC_BODY(aio_unix_socketpair_test, tc) aio_unix_socketpair_cleanup, &arg); ATF_REQUIRE_MSG(getrusage(RUSAGE_SELF, &ru_before) != -1, "getrusage failed: %s", strerror(errno)); - aio_write_test(&ac); + aio_write_test(&ac, comp); ATF_REQUIRE_MSG(getrusage(RUSAGE_SELF, &ru_after) != -1, "getrusage failed: %s", strerror(errno)); ATF_REQUIRE(ru_after.ru_msgsnd == ru_before.ru_msgsnd + 1); ru_before = ru_after; - aio_read_test(&ac); + aio_read_test(&ac, comp); ATF_REQUIRE_MSG(getrusage(RUSAGE_SELF, &ru_after) != -1, "getrusage failed: %s", strerror(errno)); ATF_REQUIRE(ru_after.ru_msgrcv == ru_before.ru_msgrcv + 1); @@ -484,6 +547,24 @@ ATF_TC_BODY(aio_unix_socketpair_test, tc) aio_unix_socketpair_cleanup(&arg); } +ATF_TC_WITHOUT_HEAD(socket_poll); +ATF_TC_BODY(socket_poll, tc) +{ + aio_unix_socketpair_test(poll); +} + +ATF_TC_WITHOUT_HEAD(socket_suspend); +ATF_TC_BODY(socket_suspend, tc) +{ + aio_unix_socketpair_test(suspend); +} + +ATF_TC_WITHOUT_HEAD(socket_waitcomplete); +ATF_TC_BODY(socket_waitcomplete, tc) +{ + aio_unix_socketpair_test(waitcomplete); +} + struct aio_pty_arg { int apa_read_fd; int apa_write_fd; @@ -501,8 +582,8 @@ aio_pty_cleanup(void *arg) #define PTY_LEN 256 #define PTY_TIMEOUT 30 -ATF_TC_WITHOUT_HEAD(aio_pty_test); -ATF_TC_BODY(aio_pty_test, tc) +static void +aio_pty_test(completion comp) { struct aio_pty_arg arg; struct aio_context ac; @@ -535,12 +616,30 @@ ATF_TC_BODY(aio_pty_test, tc) aio_context_init(&ac, read_fd, write_fd, PTY_LEN, PTY_TIMEOUT, aio_pty_cleanup, &arg); - aio_write_test(&ac); - aio_read_test(&ac); + aio_write_test(&ac, comp); + aio_read_test(&ac, comp); aio_pty_cleanup(&arg); } +ATF_TC_WITHOUT_HEAD(pty_poll); +ATF_TC_BODY(pty_poll, tc) +{ + aio_pty_test(poll); +} + +ATF_TC_WITHOUT_HEAD(pty_suspend); +ATF_TC_BODY(pty_suspend, tc) +{ + aio_pty_test(suspend); +} + +ATF_TC_WITHOUT_HEAD(pty_waitcomplete); +ATF_TC_BODY(pty_waitcomplete, tc) +{ + aio_pty_test(waitcomplete); +} + static void aio_pipe_cleanup(void *arg) { @@ -552,8 +651,8 @@ aio_pipe_cleanup(void *arg) #define PIPE_LEN 256 #define PIPE_TIMEOUT 30 -ATF_TC_WITHOUT_HEAD(aio_pipe_test); -ATF_TC_BODY(aio_pipe_test, tc) +static void +aio_pipe_test(completion comp) { struct aio_context ac; int pipes[2]; @@ -566,12 +665,30 @@ ATF_TC_BODY(aio_pipe_test, tc) aio_context_init(&ac, pipes[0], pipes[1], PIPE_LEN, PIPE_TIMEOUT, aio_pipe_cleanup, pipes); - aio_write_test(&ac); - aio_read_test(&ac); + aio_write_test(&ac, comp); + aio_read_test(&ac, comp); aio_pipe_cleanup(pipes); } +ATF_TC_WITHOUT_HEAD(pipe_poll); +ATF_TC_BODY(pipe_poll, tc) +{ + aio_pipe_test(poll); +} + +ATF_TC_WITHOUT_HEAD(pipe_suspend); +ATF_TC_BODY(pipe_suspend, tc) +{ + aio_pipe_test(suspend); +} + +ATF_TC_WITHOUT_HEAD(pipe_waitcomplete); +ATF_TC_BODY(pipe_waitcomplete, tc) +{ + aio_pipe_test(waitcomplete); +} + struct aio_md_arg { int ama_mdctl_fd; int ama_unit; @@ -608,14 +725,9 @@ aio_md_cleanup(void *arg) #define MD_LEN GLOBAL_MAX #define MD_TIMEOUT 30 -ATF_TC(aio_md_test); -ATF_TC_HEAD(aio_md_test, tc) +static void +aio_md_test(completion comp) { - - atf_tc_set_md_var(tc, "require.user", "root"); -} -ATF_TC_BODY(aio_md_test, tc) -{ int error, fd, mdctl_fd, unit; char pathname[PATH_MAX]; struct aio_md_arg arg; @@ -654,16 +766,48 @@ ATF_TC_BODY(aio_md_test, tc) aio_context_init(&ac, fd, fd, MD_LEN, MD_TIMEOUT, aio_md_cleanup, &arg); - aio_write_test(&ac); - aio_read_test(&ac); + aio_write_test(&ac, comp); + aio_read_test(&ac, comp); aio_md_cleanup(&arg); } +ATF_TC(md_poll); +ATF_TC_HEAD(md_poll, tc) +{ + + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(md_poll, tc) +{ + aio_md_test(poll); +} + +ATF_TC(md_suspend); +ATF_TC_HEAD(md_suspend, tc) +{ + + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(md_suspend, tc) +{ + aio_md_test(suspend); +} + +ATF_TC(md_waitcomplete); +ATF_TC_HEAD(md_waitcomplete, tc) +{ + + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(md_waitcomplete, tc) +{ + aio_md_test(waitcomplete); +} + ATF_TC_WITHOUT_HEAD(aio_large_read_test); ATF_TC_BODY(aio_large_read_test, tc) { - char pathname[PATH_MAX]; struct aiocb cb, *cbp; ssize_t nread; size_t len; @@ -689,11 +833,10 @@ ATF_TC_BODY(aio_large_read_test, tc) len = INT_MAX; #endif - strcpy(pathname, PATH_TEMPLATE); - fd = mkstemp(pathname); - ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno)); + fd = open(FILE_PATHNAME, O_RDWR | O_CREAT); + ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno)); - unlink(pathname); + unlink(FILE_PATHNAME); memset(&cb, 0, sizeof(cb)); cb.aio_nbytes = len; @@ -937,7 +1080,6 @@ ATF_TC_BODY(aio_fsync_test, tc) char *buffer; } buffers[16]; struct stat sb; - char pathname[PATH_MAX]; ssize_t rval; unsigned i; int fd; @@ -945,10 +1087,9 @@ ATF_TC_BODY(aio_fsync_test, tc) ATF_REQUIRE_KERNEL_MODULE("aio"); ATF_REQUIRE_UNSAFE_AIO(); - strcpy(pathname, PATH_TEMPLATE); - fd = mkstemp(pathname); - ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno)); - unlink(pathname); + fd = open(FILE_PATHNAME, O_RDWR | O_CREAT); + ATF_REQUIRE_MSG(fd != -1, "open failed: %s", strerror(errno)); + unlink(FILE_PATHNAME); ATF_REQUIRE(fstat(fd, &sb) == 0); ATF_REQUIRE(sb.st_blksize != 0); @@ -1009,12 +1150,24 @@ ATF_TC_BODY(aio_fsync_test, tc) ATF_TP_ADD_TCS(tp) { - ATF_TP_ADD_TC(tp, aio_file_test); - ATF_TP_ADD_TC(tp, aio_fifo_test); - ATF_TP_ADD_TC(tp, aio_unix_socketpair_test); - ATF_TP_ADD_TC(tp, aio_pty_test); - ATF_TP_ADD_TC(tp, aio_pipe_test); - ATF_TP_ADD_TC(tp, aio_md_test); + ATF_TP_ADD_TC(tp, file_poll); + ATF_TP_ADD_TC(tp, file_suspend); + ATF_TP_ADD_TC(tp, file_waitcomplete); + ATF_TP_ADD_TC(tp, fifo_poll); + ATF_TP_ADD_TC(tp, fifo_suspend); + ATF_TP_ADD_TC(tp, fifo_waitcomplete); + ATF_TP_ADD_TC(tp, socket_poll); + ATF_TP_ADD_TC(tp, socket_suspend); + ATF_TP_ADD_TC(tp, socket_waitcomplete); + ATF_TP_ADD_TC(tp, pty_poll); + ATF_TP_ADD_TC(tp, pty_suspend); + ATF_TP_ADD_TC(tp, pty_waitcomplete); + ATF_TP_ADD_TC(tp, pipe_poll); + ATF_TP_ADD_TC(tp, pipe_suspend); + ATF_TP_ADD_TC(tp, pipe_waitcomplete); + ATF_TP_ADD_TC(tp, md_poll); + ATF_TP_ADD_TC(tp, md_suspend); + ATF_TP_ADD_TC(tp, md_waitcomplete); ATF_TP_ADD_TC(tp, aio_large_read_test); ATF_TP_ADD_TC(tp, aio_socket_two_reads); ATF_TP_ADD_TC(tp, aio_socket_blocking_short_write);