Skip to contentSkip to conversation

syscalls: new test writev07

PATCH New Jan Stancek 3 participants 10 messages Oct 7, 2016 – Dec 1, 2016

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/3 syscalls: new test writev07

Verify writev() behaviour with partially valid iovec list. Kernel <4.8 used to shorten write up to first bad invalid iovec. Starting with 4.8, a writev with short data (under page size) is likely to get shorten to 0 bytes and return EFAULT.

This test doesn't make assumptions how much will write get shortened. It only tests that file content/offset after syscall corresponds to return value of writev().

See: [RFC] writev() semantics with invalid iovec in the middle

     https://marc.info/?l=linux-kernel&m=147388891614289&w=2

This test is meant to be replacement for writev03/writev04 and part of writev01, which all deal with partially invalid iovec lists, and all currently fail with 4.8 kernel.

---
Changes in v2:
- use tst_res_hexd
- smaller iovec with less random offsets and sizes
- fix tid

 runtest/ltplite                             |   1 +
 runtest/stress.part3                        |   1 +
 runtest/syscalls                            |   1 +
 testcases/kernel/syscalls/.gitignore        |   1 +
 testcases/kernel/syscalls/writev/writev07.c | 152 ++++++++++++++++++++++++++++
 5 files changed, 156 insertions(+)
 create mode 100644 testcases/kernel/syscalls/writev/writev07.c
runtest/ltplite +1 -0
index 42d9a039ad34..1b4c5f6ee279 100644
@@ -1047,6 +1047,7 @@ writev03 writev03
 writev04 writev04
 writev05 writev05
 writev06 writev06
+writev07 writev07
 
 #DESCRIPTION:Memory Mgmt tests
 mm01 mmap001 -m 10000
runtest/stress.part3 +1 -0
index fa75b5c08526..effa5fd9b14e 100644
@@ -908,6 +908,7 @@ writev03 writev03
 writev04 writev04
 writev05 writev05
 writev06 writev06
+writev07 writev07
 
 pty01 pty01
 hangup01 hangup01
runtest/syscalls +1 -0
index 01839e83bf83..88f75971cb3d 100644
@@ -1426,6 +1426,7 @@ writev03 writev03
 writev04 writev04
 writev05 writev05
 writev06 writev06
+writev07 writev07
 
 perf_event_open01 perf_event_open01
 perf_event_open02 perf_event_open02
testcases/kernel/syscalls/.gitignore +1 -0
index a13dbb3c5a99..f2aeab45e5bb 100644
@@ -1104,6 +1104,7 @@
 /writev/writev04
 /writev/writev05
 /writev/writev06
+/writev/writev07
 /fanotify/fanotify01
 /fanotify/fanotify02
 /fanotify/fanotify03
testcases/kernel/syscalls/writev/writev07.c new file +152 -0

152 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#1 lore raw

PATCH v2 2/3 writev: remove writev03 and writev04

Removed tests are almost identical, and there is now a new
test: writev07, which is meant to be a replacement.

---
 doc/testcases/kernel.txt                    |  23 --
 runtest/ltplite                             |   2 -
 runtest/stress.part3                        |   2 -
 runtest/syscalls                            |   2 -
 testcases/kernel/syscalls/.gitignore        |   2 -
 testcases/kernel/syscalls/writev/Makefile   |   2 +-
 testcases/kernel/syscalls/writev/writev03.c | 271 ---------------------
 testcases/kernel/syscalls/writev/writev04.c | 353 ----------------------------
 8 files changed, 1 insertion(+), 656 deletions(-)
 delete mode 100644 testcases/kernel/syscalls/writev/writev03.c
 delete mode 100644 testcases/kernel/syscalls/writev/writev04.c
doc/testcases/kernel.txt +0 -23
index fa5d686e525e..518ef87948da 100644
@@ -6897,29 +6897,6 @@
 		ltp/testcases/kernel/syscalls/writev/writev02.c
 	<\test_location>
 <\testname>
-<testname=writev03>
-	<description>
-		The testcases are written calling writev() with partially valid data
-		to overwrite the contents, to write in the beginning and to write in
-		the end of the file.
-
-	<\description>
-	<test_location>
-		ltp/testcases/kernel/syscalls/writev/writev03.c
-	<\test_location>
-<\testname>
-<testname=writev04>
-	<description>
-		The testcases are written calling writev() with partially valid data
-		to overwrite the contents, to write in the beginning and to write in
-		the end of the file. This is same as writev03, but the length of
-		buffer used here is 8192 bytes.
-
-	<\description>
-	<test_location>
-		ltp/testcases/kernel/syscalls/writev/writev04.c
-	<\test_location>
-<\testname>
 <testname=writev05>
 	<description>
 		These testcases are written to test writev() on sparse files. This
runtest/ltplite +0 -2
index 1b4c5f6ee279..338d6ebc32bd 100644
@@ -1043,8 +1043,6 @@ write05 write05
 
 writev01 writev01
 writev02 writev02
-writev03 writev03
-writev04 writev04
 writev05 writev05
 writev06 writev06
 writev07 writev07
