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 *	If mode is LIO_WAIT, lio_listio() shall wait until all I/O is
13 *	complete and the sig argument shall be ignored.
14 *
15 * method:
16 *
17 *	- open a file for writing
18 *	- submit a list of writes to lio_listio in LIO_WAIT mode
19 *	- check that upon return all I/Os are completed
20 *	- check that the sig argument is ignored
21 *
22 */
23
24#define _XOPEN_SOURCE 600
25#include <stdio.h>
26#include <unistd.h>
27#include <string.h>
28#include <errno.h>
29#include <stdlib.h>
30#include <aio.h>
31
32#include "posixtest.h"
33
34#define TNAME "lio_listio/1-1.c"
35
36#define NUM_AIOCBS	10
37#define BUF_SIZE	1024*1024
38
39int received_selected	= 0;
40int received_all	= 0;
41
42void
43sigrt1_handler(int signum, siginfo_t *info, void *context)
44{
45	received_selected = info->si_value.sival_int;
46}
47
48void
49sigrt2_handler(int signum, siginfo_t *info, void *context)
50{
51	received_all = 1;
52}
53
54int main()
55{
56	char tmpfname[256];
57	int fd;
58
59	struct aiocb **aiocbs;
60	char *bufs;
61	struct sigaction action;
62	struct sigevent event;
63	int errors = 0;
64	int ret;
65	int err;
66	int i;
67
68#if _POSIX_ASYNCHRONOUS_IO != 200112L
69	exit(PTS_UNSUPPORTED);
70#endif
71
72	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_lio_listio_1_1_%d",
73		  getpid());
74	unlink(tmpfname);
75
76	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
77
78	if (fd == -1) {
79		printf(TNAME " Error at open(): %s\n",
80		       strerror(errno));
81		exit(PTS_UNRESOLVED);
82	}
83
84	unlink(tmpfname);
85
86	bufs = (char *) malloc (NUM_AIOCBS*BUF_SIZE);
87
88	if (bufs == NULL) {
89		printf (TNAME " Error at malloc(): %s\n", strerror (errno));
90		close (fd);
91		exit(PTS_UNRESOLVED);
92	}
93
94	aiocbs = (struct aiocb**)malloc(sizeof(struct aiocb *) * NUM_AIOCBS);
95
96	/* Queue up a bunch of aio writes */
97	for (i = 0; i < NUM_AIOCBS; i++) {
98
99		aiocbs[i] = (struct aiocb *)malloc(sizeof(struct aiocb));
100		memset(aiocbs[i], 0, sizeof(struct aiocb));
101
102		aiocbs[i]->aio_fildes = fd;
103		aiocbs[i]->aio_offset = 0;
104		aiocbs[i]->aio_buf = &bufs[i*BUF_SIZE];
105		aiocbs[i]->aio_nbytes = BUF_SIZE;
106		aiocbs[i]->aio_lio_opcode = LIO_WRITE;
107
108		/* Use SIRTMIN+1 for individual completions */
109		aiocbs[i]->aio_sigevent.sigev_notify = SIGEV_SIGNAL;
110		aiocbs[i]->aio_sigevent.sigev_signo = SIGRTMIN+1;
111		aiocbs[i]->aio_sigevent.sigev_value.sival_int = i;
112	}
113
114	/* Use SIGRTMIN+2 for list completion */
115	event.sigev_notify = SIGEV_SIGNAL;
116	event.sigev_signo = SIGRTMIN+2;
117	event.sigev_value.sival_ptr = NULL;
118
119	/* Setup handler for individual operation completion */
120	action.sa_sigaction = sigrt1_handler;
121	sigemptyset(&action.sa_mask);
122	action.sa_flags = SA_SIGINFO|SA_RESTART;
123	sigaction(SIGRTMIN+1, &action, NULL);
124
125	/* Setup handler for list completion */
126	action.sa_sigaction = sigrt2_handler;
127	sigemptyset(&action.sa_mask);
128	action.sa_flags = SA_SIGINFO|SA_RESTART;
129	sigaction(SIGRTMIN+2, &action, NULL);
130
131	/* Submit request list */
132	ret = lio_listio(LIO_WAIT, aiocbs, NUM_AIOCBS, &event);
133
134	if (ret) {
135		printf(TNAME " Error at lio_listio() %d: %s\n", errno, strerror(errno));
136		for (i=0; i<NUM_AIOCBS; i++)
137			free (aiocbs[i]);
138		free (bufs);
139		free (aiocbs);
140		close (fd);
141		exit (PTS_FAIL);
142	}
143
144	if (received_selected != NUM_AIOCBS-1)
145	{
146		printf(TNAME " lio_listio() did not wait\n");
147		for (i=0; i<NUM_AIOCBS; i++)
148			free (aiocbs[i]);
149		free (bufs);
150		free (aiocbs);
151		close (fd);
152		exit (PTS_FAIL);
153	}
154
155	if (received_all != 0)
156	{
157		printf(TNAME " lio_listio() did not ignore the sig argument\n");
158		for (i=0; i<NUM_AIOCBS; i++)
159			free (aiocbs[i]);
160		free (bufs);
161		free (aiocbs);
162		close (fd);
163		exit (PTS_FAIL);
164	}
165
166	/* Check return code and free things */
167	for (i = 0; i < NUM_AIOCBS; i++) {
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, err, ret);
173			errors++;
174		}
175
176		free (aiocbs[i]);
177	}
178
179	free (bufs);
180	free (aiocbs);
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