[LTP] [PATCH] [COMMITTED] io_submit01: Rewrite & fix.

Cyril Hrubis chrubis@suse.cz
Thu Jun 1 12:47:18 CEST 2017


* Rewrite the test to the new API

* Drop uninitialized iocb test since that
  one invokes undefined behavior and may
  fail with pretty much any error

* Add a few more cases
  - write request for readonly file -- EBADFD
  - read request for writeonly file -- EBADFD

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 testcases/kernel/syscalls/io_submit/io_submit01.c | 269 +++++++++-------------
 1 file changed, 106 insertions(+), 163 deletions(-)

diff --git a/testcases/kernel/syscalls/io_submit/io_submit01.c b/testcases/kernel/syscalls/io_submit/io_submit01.c
index fd01e6ede..9baf520b8 100644
--- a/testcases/kernel/syscalls/io_submit/io_submit01.c
+++ b/testcases/kernel/syscalls/io_submit/io_submit01.c
@@ -1,32 +1,27 @@
 /*
+ * Copyright (c) Crackerjack Project., 2007
+ * Copyright (c) 2011-2017 Cyril Hrubis <chrubis@suse.cz>
  *
- *   Copyright (c) Crackerjack Project., 2007
- *   Copyright (c) 2011 Cyril Hrubis <chrubis@suse.cz>
+ * This program is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY;  without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ * the GNU General Public License for more details.
  *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program;  if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * You should have received a copy of the GNU General Public License
+ * along with this program;  if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 /* Porting from Crackerjack to LTP is done
    by Masatake YAMATO <yamato@redhat.com> */
 
 #include "config.h"
-#include "test.h"
-
-char *TCID = "io_submit01";
-
-int TST_TOTAL = 3;
+#include "tst_test.h"
 
 #ifdef HAVE_LIBAIO_H
 #include <libaio.h>
@@ -34,167 +29,115 @@ int TST_TOTAL = 3;
 #include <string.h>
 #include <fcntl.h>
 
-#define TESTFILE	"testfile"
-
-static void cleanup(void)
-{
-	tst_rmdir();
-}
+static io_context_t ctx;
+static io_context_t invalid_ctx;
+
+static struct iocb iocb;
+static struct iocb *iocbs[] = {&iocb};
+
+static struct iocb inv_fd_iocb;
+static struct iocb *inv_fd_iocbs[] = {&inv_fd_iocb};
+
+static int rdonly_fd;
+static struct iocb rdonly_fd_iocb;
+static struct iocb *rdonly_fd_iocbs[] = {&rdonly_fd_iocb};
+
+static int wronly_fd;
+static struct iocb wronly_fd_iocb;
+static struct iocb *wronly_fd_iocbs[] = {&wronly_fd_iocb};
+
+static struct iocb zero_buf_iocb;
+static struct iocb *zero_buf_iocbs[] = {&zero_buf_iocb};
+
+static struct iocb *zero_iocbs[1];
+
+static char buf[100];
+
+static struct tcase {
+	io_context_t *ctx;
+	long nr;
+	struct iocb **iocbs;
+	int exp_errno;
+	const char *desc;
+} tcases[] = {
+	/* Invalid ctx */
+	{&invalid_ctx, 1, iocbs, -EINVAL, "invalid ctx"},
+	/* Invalid nr */
+	{&ctx, -1, iocbs, -EINVAL, "invalid nr"},
+	/* Invalid pointer */
+	{&ctx, 1, (void*)-1, -EFAULT, "invalid iocbpp pointer"},
+	{&ctx, 1, zero_iocbs, -EFAULT, "NULL iocb pointers"},
+	/* Invalid fd */
+	{&ctx, 1, inv_fd_iocbs, -EBADF, "invalid fd"},
+	{&ctx, 1, rdonly_fd_iocbs, -EBADF, "readonly fd for write"},
+	{&ctx, 1, wronly_fd_iocbs, -EBADF, "writeonly fd for read"},
+	/* No-op but should work fine */
+	{&ctx, 1, zero_buf_iocbs, 1, "zero buf size"},
+	{&ctx, 0, NULL, 0, "zero nr"},
+};
 
 static void setup(void)
 {
-	int fd;
+	int rval;
+
+	rval = io_setup(1, &ctx);
+	if (rval)
+		tst_brk(TBROK | TERRNO, "io_setup() returned %d", rval);
 
-	tst_sig(NOFORK, DEF_HANDLER, cleanup);
+	io_prep_pread(&inv_fd_iocb, -1, buf, sizeof(buf), 0);
 
-	TEST_PAUSE;
+	rdonly_fd = SAFE_OPEN("rdonly_file", O_RDONLY | O_CREAT, 0777);
+	io_prep_pwrite(&rdonly_fd_iocb, rdonly_fd, buf, sizeof(buf), 0);
 
-	tst_tmpdir();
+	io_prep_pread(&zero_buf_iocb, rdonly_fd, buf, 0, 0);
 
-	fd = open(TESTFILE, O_CREAT | O_RDWR, 0755);
-	if (fd == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "open");
-	if (close(fd) == -1)
-		tst_brkm(TBROK | TERRNO, cleanup, "close");
+	wronly_fd = SAFE_OPEN("wronly_file", O_WRONLY | O_CREAT, 0777);
+	io_prep_pread(&wronly_fd_iocb, wronly_fd, buf, sizeof(buf), 0);
 }
 