runtest/stress.part3 +0 -2
index effa5fd9b14e..8abed95a0d0a 100644
@@ -904,8 +904,6 @@ write05 write05
 
 writev01 writev01
 writev02 writev02
-writev03 writev03
-writev04 writev04
 writev05 writev05
 writev06 writev06
 writev07 writev07
runtest/syscalls +0 -2
index 88f75971cb3d..b7812410a843 100644
@@ -1422,8 +1422,6 @@ write05 write05
 
 writev01 writev01
 writev02 writev02
-writev03 writev03
-writev04 writev04
 writev05 writev05
 writev06 writev06
 writev07 writev07
testcases/kernel/syscalls/.gitignore +0 -2
index f2aeab45e5bb..f53cc0513224 100644
@@ -1100,8 +1100,6 @@
 /write/write05
 /writev/writev01
 /writev/writev02
-/writev/writev03
-/writev/writev04
 /writev/writev05
 /writev/writev06
 /writev/writev07
testcases/kernel/syscalls/writev/Makefile +1 -1
index 4aa38befa598..85965e4cb17d 100644
@@ -19,7 +19,7 @@
 top_srcdir		?= ../../../..
 
 ifeq ($(UCLINUX),1)
-FILTER_OUT_MAKE_TARGETS	+= writev02 writev03
+FILTER_OUT_MAKE_TARGETS	+= writev02
 endif
 
 include $(top_srcdir)/include/mk/testcases.mk
testcases/kernel/syscalls/writev/writev03.c deleted +0 -271

271 lines not on this page · raw message

testcases/kernel/syscalls/writev/writev04.c deleted +0 -353

353 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#2 lore raw

PATCH v2 3/3 writev01: rewrite and drop partially valid iovec tests

In reply to Jan Stancek

Convert to newlib style, and drop tests for partially valid iovec lists, these are now tested in writev07.

---
 testcases/kernel/syscalls/writev/writev01.c | 550 ++++++++--------------------
 1 file changed, 152 insertions(+), 398 deletions(-)

rewrite testcases/kernel/syscalls/writev/writev01.c (90%)

