[LTP] [PATCH] aio_suspend_4-1: Fix failures on s390x

Cyril Hrubis chrubis@suse.cz
Thu Feb 2 14:22:26 CET 2017


The testcase often fails on s390x due to fast I/O. The AIO request we
wanted to timeout on finishes too fast most of the time.

While this is not a complete fix it's good enough so that the test works
fine if executed 1000 times, previously the success ratio was between
20% and 80%.

This patch changes:

* The file is written instead of read
  - this simplifies the code and also ensures that we are not just
    reading data from kernel caches

* The file is opened with O_SYNC
  - which increases chance that the buffers are not written too fast

* The timeout is decreased

* The buffer sizes are increased, especially for the AIO operation we
  want to timeout on

+ Simplifications in error paths

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---

Jan: Have you seen this test failing on s390x as well?
     Can you please test the patch on RHEL on s390x?

 .../conformance/interfaces/aio_suspend/4-1.c       | 158 +++++++++------------
 1 file changed, 65 insertions(+), 93 deletions(-)

diff --git a/testcases/open_posix_testsuite/conformance/interfaces/aio_suspend/4-1.c b/testcases/open_posix_testsuite/conformance/interfaces/aio_suspend/4-1.c
index 7cf377d..f859aa4 100644
--- a/testcases/open_posix_testsuite/conformance/interfaces/aio_suspend/4-1.c
+++ b/testcases/open_posix_testsuite/conformance/interfaces/aio_suspend/4-1.c
@@ -13,8 +13,7 @@
  *
  * method: Testing for a non NULL timeout
  *
- *	- write to a file
- *	- submit a list of read requests
+ *	- submit a list of write requests
  *	- check that the selected request has not completed
  *	- suspend on selected request
  *	- check that the suspend timed out
@@ -38,37 +37,38 @@
 #define TNAME "aio_suspend/4-1.c"
 
 #define NUM_AIOCBS	10
-#define BUF_SIZE	(1024*1024)
+#define BUF_SIZE	(2 * 1024 * 1024)
 #define WAIT_FOR_AIOCB	6
+#define WAIT_FOR_AIOCB_BUF_SIZE (20 * 1024 * 1024)
 
-static int received_selected;
-static int received_all;
+static volatile int received_selected;
+static volatile int received_all;
 
-static void sigrt1_handler(int signum, siginfo_t *info, void *context)
+static void sigrt1_handler(int signum)
 {
+	(void)signum;
+
 	received_selected = 1;
 }
 
-static void sigrt2_handler(int signum, siginfo_t *info, void *context)
+static void sigrt2_handler(int signum)
 {
+	(void)signum;
+
 	received_all = 1;
 }
 
 int main(void)
 {
 	char tmpfname[256];
-	int fd;
-
-	struct aiocb **aiocbs;
+	struct aiocb aiocbs[NUM_AIOCBS];
+	struct aiocb *aiolist[NUM_AIOCBS];
 	struct aiocb *plist[2];
-	char *bufs;
 	struct sigaction action;
 	struct sigevent event;
-	struct timespec ts = { 0, 1000 };	/* 1 us */
+	struct timespec ts = {0, 10};
 	int errors = 0;
-	int ret;
-	int err;
-	int i;
+	int ret, err, i, rval, fd;
 
 	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
 		return PTS_UNSUPPORTED;
@@ -77,7 +77,7 @@ int main(void)
 		 getpid());
 	unlink(tmpfname);
 