-static void check_result(long exp, long act)
+static void cleanup(void)
 {
-	if (exp >= 0) {
-		if (act == exp)
-			tst_resm(TPASS, "expected success - "
-				 "returned value = %ld", act);
-		else
-			tst_resm(TFAIL, "unexpected failure - "
-				 "returned value = %ld : %s",
-				 act, strerror(-1 * act));
-		return;
-	}
+	if (rdonly_fd > 0)
+		SAFE_CLOSE(rdonly_fd);
 
-	/* if return value is expected to be < 0 */
-	if (act == exp)
-		tst_resm(TPASS, "expected failure - "
-			 "returned value = %ld : %s", act, strerror(-1 * act));
-	else if (act == 0)
-		tst_resm(TFAIL, "call succeeded unexpectedly");
-	else
-		tst_resm(TFAIL, "unexpected failure - "
-			 "returned value = %ld : %s, "
-			 "expected value = %ld : %s",
-			 act, strerror(-1 * act), exp, strerror(-1 * exp));
+	if (wronly_fd > 0)
+		SAFE_CLOSE(wronly_fd);
 }
 
-int main(int argc, char *argv[])
+static const char *errno_name(int err)
 {
-	int lc;
-
-	int rval, fd;
-	char buf[256];
-	struct iocb iocb;
-	struct iocb *iocbs[1];
-	io_context_t ctx;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-		tst_count = 0;
-
-		/* 1 - EINVAL */
-		/* 1.1 - EINVAL: invalid ctx */
-		memset(&ctx, 0, sizeof(ctx));
-		TEST(io_submit(ctx, 0, NULL));
-		check_result(-EINVAL, TEST_RETURN);
-
-		/* 1.2 - EINVAL: invalid nr */
-		rval = io_setup(1, &ctx);
-		if (rval != 0)
-			tst_brkm(TBROK, cleanup, "io_setup failed: %d", rval);
-		TEST(io_submit(ctx, -1, NULL));
-		check_result(-EINVAL, TEST_RETURN);
-
-		/* 1.3 - EINVAL: uninitialized iocb */
-		iocbs[0] = &iocb;
-
-		/* There are multiple checks we can hit with uninitialized
-		 * iocb, but with "random" data it's not 100%. Make sure we
-		 * fail eventually in opcode check. */
-		iocb.aio_lio_opcode = -1;
-
-		TEST(io_submit(ctx, 1, iocbs));
-		switch (TEST_RETURN) {
-		case -EINVAL:
-		case -EBADF:
-		case -EFAULT:
-			tst_resm(TPASS, "expected failure - "
-				 "returned value = %ld : %s",
-				 TEST_RETURN, strerror(-1 * TEST_RETURN));
-			break;
-		default:
-			tst_resm(TFAIL, "unexpected failure - "
-				 "returned value = %ld : %s, "
-				 "expected one of -EINVAL, -EBADF, -EFAULT",
-				 TEST_RETURN, strerror(-1 * TEST_RETURN));
-		}
-
-		/* 2 - EFAULT: iocb points to invalid data */
-		TEST(io_submit(ctx, 1, (struct iocb **)-1));
-		check_result(-EFAULT, TEST_RETURN);
-
-		/*
-		 * 3 - Special case EFAULT or EINVAL (indetermination)
-		 *
-		 * The errno depends on the per architecture implementation
-		 * of io_submit. On the architecture using compat_sys_io_submit
-		 * as its implementation, errno is set to -EINVAL.
-		 */
-		TEST(io_submit(ctx, -1, (struct iocb **)-1));
-		if (TEST_RETURN == 0)
-			tst_resm(TFAIL, "call succeeded unexpectedly");
-		else if (TEST_RETURN == -EFAULT || TEST_RETURN == -EINVAL)
-			tst_resm(TPASS, "expected failure - "
-				 "returned value = %ld : %s",
-				 TEST_RETURN, strerror(-1 * TEST_RETURN));
-		else
-			tst_resm(TFAIL, "unexpected failure - "
-				 "returned value = %ld : %s, "
-				 "expected = %d : %s or %d : %s",
-				 TEST_RETURN, strerror(-1 * TEST_RETURN),
-				 -EFAULT, strerror(EFAULT),
-				 -EINVAL, strerror(EINVAL));
-
-		/*
-		 * 4 - EBADF: fd in iocb is invalid
-		 */
-		io_prep_pread(&iocb, -1, buf, sizeof(buf), 0);
-		iocbs[0] = &iocb;
-		TEST(io_submit(ctx, 1, iocbs));
-		check_result(-EBADF, TEST_RETURN);
-
-		/* 5 - Positive test: nr == 0 */
-		TEST(io_submit(ctx, 0, NULL));
-		check_result(0, TEST_RETURN);
-
-		/* 6 - Positive test: valid fd */
-		fd = open(TESTFILE, O_RDONLY);
-		if (fd == -1)
-			tst_resm(TBROK | TERRNO, "open");
-		io_prep_pread(&iocb, fd, buf, sizeof(buf), 0);
-		iocbs[0] = &iocb;
-		TEST(io_submit(ctx, 1, iocbs));
-		check_result(1, TEST_RETURN);
-		if (close(fd) == -1)
-			tst_resm(TBROK | TERRNO, "close");
+	if (err <= 0)
+		return tst_strerrno(-err);
 
+	return "SUCCESS";
+}
+
+static void verify_io_submit(unsigned int n)
+{
+	struct tcase *t = &tcases[n];
+	int ret;
+
+	ret = io_submit(*t->ctx, t->nr, t->iocbs);
+
+	if (ret == t->exp_errno) {
+		tst_res(TPASS, "io_submit() with %s failed with %s",
+			t->desc, errno_name(t->exp_errno));
+		return;
 	}
-	cleanup();
 
-	tst_exit();
+	tst_res(TFAIL, "io_submit() returned %i(%s), expected %s(%i)",
+		ret, ret < 0 ? tst_strerrno(-ret) : "SUCCESS",
+		errno_name(t->exp_errno), t->exp_errno);
 }
+
+static struct tst_test test = {
+	.setup = setup,
+	.cleanup = cleanup,
+	.test = verify_io_submit,
+	.tcnt = ARRAY_SIZE(tcases),
+	.needs_tmpdir = 1,
+};
+
 #else
-int main(int argc, char *argv[])
-{
-	tst_brkm(TCONF, NULL, "System doesn't support execution of the test");
-}
+	TST_TEST_TCONF("libaio.h was mission upon compilation");
 #endif
-- 
2.13.0



More information about the ltp mailing list