testcases/kernel/syscalls/writev/writev01.c +152 -398
dissimilarity index 90%
index 8e4f756fee3a..843736a21852 100644
@@ -1,398 +1,152 @@
-/*
- *
- *   Copyright (c) International Business Machines  Corp., 2001
- *
- *   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.
- *
- *   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
- */
-
-/*
- * NAME
- *	writev01.c
- *
- * DESCRIPTION
- *	Testcase to check the basic functionality of writev(2) system call.
- *
- * ALGORITHM
- *	Create a IO vector, and attempt to writev various components of it.
- *
- * USAGE:  <for command-line>
- *	writev01 [-c n] [-e] [-i n] [-I x] [-P x] [-t]
- *	where,	-c n : Run n copies concurrently.
- *		-e   : Turn on errno logging.
- *		-i n : Execute test n times.
- *		-I x : Execute test for x seconds.
- *		-P x : Pause for x seconds between iterations.
- *		-t   : Turn on syscall timing.
- *
- * History
- *	07/2001 John George
- *		-Ported
- *      04/2002 wjhuie sigset cleanups
- *     06/2002 Shaobo Li
- *             fix testcase 7, add each testcase comment.
- *
- * Restrictions
- *	None
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <signal.h>
-#include <sys/uio.h>
-#include <sys/fcntl.h>
-#include <memory.h>
-#include <errno.h>
-#include "test.h"
-#include <sys/mman.h>
-
-#define	K_1	1024
-#define	M_1	K_1 * K_1
-#define	G_1	M_1 * K_1
-
-#define	NBUFS		4
-#define	CHUNK		64	/* single chunk */
-#define	MAX_IOVEC	16
-#define	DATA_FILE	"writev_data_file"
-
-char buf1[K_1], buf2[K_1], buf3[K_1];
-
-struct iovec wr_iovec[MAX_IOVEC] = {
-	/* iov_base *//* iov_len */
-
-	/* testcase# 1 */
-	{buf1, -1},
-	{(buf1 + CHUNK), CHUNK},
-	{(buf1 + CHUNK * 2), CHUNK},
-
-	/* testcase# 2 */
-	{(buf1 + CHUNK * 3), G_1},
-	{(buf1 + CHUNK * 4), G_1},
-	{(buf1 + CHUNK * 5), G_1},
-
-	/* testcase# 3 */
-	{(buf1 + CHUNK * 6), CHUNK},
-	{(caddr_t) - 1, CHUNK},
-	{(buf1 + CHUNK * 8), CHUNK},
-
-	/* testcase# 4 */
-	{(buf1 + CHUNK * 9), CHUNK},
-
-	/* testcase# 5 */
-	{(buf1 + CHUNK * 10), CHUNK},
-
-	/* testcase# 6 */
-	{(buf1 + CHUNK * 11), CHUNK},
-
-	/* testcase# 7 */
-	{(buf1 + CHUNK * 12), CHUNK},
-
-	/* testcase# 8 */
-	{(buf1 + CHUNK * 13), 0},
-
-	/* testcase# 7 */
-	{NULL, 0},
-	{NULL, 0}
-};
-
-char name[K_1], f_name[K_1];
-
-char *bad_addr = 0;
-
-int fd[4], in_sighandler;
-int pfd[2];			/* pipe fd's */
-char *buf_list[NBUFS];
-
-void sighandler(int);
-int fill_mem(char *, int, int);
-void init_buffs(char *[]);
-void setup(void);
-void cleanup(void);
-
-char *TCID = "writev01";
-int TST_TOTAL = 1;
-
-int main(int argc, char **argv)
-{
-	int nbytes, ret;
-
-	int lc;
-
-	tst_parse_opts(argc, argv, NULL, NULL);
-
-	setup();
-
-	for (lc = 0; TEST_LOOPING(lc); lc++) {
-
-		tst_count = 0;
-
-		buf_list[0] = buf1;
-		buf_list[1] = buf2;
-		buf_list[2] = buf3;
-		buf_list[3] = NULL;
-
-		fd[1] = -1;	/* Invalid file descriptor  */
-
-		if (signal(SIGTERM, sighandler) == SIG_ERR)
-			tst_brkm(TBROK | TERRNO, cleanup,
-				 "signal(SIGTERM, ..) failed");
-
-		if (signal(SIGPIPE, sighandler) == SIG_ERR)
-			tst_brkm(TBROK | TERRNO, cleanup,
-				 "signal(SIGPIPE, ..) failed");
-
-		init_buffs(buf_list);
-
-		if ((fd[0] = open(f_name, O_WRONLY | O_CREAT, 0666)) == -1)
-			tst_brkm(TBROK | TERRNO, cleanup,
-				 "open(.., O_WRONLY|O_CREAT, ..) failed");
-		else if ((nbytes = write(fd[0], buf_list[2], K_1)) != K_1)
-			tst_brkm(TBROK | TERRNO, cleanup, "write failed");
-
-		if (close(fd[0]) == -1)
-			tst_brkm(TBROK | TERRNO, cleanup, "close failed");
-
-		if ((fd[0] = open(f_name, O_RDWR, 0666)) == -1)
-			tst_brkm(TBROK | TERRNO, cleanup, "open failed");
-//block1: /* given vector length -1, writev return EINVAL. */
-		tst_resm(TPASS, "Enter Block 1");
-
-		TEST(writev(fd[0], wr_iovec, 1));
-		if (TEST_RETURN == -1) {
-			if (TEST_ERRNO == EINVAL)
-				tst_resm(TPASS, "Received EINVAL as expected");
-			else
-				tst_resm(TFAIL, "Expected errno = EINVAL, "
-					 "got %d", TEST_ERRNO);
-		} else
-			tst_resm(TFAIL, "writev failed to fail");
-		tst_resm(TINFO, "Exit block 1");
-
-//block2:
-		/* This testcases doesn't look like what it intent to do
-		 * 1. it is not using the wr_iovec initialized
-		 * 2. read() and following message is not consistent
-		 */
-		tst_resm(TPASS, "Enter block 2");
-
-		if (lseek(fd[0], CHUNK * 6, 0) == -1)
-			tst_resm(TBROK | TERRNO, "block2: 1st lseek failed");
-
-		if ((ret = writev(fd[0], (wr_iovec + 6), 3)) == CHUNK) {
-			if (lseek(fd[0], CHUNK * 6, 0) == -1)
-				tst_brkm(TBROK | TERRNO, cleanup,
-					 "block2: 2nd lseek failed");
-			if ((nbytes = read(fd[0], buf_list[0], CHUNK)) != CHUNK)
-				tst_resm(TFAIL, "read failed; expected nbytes "
-					 "= 1024, got = %d", nbytes);
-			else if (memcmp((buf_list[0] + CHUNK * 6),
-					(buf_list[2] + CHUNK * 6), CHUNK) != 0)
-				tst_resm(TFAIL, "writev over "
-					 "wrote %s", f_name);
-		} else
-			tst_resm(TFAIL | TERRNO, "writev failed unexpectedly");
-		tst_resm(TINFO, "Exit block 2");
-
-//block3: /* given 1 bad vector buffer with good ones, writev success */
-		tst_resm(TPASS, "Enter block 3");
-
-		if (lseek(fd[0], CHUNK * 6, 0) == -1)
-			tst_brkm(TBROK | TERRNO, cleanup,
-				 "block3: 1st lseek failed");
-		if ((nbytes = writev(fd[0], (wr_iovec + 6), 3)) == -1) {
-			if (errno == EFAULT)
-				tst_resm(TFAIL, "Got EFAULT");
-		}
-		if (lseek(fd[0], 0, 0) == -1)
-			tst_brkm(TBROK, cleanup, "block3: 2nd lseek failed");
-		if ((nbytes = read(fd[0], buf_list[0], K_1)) != K_1) {
-			tst_resm(TFAIL | TERRNO,
-				 "read failed; expected nbytes = 1024, got = %d",
-				 nbytes);
-		} else if (memcmp((buf_list[0] + CHUNK * 6),
-				  (buf_list[2] + CHUNK * 6), CHUNK * 3) != 0)
-			tst_resm(TFAIL, "writev overwrote file");
-
-		tst_resm(TINFO, "Exit block 3");
-
-//block4: /* given bad file descriptor, writev return EBADF. */
-		tst_resm(TPASS, "Enter block 4");
-
-		TEST(writev(fd[1], (wr_iovec + 9), 1));
-		if (TEST_RETURN == -1) {
-			if (TEST_ERRNO == EBADF)
-				tst_resm(TPASS, "Received EBADF as expected");
-			else
-				tst_resm(TFAIL, "expected errno = EBADF, "
-					 "got %d", TEST_ERRNO);
-		} else
-			tst_resm(TFAIL, "writev returned a " "positive value");
-
-		tst_resm(TINFO, "Exit block 4");
-
-//block5: /* given invalid vector count, writev return EINVAL */
-		tst_resm(TPASS, "Enter block 5");
-
-		TEST(writev(fd[0], (wr_iovec + 10), -1));
-		if (TEST_RETURN == -1) {
-			if (TEST_ERRNO == EINVAL)
-				tst_resm(TPASS, "Received EINVAL as expected");
-			else
-				tst_resm(TFAIL, "expected errno = EINVAL, "
-					 "got %d", TEST_ERRNO);
-		} else
-			tst_resm(TFAIL, "writev returned a " "positive value");
-
-		tst_resm(TINFO, "Exit block 5");
-
-//block6: /* given no buffer vector, writev success */
-		tst_resm(TPASS, "Enter block 6");
-
-		TEST(writev(fd[0], (wr_iovec + 11), 0));
-		if (TEST_RETURN == -1)
-			tst_resm(TFAIL | TTERRNO, "writev failed");
-		else
-			tst_resm(TPASS, "writev wrote 0 iovectors");
-
-		tst_resm(TINFO, "Exit block 6");
-
-//block7:
-		/* given 4 vectors, 2 are NULL, 1 with 0 length and 1 with fixed length,
-		 * writev success writing fixed length.
-		 */
-		tst_resm(TPASS, "Enter block 7");
-
-		if (lseek(fd[0], CHUNK * 12, 0) == -1)
-			tst_resm(TBROK, "lseek failed");
-		else if ((ret = writev(fd[0], (wr_iovec + 12), 4)) != CHUNK)
-			tst_resm(TFAIL, "writev failed writing %d bytes, "
-				 "followed by two NULL vectors", CHUNK);
-		else
-			tst_resm(TPASS, "writev passed writing %d bytes, "
-				 "followed by two NULL vectors", CHUNK);
-
-		tst_resm(TINFO, "Exit block 7");
-
-//block8: /* try to write to a closed pipe, writev return EPIPE. */
-		tst_resm(TPASS, "Enter block 8");
-
-		if (pipe(pfd) == -1)
-			tst_resm(TFAIL | TERRNO, "pipe failed");
-		else {
-			if (close(pfd[0]) == -1)
-				tst_resm(TFAIL | TERRNO, "close failed");
-			else if (writev(pfd[1], (wr_iovec + 12), 1) == -1 &&
-				 in_sighandler) {
-				if (errno == EPIPE)
-					tst_resm(TPASS, "Received EPIPE as "
-						 "expected");
-				else
-					tst_resm(TFAIL | TERRNO,
-						 "didn't get EPIPE");
-			} else
-				tst_resm(TFAIL, "writev returned a positive "
-					 "value");
-		}
-		tst_resm(TINFO, "Exit block 8");
-	}
-	cleanup();
-	tst_exit();
-}
-
-void setup(void)
-{
-
-	tst_sig(FORK, sighandler, cleanup);
-
-	TEST_PAUSE;
-
-	tst_tmpdir();
-
-	strcpy(name, DATA_FILE);
-	sprintf(f_name, "%s.%d", name, getpid());
-
-	bad_addr = mmap(0, 1, PROT_NONE,
-			MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
-	if (bad_addr == MAP_FAILED)
-		tst_brkm(TBROK | TERRNO, cleanup, "mmap failed");
-	wr_iovec[7].iov_base = bad_addr;
-
-}
-
-void cleanup(void)
-{
-	if (munmap(bad_addr, 1) == -1)
-		tst_resm(TBROK | TERRNO, "munmap failed");
-
-	close(fd[0]);
-	close(fd[1]);
-
-	if (unlink(f_name) == -1)
-		tst_resm(TBROK | TERRNO, "unlink failed");
-
-	tst_rmdir();
-
-}
-
-void init_buffs(char *pbufs[])
-{
-	int i;
-
-	for (i = 0; pbufs[i] != NULL; i++) {
-		switch (i) {
-		case 0:
-
-		case 1:
-			fill_mem(pbufs[i], 0, 1);
-			break;
-
-		case 2:
-			fill_mem(pbufs[i], 1, 0);
-			break;
-
-		default:
-			tst_brkm(TBROK, cleanup, "error detected: init_buffs");
-		}
-	}
-}
-
-int fill_mem(char *c_ptr, int c1, int c2)
-{
-	int count;
-
-	for (count = 1; count <= K_1 / CHUNK; count++) {
-		if (count & 0x01) {	/* if odd */
-			memset(c_ptr, c1, CHUNK);
-		} else {	/* if even */
-			memset(c_ptr, c2, CHUNK);
-		}
-	}
-	return 0;
-}
-
-void sighandler(int sig)
-{
-	switch (sig) {
-	case SIGTERM:
-		break;
-
-	case SIGPIPE:
-		in_sighandler++;
-		return;
-
-	default:
-		tst_resm(TFAIL, "sighandler received invalid signal:%d", sig);
-		break;
-	}
-}
+/*
+ *   Copyright (c) International Business Machines  Corp., 2001
+ *                 Linux Test Project, 2016
+ *
+ *   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.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;
+ */
+
+/*
+ * DESCRIPTION
+ *	Testcase to check the basic functionality of writev(2) system call.
+ *	Create IO vectors and attempt to writev various components of it.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/uio.h>
+#include "tst_test.h"
+
+#define	CHUNK		64
+#define	TESTFILE	"writev_data_file"
+
+static int valid_fd;
+static int invalid_fd = -1;
+static int pipe_fd[2];
+
+static char buf[CHUNK * 4];
+
+struct iovec iovec_badlen[] = {
+	{ buf, -1 },
+	{ buf + CHUNK, CHUNK },
+	{ buf + CHUNK * 2, CHUNK },
+};
+
+struct iovec iovec_simple[] = {
+	{ buf, CHUNK },
+};
+
+struct iovec iovec_zero_null[] = {
+	{ buf, CHUNK },
+	{ buf + CHUNK, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 }
+};
+
+struct testcase_t {
+	const char *desc;
+	int *pfd;
+	struct iovec (*piovec)[];
+	int iovcnt;
+	int exp_ret;
+	int exp_errno;
+} testcases[] = {
+	{
+		.desc = "invalid iov_len",
+		.pfd = &valid_fd,
+		.piovec = &iovec_badlen,
+		.iovcnt = ARRAY_SIZE(iovec_badlen),
+		.exp_ret = -1,
+		.exp_errno = EINVAL
+	},
+	{
+		.desc = "invalid fd",
+		.pfd = &invalid_fd,
+		.piovec = &iovec_simple,
+		.iovcnt = ARRAY_SIZE(iovec_simple),
+		.exp_ret = -1,
+		.exp_errno = EBADF
+	},
+	{
+		.desc = "invalid iovcnt",
+		.pfd = &valid_fd,
+		.piovec = &iovec_simple,
+		.iovcnt = -1,
+		.exp_ret = -1,
+		.exp_errno = EINVAL
+	},
+	{
+		.desc = "zero iovcnt",
+		.pfd = &valid_fd,
+		.piovec = &iovec_simple,
+		.iovcnt = 0,
+		.exp_ret = 0,
+	},
+	{
+		.desc = "NULL and zero length iovec",
+		.pfd = &valid_fd,
+		.piovec = &iovec_zero_null,
+		.iovcnt = ARRAY_SIZE(iovec_zero_null),
+		.exp_ret = CHUNK,
+	},
+	{
+		.desc = "write to closed pipe",
+		.pfd = &(pipe_fd[1]),
+		.piovec = &iovec_simple,
+		.iovcnt = ARRAY_SIZE(iovec_simple),
+		.exp_ret = -1,
+		.exp_errno = EPIPE,
+	},
+};
+
+void setup(void)
+{
+	sigset_t block_mask;
+
+	sigemptyset(&block_mask);
+	sigaddset(&block_mask, SIGPIPE);
+	sigprocmask(SIG_BLOCK, &block_mask, NULL);
+
+	valid_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, 0644);
+
+	SAFE_PIPE(pipe_fd);
+	SAFE_CLOSE(pipe_fd[0]);
+}
+
+static void test_writev(unsigned int i)
+{
+	struct testcase_t *tcase = &testcases[i];
+	int ret;
+
+	TEST(writev(*(tcase->pfd), *(tcase->piovec), tcase->iovcnt));
+
+	ret = (TEST_RETURN == tcase->exp_ret);
+	if (TEST_RETURN < 0 || tcase->exp_ret < 0)
+		ret &= (TEST_ERRNO == tcase->exp_errno);
+
+	if (ret) {
+		tst_res(TPASS | TTERRNO, "%s, ret: %ld", tcase->desc,
+			TEST_RETURN);
+	} else {
+		tst_res(TPASS | TTERRNO, "%s, ret: %ld", tcase->desc,
+			TEST_RETURN);
+	}
+}
+
+static struct tst_test test = {
+	.tid = "writev01",
+	.needs_tmpdir = 1,
+	.setup = setup,
+	.test = test_writev,
+	.tcnt = ARRAY_SIZE(testcases),
+};
Signature · 1 line
1.8.3.1
#3 lore raw

PATCH v2 3/3 writev01: rewrite and drop partially valid iovec tests

Hi!

Quoted 131 lines
testcases/kernel/syscalls/writev/writev01.c +131 -0
+/*
+ *   Copyright (c) International Business Machines  Corp., 2001
+ *                 Linux Test Project, 2016
+ *
+ *   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.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program;
+ */
+
+/*
+ * DESCRIPTION
+ *	Testcase to check the basic functionality of writev(2) system call.
+ *	Create IO vectors and attempt to writev various components of it.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/uio.h>
+#include "tst_test.h"
+
+#define	CHUNK		64
+#define	TESTFILE	"writev_data_file"
+
+static int valid_fd;
+static int invalid_fd = -1;
+static int pipe_fd[2];
+
+static char buf[CHUNK * 4];
+
+struct iovec iovec_badlen[] = {
+	{ buf, -1 },
+	{ buf + CHUNK, CHUNK },
+	{ buf + CHUNK * 2, CHUNK },
+};
+
+struct iovec iovec_simple[] = {
+	{ buf, CHUNK },
+};
+
+struct iovec iovec_zero_null[] = {
+	{ buf, CHUNK },
+	{ buf + CHUNK, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 }
+};
+
+struct testcase_t {
+	const char *desc;
+	int *pfd;
+	struct iovec (*piovec)[];
+	int iovcnt;
+	int exp_ret;
+	int exp_errno;
+} testcases[] = {
+	{
+		.desc = "invalid iov_len",
+		.pfd = &valid_fd,
+		.piovec = &iovec_badlen,
+		.iovcnt = ARRAY_SIZE(iovec_badlen),
+		.exp_ret = -1,
+		.exp_errno = EINVAL
+	},
+	{
+		.desc = "invalid fd",
+		.pfd = &invalid_fd,
+		.piovec = &iovec_simple,
+		.iovcnt = ARRAY_SIZE(iovec_simple),
+		.exp_ret = -1,
+		.exp_errno = EBADF
+	},
+	{
+		.desc = "invalid iovcnt",
+		.pfd = &valid_fd,
+		.piovec = &iovec_simple,
+		.iovcnt = -1,
+		.exp_ret = -1,
+		.exp_errno = EINVAL
+	},
+	{
+		.desc = "zero iovcnt",
+		.pfd = &valid_fd,
+		.piovec = &iovec_simple,
+		.iovcnt = 0,
+		.exp_ret = 0,
+	},
+	{
+		.desc = "NULL and zero length iovec",
+		.pfd = &valid_fd,
+		.piovec = &iovec_zero_null,
+		.iovcnt = ARRAY_SIZE(iovec_zero_null),
+		.exp_ret = CHUNK,
+	},
+	{
+		.desc = "write to closed pipe",
+		.pfd = &(pipe_fd[1]),
+		.piovec = &iovec_simple,
+		.iovcnt = ARRAY_SIZE(iovec_simple),
+		.exp_ret = -1,
+		.exp_errno = EPIPE,
+	},
+};
+
+void setup(void)
+{
+	sigset_t block_mask;
+
+	sigemptyset(&block_mask);
+	sigaddset(&block_mask, SIGPIPE);
+	sigprocmask(SIG_BLOCK, &block_mask, NULL);
+
+	valid_fd = SAFE_OPEN(TESTFILE, O_RDWR | O_CREAT, 0644);
+
+	SAFE_PIPE(pipe_fd);
+	SAFE_CLOSE(pipe_fd[0]);
+}
+
+static void test_writev(unsigned int i)
+{
+	struct testcase_t *tcase = &testcases[i];
+	int ret;
+
+	TEST(writev(*(tcase->pfd), *(tcase->piovec), tcase->iovcnt));

testcases/kernel/syscalls/writev/writev01.c line 141

Quoted 10 lines
testcases/kernel/syscalls/writev/writev01.c +10 -0
+
+	ret = (TEST_RETURN == tcase->exp_ret);
+	if (TEST_RETURN < 0 || tcase->exp_ret < 0)
+		ret &= (TEST_ERRNO == tcase->exp_errno);
+
+	if (ret) {
+		tst_res(TPASS | TTERRNO, "%s, ret: %ld", tcase->desc,
+			TEST_RETURN);
+	} else {
+		tst_res(TPASS | TTERRNO, "%s, ret: %ld", tcase->desc,
                         ^
			 TFAIL?

Review

Quoted 2 lines
(quoted diff) +2 -0
+			TEST_RETURN);
+	}

Also I would have created separate functions for failure/success tests so that we can print more informative results, i.e. include the expected errno in the TFAIL result message.

Apart from that this is much better than the original.

Signature · 2 lines
Cyril Hrubis
[email protected]
#4 lore raw

PATCH v2 3/3 writev01: rewrite and drop partially valid iovec tests

Quoted 20 lines · Cyril Hrubis
Quoted 7 lines
testcases/kernel/syscalls/writev/writev01.c +7 -0
+
+static void test_writev(unsigned int i)
+{
+	struct testcase_t *tcase = &testcases[i];
+	int ret;
+
+	TEST(writev(*(tcase->pfd), *(tcase->piovec), tcase->iovcnt));

testcases/kernel/syscalls/writev/writev01.c line 141

Quoted 10 lines
testcases/kernel/syscalls/writev/writev01.c +10 -0
+
+	ret = (TEST_RETURN == tcase->exp_ret);
+	if (TEST_RETURN < 0 || tcase->exp_ret < 0)
+		ret &= (TEST_ERRNO == tcase->exp_errno);
+
+	if (ret) {
+		tst_res(TPASS | TTERRNO, "%s, ret: %ld", tcase->desc,
+			TEST_RETURN);
+	} else {
+		tst_res(TPASS | TTERRNO, "%s, ret: %ld", tcase->desc,
                         ^
			 TFAIL?
Quoted 9 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+			TEST_RETURN);
+	}

Also I would have created separate functions for failure/success tests so that we can print more informative results, i.e. include the expected errno in the TFAIL result message.

Apart from that this is much better than the original.

How about:

static void test_writev(unsigned int i)

{
        struct testcase_t *tcase = &testcases[i];
        int ret;

        TEST(writev(*(tcase->pfd), *(tcase->piovec), tcase->iovcnt));

        ret = (TEST_RETURN == tcase->exp_ret);
        if (TEST_RETURN < 0 || tcase->exp_ret < 0) {
                ret &= (TEST_ERRNO == tcase->exp_errno);
                tst_res((ret ? TPASS : TFAIL),
                        "%s, expected: %d (%s), got: %ld (%s)", tcase->desc,
                        tcase->exp_ret, tst_strerrno(tcase->exp_errno),
                        TEST_RETURN, tst_strerrno(TEST_ERRNO));
        } else {
                tst_res((ret ? TPASS : TFAIL),
                        "%s, expected: %d, got: %ld", tcase->desc,
                        tcase->exp_ret, TEST_RETURN);
        }
}
$ ./writev01
tst_test.c:756: INFO: Timeout per run is 0h 05m 00s
writev01.c:139: PASS: invalid iov_len, expected: -1 (EINVAL), got: -1 (EINVAL)
writev01.c:139: PASS: invalid fd, expected: -1 (EBADF), got: -1 (EBADF)
writev01.c:139: PASS: invalid iovcnt, expected: -1 (EINVAL), got: -1 (EINVAL)
writev01.c:143: PASS: zero iovcnt, expected: 0, got: 0
writev01.c:143: PASS: NULL and zero length iovec, expected: 64, got: 64
writev01.c:139: PASS: write to closed pipe, expected: -1 (EPIPE), got: -1 (EPIPE)

Regards,
Jan

#5 lore raw

PATCH v2 3/3 writev01: rewrite and drop partially valid iovec tests

Hi!

Quoted 14 lines

How about:

static void test_writev(unsigned int i)

{
        struct testcase_t *tcase = &testcases[i];
        int ret;

        TEST(writev(*(tcase->pfd), *(tcase->piovec), tcase->iovcnt));

        ret = (TEST_RETURN == tcase->exp_ret);
        if (TEST_RETURN < 0 || tcase->exp_ret < 0) {
                ret &= (TEST_ERRNO == tcase->exp_errno);
                tst_res((ret ? TPASS : TFAIL),
                        "%s, expected: %d (%s), got: %ld (%s)", tcase->desc,
Quoted 8 lines
                        tcase->exp_ret, tst_strerrno(tcase->exp_errno),
                        TEST_RETURN, tst_strerrno(TEST_ERRNO));
        } else {
                tst_res((ret ? TPASS : TFAIL),
                        "%s, expected: %d, got: %ld", tcase->desc,
                        tcase->exp_ret, TEST_RETURN);
        }
}

Looks good.

Signature · 2 lines
Cyril Hrubis
[email protected]
#6 lore raw

PATCH v2 3/3 writev01: rewrite and drop partially valid iovec tests

Quoted 6 lines

Looks good.

--
Cyril Hrubis
[email protected]

Thanks for review, I pushed the series with suggested changes and your ACK.

Regards,
Jan

#7 lore raw

PATCH v2 1/3 syscalls: new test writev07

In reply to Jan Stancek

Hi!

testcases/kernel/syscalls/writev/writev07.c line 117

Quoted 8 lines
testcases/kernel/syscalls/writev/writev07.c new file +8 -0
+	/* file content matches written bytes */
+	SAFE_LSEEK(fd, initial_file_offset, SEEK_SET);
+	SAFE_READ(1, fd, tmp, TEST_RETURN);
+	if (memcmp(tmp, wr_iovec[0].iov_base, TEST_RETURN) == 0) {
+		tst_res(TPASS, "file has expected content");
+	} else {
+		tst_res(TFAIL, "file has unexpected content");
+		tst_res(TINFO, "expected:");

^
This TINFO looks redundant now.

Otherwise it looks good, acked.

Signature · 2 lines
Cyril Hrubis
[email protected]
#8 lore raw

PATCH v2 1/3 syscalls: new test writev07

In reply to Jan Stancek

testcases/kernel/syscalls/writev/writev07.c line 104

Quoted 9 lines · Jan Stancek
testcases/kernel/syscalls/writev/writev07.c new file +9 -0
+				off_after);
+
+		SAFE_CLOSE(fd);
+		return;
+	}
+
+	/* writev() wrote more bytes than bytes preceding invalid iovec */
+	tst_res(TINFO, "writev() has written %ld bytes", TEST_RETURN);
+	if (TEST_RETURN > (long) wr_iovec[0].iov_base) {

Hi, why TEST_RETURN(the return of writev) compare with wr_iovec[0].iov_base(the address) here?

I run it in armv7 (with printf("TEST_RETURN:%ld, wr_iovec[0].iov_base:%ld\n", TEST_RETURN, (long) wr_iovec[0].iov_base) for debug):

# ./writev07
tst_test.c:760: INFO: Timeout per run is 0h 05m 00s
writev07.c:60: INFO: starting test with initial file offset: 0
writev07.c:104: INFO: writev() has written 64 bytes
writev07.c:106: FAIL: writev wrote more than expected
TEST_RETURN:64, wr_iovec[0].iov_base:-1092708152
writev07.c:60: INFO: starting test with initial file offset: 65
writev07.c:104: INFO: writev() has written 64 bytes
writev07.c:106: FAIL: writev wrote more than expected
TEST_RETURN:64, wr_iovec[0].iov_base:-1092708152
writev07.c:60: INFO: starting test with initial file offset: 4096
writev07.c:104: INFO: writev() has written 64 bytes
writev07.c:106: FAIL: writev wrote more than expected
TEST_RETURN:64, wr_iovec[0].iov_base:-1092708152
writev07.c:60: INFO: starting test with initial file offset: 4097
writev07.c:104: INFO: writev() has written 64 bytes
writev07.c:106: FAIL: writev wrote more than expected
TEST_RETURN:64, wr_iovec[0].iov_base:-1092708144

So the case fail at all time.

Thanks,
Cui Bixuan

Quoted 8 lines
testcases/kernel/syscalls/writev/writev07.c new file +8 -0
+		tst_res(TFAIL, "writev wrote more than expected");
+		SAFE_CLOSE(fd);
+		return;
+	}
+
+	/* file content matches written bytes */
+	SAFE_LSEEK(fd, initial_file_offset, SEEK_SET);
+	SAFE_READ(1, fd, tmp, TEST_RETURN);
#9 lore raw

