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