14-1.c revision d218f348c12b42a78fa0306d9a033bfa4f67238b
1/*
2 * Copyright (c) 2004, Bull SA. All rights reserved.
3 * Created by:  Laurent.Vivier@bull.net
4 * This file is licensed under the GPL license.  For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7 */
8
9/*
10 * assertion:
11 *
12 *	Failure of an individual request does not prevend completion of any
13 *	other individual request.
14 *
15 * method:
16 *
17 *	- open a file for writing
18 *	- submit a list with an invalid aiocb to lio_listio in LIO_NOWAIT mode
19 *	- check that the good requests do not fail
20 *
21 */
22
23#define _XOPEN_SOURCE 600
24#include <sys/stat.h>
25#include <aio.h>
26#include <errno.h>
27#include <fcntl.h>
28#include <signal.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33#include "posixtest.h"
34
35#define TNAME "lio_listio/14-1.c"
36
37#define NUM_AIOCBS	10
38#define BUF_SIZE	1024
39
40int num_received = 0;
41int received_all = 0;
42
43void sigrt1_handler(int signum, siginfo_t * info, void *context)
44{
45	num_received++;
46}
47
48void sigrt2_handler(int signum, siginfo_t * info, void *context)
49{
50	received_all = 1;
51}
52
53int main(void)
54{
55	char tmpfname[256];
56	int fd;
57
58	struct aiocb *aiocbs[NUM_AIOCBS];
59	char *bufs;
60	struct sigaction action;
61	struct sigevent event;
62	int errors = 0;
63	int ret;
64	int err;
65	int i;
66
67	if (sysconf(_SC_ASYNCHRONOUS_IO) < 200112L)
68		exit(PTS_UNSUPPORTED);
69
70	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_lio_listio_14_1_%d",
71		 getpid());
72	unlink(tmpfname);
73
74	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
75
76	if (fd == -1) {
77		printf(TNAME " Error at open(): %s\n", strerror(errno));
78		exit(PTS_UNRESOLVED);
79	}
80
81	unlink(tmpfname);
82
83	bufs = malloc(NUM_AIOCBS * BUF_SIZE);
84
85	if (bufs == NULL) {
86		printf(TNAME " Error at malloc(): %s\n", strerror(errno));
87		close(fd);
88		exit(PTS_UNRESOLVED);
89	}
90
91	/* Queue up a bunch of aio writes */
92	for (i = 0; i < NUM_AIOCBS; i++) {
93
94		aiocbs[i] = (struct aiocb *)calloc(sizeof(struct aiocb), 1);
95		if (aiocbs == NULL) {
96			printf(TNAME " Error at malloc(): %s\n",
97			       strerror(errno));
98			free(bufs);
99			close(fd);
100			exit(PTS_UNRESOLVED);
101		}
102
103		if (i == 2)
104			aiocbs[i]->aio_fildes = -1;
105		else
106			aiocbs[i]->aio_fildes = fd;
107
108		aiocbs[i]->aio_offset = 0;
109		aiocbs[i]->aio_buf = &bufs[i * BUF_SIZE];
110		aiocbs[i]->aio_nbytes = BUF_SIZE;
111		aiocbs[i]->aio_lio_opcode = LIO_WRITE;
112
113		/* Use SIRTMIN+1 for individual completions */
114		aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
115		aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN + 1;
116		aiocbs[i]->aio_sigevent.sigev_value.sival_int = i;
117	}
118
119	/* Use SIGRTMIN+2 for list completion */
120	event.sigev_notify = SIGEV_SIGNAL;
121	event.sigev_signo = SIGRTMIN + 2;
122	event.sigev_value.sival_ptr = NULL;
123
124	/* Setup handler for individual operation completion */
125	action.sa_sigaction = sigrt1_handler;
126	sigemptyset(&action.sa_mask);
127	action.sa_flags = SA_SIGINFO | SA_RESTART;
128	sigaction(SIGRTMIN + 1, &action, NULL);
129
130	/* Setup handler for list completion */
131	action.sa_sigaction = sigrt2_handler;
132	sigemptyset(&action.sa_mask);
133	action.sa_flags = SA_SIGINFO | SA_RESTART;
134	sigaction(SIGRTMIN + 2, &action, NULL);
135
136	/* Submit request list */
137	ret = lio_listio(LIO_NOWAIT, aiocbs, NUM_AIOCBS, &event);
138
139	if (ret != 0) {
140		printf(TNAME " Error lio_listio() %s\n", strerror(errno));
141
142		for (i = 0; i < NUM_AIOCBS; i++)
143			free(aiocbs[i]);
144		free(bufs);
145		close(fd);
146		exit(PTS_FAIL);
147	}
148
149	while (received_all == 0)
150		sleep(1);
151
152	if (num_received != NUM_AIOCBS) {
153		printf(TNAME
154		       " Error incomplete number of completed requests\n");
155
156		for (i = 0; i < NUM_AIOCBS; i++)
157			free(aiocbs[i]);
158		free(bufs);
159		close(fd);
160		exit(PTS_FAIL);
161	}
162
163	/* Check return code and free things */
164	for (i = 0; i < NUM_AIOCBS; i++) {
165		if (i == 2)
166			continue;
167
168		err = aio_error(aiocbs[i]);
169		ret = aio_return(aiocbs[i]);
170
171		if ((err != 0) && (ret != BUF_SIZE)) {
172			printf(TNAME " req %d: error = %d - return = %d\n", i,
173			       err, ret);
174			errors++;
175		}
176
177		free(aiocbs[i]);
178	}
179
180	free(bufs);
181
182	close(fd);
183
184	if (errors != 0)
185		exit(PTS_FAIL);
186
187	printf(TNAME " PASSED\n");
188
189	return PTS_PASS;
190}
191