-	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
+	fd = open(tmpfname, O_SYNC | O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
 
 	if (fd == -1) {
 		printf(TNAME " Error at open(): %s\n", strerror(errno));
@@ -86,41 +86,35 @@ int main(void)
 
 	unlink(tmpfname);
 
-	bufs = malloc(NUM_AIOCBS * BUF_SIZE);
-
-	if (bufs == NULL) {
-		printf(TNAME " Error at malloc(): %s\n", strerror(errno));
-		close(fd);
-		exit(PTS_UNRESOLVED);
-	}
-
-	if (write(fd, bufs, NUM_AIOCBS * BUF_SIZE) != (NUM_AIOCBS * BUF_SIZE)) {
-		printf(TNAME " Error at write(): %s\n", strerror(errno));
-		free(bufs);
-		close(fd);
-		exit(PTS_UNRESOLVED);
-	}
-
-	aiocbs = malloc(sizeof(struct aiocb *) * NUM_AIOCBS);
+	memset(aiocbs, 0, sizeof(aiocbs));
+	size_t buf_offset = 0;
 
 	/* Queue up a bunch of aio reads */
 	for (i = 0; i < NUM_AIOCBS; i++) {
-
-		aiocbs[i] = malloc(sizeof(struct aiocb));
-		memset(aiocbs[i], 0, sizeof(struct aiocb));
-
-		aiocbs[i]->aio_fildes = fd;
-		aiocbs[i]->aio_offset = i * BUF_SIZE;
-		aiocbs[i]->aio_buf = &bufs[i * BUF_SIZE];
-		aiocbs[i]->aio_nbytes = BUF_SIZE;
-		aiocbs[i]->aio_lio_opcode = LIO_READ;
+		size_t buf_size = (i == WAIT_FOR_AIOCB) ?
+		                   WAIT_FOR_AIOCB_BUF_SIZE : BUF_SIZE;
+
+		aiocbs[i].aio_fildes = fd;
+		aiocbs[i].aio_offset = buf_offset;
+		aiocbs[i].aio_buf = malloc(buf_size);
+		aiocbs[i].aio_nbytes = buf_size;
+		aiocbs[i].aio_lio_opcode = LIO_WRITE;
+
+		if (!aiocbs[i].aio_buf) {
+			perror("malloc()");
+			rval = PTS_UNRESOLVED;
+			goto exit;
+		}
 
 		/* Use SIGRTMIN+1 for individual completions */
 		if (i == WAIT_FOR_AIOCB) {
-			aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
-			aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN + 1;
-			aiocbs[i]->aio_sigevent.sigev_value.sival_int = i;
+			aiocbs[i].aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+			aiocbs[i].aio_sigevent.sigev_signo = SIGRTMIN + 1;
+			aiocbs[i].aio_sigevent.sigev_value.sival_int = i;
 		}
+
+		buf_offset += buf_size;
+		aiolist[i] = &aiocbs[i];
 	}
 
 	/* Use SIGRTMIN+2 for list completion */
@@ -129,45 +123,37 @@ int main(void)
 	event.sigev_value.sival_ptr = NULL;
 
 	/* Setup handler for individual operation completion */
-	action.sa_sigaction = sigrt1_handler;
+	action.sa_handler = sigrt1_handler;
 	sigemptyset(&action.sa_mask);
 	action.sa_flags = SA_SIGINFO | SA_RESTART;
 	sigaction(SIGRTMIN + 1, &action, NULL);
 
 	/* Setup handler for list completion */
-	action.sa_sigaction = sigrt2_handler;
+	action.sa_handler = sigrt2_handler;
 	sigemptyset(&action.sa_mask);
 	action.sa_flags = SA_SIGINFO | SA_RESTART;
 	sigaction(SIGRTMIN + 2, &action, NULL);
 
 	/* Setup suspend list */
 	plist[0] = NULL;
-	plist[1] = aiocbs[WAIT_FOR_AIOCB];
+	plist[1] = &aiocbs[WAIT_FOR_AIOCB];
 
 	/* Submit request list */
-	ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);
+	ret = lio_listio(LIO_NOWAIT, aiolist, NUM_AIOCBS, &event);
 
 	if (ret) {
 		printf(TNAME " Error at lio_listio() %d: %s\n",
 		       errno, strerror(errno));
-		for (i = 0; i < NUM_AIOCBS; i++)
-			free(aiocbs[i]);
-		free(bufs);
-		free(aiocbs);
-		close(fd);
-		exit(PTS_UNRESOLVED);
+		rval = PTS_UNRESOLVED;
+		goto exit;
 	}
 
 	/* Check selected request has not completed yet */
 	if (received_selected) {
 		printf(TNAME " Error : AIOCB %d already completed"
 		       " before suspend\n", WAIT_FOR_AIOCB);
-		for (i = 0; i < NUM_AIOCBS; i++)
-			free(aiocbs[i]);
-		free(bufs);
-		free(aiocbs);
-		close(fd);
-		exit(PTS_FAIL);
+		rval = PTS_FAIL;
+		goto exit;
 	}
 
 	/* Suspend on selected request */
@@ -177,63 +163,49 @@ int main(void)
 	if (received_selected) {
 		printf(TNAME " Error : AIOCB %d should not have completed"
 		       " after timed out suspend\n", WAIT_FOR_AIOCB);
-		for (i = 0; i < NUM_AIOCBS; i++)
-			free(aiocbs[i]);
-		free(bufs);
-		free(aiocbs);
-		close(fd);
-		exit(PTS_FAIL);
+		rval = PTS_FAIL;
+		goto exit;
 	}
 
 	/* timed out aio_suspend should return -1 and set errno to EAGAIN */
 	if (ret != -1) {
 		printf(TNAME " aio_suspend() should return -1\n");
-		for (i = 0; i < NUM_AIOCBS; i++)
-			free(aiocbs[i]);
-		free(bufs);
-		free(aiocbs);
-		close(fd);
-		exit(PTS_FAIL);
+		rval = PTS_FAIL;
+		goto exit;
 	}
 
 	if (errno != EAGAIN) {
 		printf(TNAME " aio_suspend() should set errno to EAGAIN:"
 		       " %d (%s)\n", errno, strerror(errno));
-		for (i = 0; i < NUM_AIOCBS; i++)
-			free(aiocbs[i]);
-		free(bufs);
-		free(aiocbs);
-		close(fd);
-		exit(PTS_FAIL);
+		rval = PTS_FAIL;
+		goto exit;
 	}
 
 	/* Wait for list processing completion */
 	while (!received_all)
-		sleep(1);
+		usleep(50000);
 
-	/* Check return code and free things */
 	for (i = 0; i < NUM_AIOCBS; i++) {
-		err = aio_error(aiocbs[i]);
-		ret = aio_return(aiocbs[i]);
+		err = aio_error(&aiocbs[i]);
+		ret = aio_return(&aiocbs[i]);
 
 		if ((err != 0) && (ret != BUF_SIZE)) {
 			printf(TNAME " req %d: error = %d - return = %d\n",
 			       i, err, ret);
 			errors++;
 		}
-
-		free(aiocbs[i]);
 	}
 
-	free(bufs);
-	free(aiocbs);
+	if (errors == 0) {
+		printf(TNAME " PASSED\n");
+		rval = PTS_PASS;
+	} else {
+		rval = PTS_FAIL;
+	}
 
+exit:
+	for (i = 0; i < NUM_AIOCBS; i++)
+		free((void*)aiocbs[i].aio_buf);
 	close(fd);
-
-	if (errors != 0)
-		exit(PTS_FAIL);
-
-	printf(TNAME " PASSED\n");
-
-	return PTS_PASS;
+	return rval;
 }
-- 
2.10.2



More information about the ltp mailing list