PATCH v2 1/3 syscalls: new test writev07

----- Original Message -----

Quoted 6 lines

From: "Cui Bixuan" <[email protected]>
To: [email protected]
Sent: Thursday, 1 December, 2016 7:36:58 AM
Subject: Re: [LTP] [PATCH v2 1/3] syscalls: new test writev07

On 2016/10/7 16:11, Jan Stancek wrote:

Quoted 11 lines

testcases/kernel/syscalls/writev/writev07.c line 104

Quoted 9 lines
testcases/kernel/syscalls/writev/writev07.c new file +9 -0
+				off_after);
+
+		SAFE_CLOSE(fd);
+		return;
+	}
+
+	/* writev() wrote more bytes than bytes preceding invalid iovec */
+	tst_res(TINFO, "writev() has written %ld bytes", TEST_RETURN);
+	if (TEST_RETURN > (long) wr_iovec[0].iov_base) {

Hi, why TEST_RETURN(the return of writev) compare with wr_iovec[0].iov_base(the address) here?

Mistake on my part. That was obviously supposed to compare iovec length. I pushed a fix to change that.

Thanks,
Jan

Quoted 41 lines

I run it in armv7 (with printf("TEST_RETURN:%ld, wr_iovec[0].iov_base:%ld\n", TEST_RETURN, (long) wr_iovec[0].iov_base) for debug):

# ./writev07
tst_test.c:760: INFO: Timeout per run is 0h 05m 00s
writev07.c:60: INFO: starting test with initial file offset: 0
writev07.c:104: INFO: writev() has written 64 bytes
writev07.c:106: FAIL: writev wrote more than expected
TEST_RETURN:64, wr_iovec[0].iov_base:-1092708152
writev07.c:60: INFO: starting test with initial file offset: 65
writev07.c:104: INFO: writev() has written 64 bytes
writev07.c:106: FAIL: writev wrote more than expected
TEST_RETURN:64, wr_iovec[0].iov_base:-1092708152
writev07.c:60: INFO: starting test with initial file offset: 4096
writev07.c:104: INFO: writev() has written 64 bytes
writev07.c:106: FAIL: writev wrote more than expected
TEST_RETURN:64, wr_iovec[0].iov_base:-1092708152
writev07.c:60: INFO: starting test with initial file offset: 4097
writev07.c:104: INFO: writev() has written 64 bytes
writev07.c:106: FAIL: writev wrote more than expected
TEST_RETURN:64, wr_iovec[0].iov_base:-1092708144

So the case fail at all time.

Thanks,
Cui Bixuan

testcases/kernel/syscalls/writev/writev07.c line 112

Quoted 8 lines
testcases/kernel/syscalls/writev/writev07.c new file +8 -0
+		tst_res(TFAIL, "writev wrote more than expected");
+		SAFE_CLOSE(fd);
+		return;
+	}
+
+	/* file content matches written bytes */
+	SAFE_LSEEK(fd, initial_file_offset, SEEK_SET);
+	SAFE_READ(1, fd, tmp, TEST_RETURN);

--
Mailing list info: https://lists.linux.it/listinfo/ltp