blob: 83377ddacaf828887c13e2e5e45cc3380e6a87c1 [file] [log] [blame]
subrata_modak66b84472008-08-11 09:56:25 +00001/*
2 * Copyright (c) 2008 Vijay Kumar B. <vijaykumar@bravegnu.org>
3 *
4 * Based on testcases/kernel/syscalls/waitpid/waitpid01.c
5 * Original copyright message:
6 *
7 * Copyright (c) International Business Machines Corp., 2001
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
subrata_modak66b84472008-08-11 09:56:25 +000022 */
23
24/*
25 * NAME
26 * eventfd01.c
27 *
28 * DESCRIPTION
29 * Test cases for eventfd syscall.
30 *
31 * USAGE: <for command-line>
32 * eventfd01 [-c n] [-i n] [-I x] [-P x] [-t]
33 * where, -c n : Run n copies concurrently.
34 * -i n : Execute test n times.
35 * -I x : Execute test for x seconds.
36 * -P x : Pause for x seconds between iterations.
subrata_modak66b84472008-08-11 09:56:25 +000037 *
38 * History
39 * 07/2008 Vijay Kumar
40 * Initial Version.
41 *
42 * Restrictions
43 * None
44 */
45
subrata_modak4fc9f542009-01-16 09:03:14 +000046#include "config.h"
47
subrata_modak66b84472008-08-11 09:56:25 +000048#include <sys/types.h>
Garrett Cooper02d739b2010-12-21 10:44:52 -080049#include <sys/select.h>
subrata_modak66b84472008-08-11 09:56:25 +000050#include <sys/wait.h>
subrata_modak66b84472008-08-11 09:56:25 +000051#include <errno.h>
Garrett Cooper02d739b2010-12-21 10:44:52 -080052#include <fcntl.h>
vapierc8b68a42009-08-28 12:26:07 +000053#include <inttypes.h>
subrata_modaka5b38e42008-08-20 11:28:51 +000054#include <poll.h>
Garrett Cooper02d739b2010-12-21 10:44:52 -080055#include <signal.h>
56#include <stdint.h>
57#include <string.h>
58#include <unistd.h>
subrata_modak66b84472008-08-11 09:56:25 +000059
Garrett Cooper02d739b2010-12-21 10:44:52 -080060#include "test.h"
yaberauneya6aa27372009-12-06 19:54:10 +000061#define CLEANUP cleanup
62#include "linux_syscall_numbers.h"
subrata_modak66b84472008-08-11 09:56:25 +000063
subrata_modak4fc9f542009-01-16 09:03:14 +000064#ifdef HAVE_LIBAIO_H
subrata_modaka5b38e42008-08-20 11:28:51 +000065#include <libaio.h>
66#endif
67
subrata_modak66b84472008-08-11 09:56:25 +000068static void setup(void);
subrata_modak66b84472008-08-11 09:56:25 +000069
subrata_modak4fc9f542009-01-16 09:03:14 +000070TCID_DEFINE(eventfd01);
subrata_modaka5b38e42008-08-20 11:28:51 +000071int TST_TOTAL = 15;
subrata_modak66b84472008-08-11 09:56:25 +000072
subrata_modak56207ce2009-03-23 13:35:39 +000073static int myeventfd(unsigned int initval, int flags)
subrata_modak66b84472008-08-11 09:56:25 +000074{
subrata_modak56207ce2009-03-23 13:35:39 +000075 /* eventfd2 uses FLAGS but eventfd doesn't take FLAGS. */
Jan Stancek359980f2013-02-15 10:16:05 +010076 return ltp_syscall(__NR_eventfd, initval);
subrata_modak66b84472008-08-11 09:56:25 +000077}
78
79/*
80 * clear_counter() - clears the counter by performing a dummy read
81 * @fd: the eventfd
82 *
83 * RETURNS:
84 * 0 on success, and -1 on failure
85 */
subrata_modak56207ce2009-03-23 13:35:39 +000086static int clear_counter(int fd)
subrata_modak66b84472008-08-11 09:56:25 +000087{
88 uint64_t dummy;
89 int ret;
90
91 ret = read(fd, &dummy, sizeof(dummy));
92 if (ret == -1) {
93 if (errno != EAGAIN) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080094 tst_resm(TINFO | TERRNO, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +000095 return -1;
96 }
97 }
98
99 return 0;
100}
101
102/*
103 * set_counter() - sets the count to specified value
104 * @fd: the eventfd
105 * @val: the value to be set
106 *
107 * Clears the counter and sets the counter to @val.
108 *
109 * RETURNS:
110 * 0 on success, -1 on failure
111 */
subrata_modak56207ce2009-03-23 13:35:39 +0000112static int set_counter(int fd, uint64_t val)
subrata_modak66b84472008-08-11 09:56:25 +0000113{
114 int ret;
115
116 ret = clear_counter(fd);
Garrett Cooper80678cf2010-12-21 10:49:20 -0800117 if (ret == -1)
subrata_modak66b84472008-08-11 09:56:25 +0000118 return -1;
subrata_modak66b84472008-08-11 09:56:25 +0000119
120 ret = write(fd, &val, sizeof(val));
121 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800122 tst_resm(TINFO | TERRNO, "error setting counter value");
subrata_modak66b84472008-08-11 09:56:25 +0000123 return -1;
124 }
125
126 return 0;
127}
128
129/*
130 * Test whether the current value of the counter matches @required.
131 */
subrata_modak56207ce2009-03-23 13:35:39 +0000132static void read_test(int fd, uint64_t required)
subrata_modak66b84472008-08-11 09:56:25 +0000133{
134 int ret;
135 uint64_t val;
136
137 ret = read(fd, &val, sizeof(val));
138 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800139 tst_resm(TBROK | TERRNO, "error reading eventfd");
subrata_modak66b84472008-08-11 09:56:25 +0000140 return;
141 }
142
143 if (val == required)
144 tst_resm(TPASS, "counter value matches required");
145 else
146 tst_resm(TFAIL, "counter value mismatch: "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800147 "required: %" PRIu64 ", got: %" PRIu64, required, val);
subrata_modak66b84472008-08-11 09:56:25 +0000148}
149
150/*
151 * Test whether read returns with error EAGAIN when counter is at 0.
152 */
subrata_modak56207ce2009-03-23 13:35:39 +0000153static void read_eagain_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000154{
155 int ret;
156 uint64_t val;
157
158 ret = clear_counter(fd);
subrata_modaka5b38e42008-08-20 11:28:51 +0000159 if (ret == -1) {
160 tst_resm(TBROK, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +0000161 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000162 }
subrata_modak66b84472008-08-11 09:56:25 +0000163
164 ret = read(fd, &val, sizeof(val));
165 if (ret == -1) {
166 if (errno == EAGAIN)
167 tst_resm(TPASS, "read failed with EAGAIN as expected");
168 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800169 tst_resm(TFAIL | TERRNO, "read failed (wanted EAGAIN)");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800170 } else
vapierc8b68a42009-08-28 12:26:07 +0000171 tst_resm(TFAIL, "read returned with %d", ret);
subrata_modak66b84472008-08-11 09:56:25 +0000172}
173
174/*
175 * Test whether writing to counter works.
176 */
subrata_modak56207ce2009-03-23 13:35:39 +0000177static void write_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000178{
179 int ret;
180 uint64_t val;
181
182 val = 12;
183
184 ret = set_counter(fd, val);
subrata_modaka5b38e42008-08-20 11:28:51 +0000185 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800186 tst_resm(TBROK, "error setting counter value to %" PRIu64, val);
subrata_modak66b84472008-08-11 09:56:25 +0000187 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000188 }
subrata_modak66b84472008-08-11 09:56:25 +0000189
190 read_test(fd, val);
191}
192
193/*
194 * Test whether write returns with error EAGAIN when counter is at
195 * (UINT64_MAX - 1).
196 */
subrata_modak56207ce2009-03-23 13:35:39 +0000197static void write_eagain_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000198{
199 int ret;
200 uint64_t val;
201
202 ret = set_counter(fd, UINT64_MAX - 1);
subrata_modaka5b38e42008-08-20 11:28:51 +0000203 if (ret == -1) {
204 tst_resm(TBROK, "error setting counter value to UINT64_MAX-1");
subrata_modak66b84472008-08-11 09:56:25 +0000205 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000206 }
subrata_modak66b84472008-08-11 09:56:25 +0000207
208 val = 1;
209 ret = write(fd, &val, sizeof(val));
210 if (ret == -1) {
211 if (errno == EAGAIN)
vapierc8b68a42009-08-28 12:26:07 +0000212 tst_resm(TPASS, "write failed with EAGAIN as expected");
subrata_modak66b84472008-08-11 09:56:25 +0000213 else
vapierc8b68a42009-08-28 12:26:07 +0000214 tst_resm(TFAIL, "write failed (wanted EAGAIN)");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800215 } else
subrata_modak66b84472008-08-11 09:56:25 +0000216 tst_resm(TFAIL, "write returned with %d", ret);
subrata_modak66b84472008-08-11 09:56:25 +0000217}
218
219/*
220 * Test whether read returns with error EINVAL, if buffer size is less
221 * than 8 bytes.
222 */
subrata_modak56207ce2009-03-23 13:35:39 +0000223static void read_einval_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000224{
225 uint32_t invalid;
226 int ret;
227
228 ret = read(fd, &invalid, sizeof(invalid));
229 if (ret == -1) {
Garrett Cooper80678cf2010-12-21 10:49:20 -0800230 if (errno == EINVAL)
subrata_modak66b84472008-08-11 09:56:25 +0000231 tst_resm(TPASS, "read failed with EINVAL as expected");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800232 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800233 tst_resm(TFAIL | TERRNO, "read failed (wanted EINVAL)");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800234 } else
subrata_modak66b84472008-08-11 09:56:25 +0000235 tst_resm(TFAIL, "read returned with %d", ret);
subrata_modak66b84472008-08-11 09:56:25 +0000236}
237
238/*
239 * Test whether write returns with error EINVAL, if buffer size is
240 * less than 8 bytes.
241 */
subrata_modak56207ce2009-03-23 13:35:39 +0000242static void write_einval_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000243{
244 uint32_t invalid;
245 int ret;
246
247 ret = write(fd, &invalid, sizeof(invalid));
248 if (ret == -1) {
Garrett Cooper80678cf2010-12-21 10:49:20 -0800249 if (errno == EINVAL)
vapierc8b68a42009-08-28 12:26:07 +0000250 tst_resm(TPASS, "write failed with EINVAL as expected");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800251 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800252 tst_resm(TFAIL | TERRNO,
253 "write failed (wanted EINVAL)");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800254 } else
subrata_modak66b84472008-08-11 09:56:25 +0000255 tst_resm(TFAIL, "write returned with %d", ret);
subrata_modak66b84472008-08-11 09:56:25 +0000256}
257
258/*
259 * Test wheter write returns with error EINVAL, when the written value
260 * is 0xFFFFFFFFFFFFFFFF.
261 */
subrata_modak56207ce2009-03-23 13:35:39 +0000262static void write_einval2_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000263{
264 int ret;
265 uint64_t val;
266
267 ret = clear_counter(fd);
subrata_modaka5b38e42008-08-20 11:28:51 +0000268 if (ret == -1) {
269 tst_resm(TBROK, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +0000270 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000271 }
subrata_modak66b84472008-08-11 09:56:25 +0000272
273 val = 0xffffffffffffffffLL;
274 ret = write(fd, &val, sizeof(val));
275 if (ret == -1) {
276 if (errno == EINVAL)
vapierc8b68a42009-08-28 12:26:07 +0000277 tst_resm(TPASS, "write failed with EINVAL as expected");
subrata_modak66b84472008-08-11 09:56:25 +0000278 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800279 tst_resm(TFAIL | TERRNO,
280 "write failed (wanted EINVAL)");
subrata_modak66b84472008-08-11 09:56:25 +0000281 } else {
282 tst_resm(TFAIL, "write returned with %d", ret);
283 }
284}
285
286/*
287 * Test whether readfd is set by select when counter value is
288 * non-zero.
289 */
subrata_modak56207ce2009-03-23 13:35:39 +0000290static void readfd_set_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000291{
292 int ret;
293 fd_set readfds;
294 struct timeval timeout = { 0, 0 };
295 uint64_t non_zero = 10;
296
297 FD_ZERO(&readfds);
298 FD_SET(fd, &readfds);
299
300 ret = set_counter(fd, non_zero);
subrata_modaka5b38e42008-08-20 11:28:51 +0000301 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800302 tst_resm(TBROK, "error setting counter value to %" PRIu64,
subrata_modaka5b38e42008-08-20 11:28:51 +0000303 non_zero);
subrata_modak66b84472008-08-11 09:56:25 +0000304 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000305 }
subrata_modak66b84472008-08-11 09:56:25 +0000306
307 ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
308 if (ret == -1) {
309 /* EINTR cannot occur, since we don't block. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800310 tst_resm(TBROK | TERRNO, "select() failed");
subrata_modak66b84472008-08-11 09:56:25 +0000311 return;
312 }
313
314 if (FD_ISSET(fd, &readfds))
315 tst_resm(TPASS, "fd is set in readfds");
316 else
317 tst_resm(TFAIL, "fd is not set in readfds");
318}
319
320/*
321 * Test whether readfd is not set by select when counter value is
322 * zero.
323 */
subrata_modak56207ce2009-03-23 13:35:39 +0000324static void readfd_not_set_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000325{
326 int ret;
327 fd_set readfds;
328 struct timeval timeout = { 0, 0 };
329
330 FD_ZERO(&readfds);
331 FD_SET(fd, &readfds);
332
333 ret = clear_counter(fd);
subrata_modaka5b38e42008-08-20 11:28:51 +0000334 if (ret == -1) {
335 tst_resm(TBROK, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +0000336 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000337 }
subrata_modak66b84472008-08-11 09:56:25 +0000338
339 ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
340 if (ret == -1) {
341 /* EINTR cannot occur, since we don't block. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800342 tst_resm(TBROK | TERRNO, "select() failed");
subrata_modak66b84472008-08-11 09:56:25 +0000343 return;
344 }
345
346 if (!FD_ISSET(fd, &readfds))
347 tst_resm(TPASS, "fd is not set in readfds");
348 else
349 tst_resm(TFAIL, "fd is set in readfds");
350}
351
352/*
353 * Test whether writefd is set by select when counter value is not the
354 * maximum counter value.
355 */
subrata_modak56207ce2009-03-23 13:35:39 +0000356static void writefd_set_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000357{
358 int ret;
359 fd_set writefds;
360 struct timeval timeout = { 0, 0 };
361 uint64_t non_max = 10;
362
363 FD_ZERO(&writefds);
364 FD_SET(fd, &writefds);
365
366 ret = set_counter(fd, non_max);
subrata_modaka5b38e42008-08-20 11:28:51 +0000367 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800368 tst_resm(TBROK, "error setting counter value to %" PRIu64,
369 non_max);
subrata_modak66b84472008-08-11 09:56:25 +0000370 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000371 }
subrata_modak66b84472008-08-11 09:56:25 +0000372
373 ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
374 if (ret == -1) {
375 /* EINTR cannot occur, since we don't block. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800376 tst_resm(TBROK | TERRNO, "select: error getting fd status");
subrata_modak66b84472008-08-11 09:56:25 +0000377 return;
378 }
379
380 if (FD_ISSET(fd, &writefds))
381 tst_resm(TPASS, "fd is set in writefds");
382 else
383 tst_resm(TFAIL, "fd is not set in writefds");
384}
385
386/*
387 * Test whether writefd is not set by select when counter value is at
388 * (UINT64_MAX - 1).
389 */
subrata_modak56207ce2009-03-23 13:35:39 +0000390static void writefd_not_set_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000391{
392 int ret;
393 fd_set writefds;
394 struct timeval timeout = { 0, 0 };
395
396 FD_ZERO(&writefds);
397 FD_SET(fd, &writefds);
398
399 ret = set_counter(fd, UINT64_MAX - 1);
subrata_modaka5b38e42008-08-20 11:28:51 +0000400 if (ret == -1) {
401 tst_resm(TBROK, "error setting counter value to UINT64_MAX-1");
subrata_modak66b84472008-08-11 09:56:25 +0000402 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000403 }
subrata_modak66b84472008-08-11 09:56:25 +0000404
405 ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
406 if (ret == -1) {
407 /* EINTR cannot occur, since we don't block. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800408 tst_resm(TBROK | TERRNO, "select: error getting fd status");
subrata_modak66b84472008-08-11 09:56:25 +0000409 return;
410 }
411
412 if (!FD_ISSET(fd, &writefds))
413 tst_resm(TPASS, "fd is not set in writefds");
414 else
415 tst_resm(TFAIL, "fd is set in writefds");
416}
417
418/*
419 * Test whether counter update in child is reflected in the parent.
420 */
subrata_modak56207ce2009-03-23 13:35:39 +0000421static void child_inherit_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000422{
423 uint64_t val;
424 pid_t cpid;
425 int ret;
426 int status;
427 uint64_t to_parent = 0xdeadbeef;
428 uint64_t dummy;
429
430 cpid = fork();
431 if (cpid == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800432 tst_resm(TBROK | TERRNO, "fork failed");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800433 else if (cpid != 0) {
subrata_modak66b84472008-08-11 09:56:25 +0000434 ret = wait(&status);
435 if (ret == -1) {
436 tst_resm(TBROK, "error getting child exit status");
437 return;
438 }
439
440 if (WEXITSTATUS(status) == 1) {
441 tst_resm(TBROK, "counter value write not "
Garrett Cooper80678cf2010-12-21 10:49:20 -0800442 "successful in child");
subrata_modak66b84472008-08-11 09:56:25 +0000443 return;
444 }
445
446 ret = read(fd, &val, sizeof(val));
447 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800448 tst_resm(TBROK | TERRNO, "error reading eventfd");
subrata_modak66b84472008-08-11 09:56:25 +0000449 return;
450 }
451
452 if (val == to_parent)
453 tst_resm(TPASS, "counter value write from "
454 "child successful");
455 else
456 tst_resm(TFAIL, "counter value write in child "
457 "failed");
458 } else {
459 /* Child */
460 ret = read(fd, &dummy, sizeof(dummy));
461 if (ret == -1 && errno != EAGAIN) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800462 tst_resm(TWARN | TERRNO, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +0000463 exit(1);
464 }
465
466 ret = write(fd, &to_parent, sizeof(to_parent));
467 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800468 tst_resm(TWARN | TERRNO, "error writing eventfd");
subrata_modak66b84472008-08-11 09:56:25 +0000469 exit(1);
470 }
471
472 exit(0);
473 }
474}
475
subrata_modak4fc9f542009-01-16 09:03:14 +0000476#ifdef HAVE_IO_SET_EVENTFD
subrata_modaka5b38e42008-08-20 11:28:51 +0000477/*
subrata_modak4bb656a2009-02-26 12:02:09 +0000478 * Test whether counter overflow is detected and handled correctly.
subrata_modaka5b38e42008-08-20 11:28:51 +0000479 *
480 * It is not possible to directly overflow the counter using the
481 * write() syscall. Overflows occur when the counter is incremented
482 * from kernel space, in an irq context, when it is not possible to
483 * block the calling thread of execution.
484 *
485 * The AIO subsystem internally uses eventfd mechanism for
486 * notification of completion of read or write requests. In this test
487 * we trigger a counter overflow, by setting the counter value to the
488 * max possible value initially. When the AIO subsystem notifies
489 * through the eventfd counter, the counter overflows.
490 *
491 * NOTE: If the the counter starts from an initial value of 0, it will
492 * take decades for an overflow to occur. But since we set the initial
493 * value to the max possible counter value, we are able to cause it to
494 * overflow with a single increment.
495 *
496 * When the counter overflows, the following are tested
497 * 1. Check whether POLLERR event occurs in poll() for the eventfd.
498 * 2. Check whether readfd_set/writefd_set is set in select() for the
499 eventfd.
500 * 3. The counter value is UINT64_MAX.
501 */
subrata_modak56207ce2009-03-23 13:35:39 +0000502static int trigger_eventfd_overflow(int evfd, int *fd, io_context_t * ctx)
subrata_modaka5b38e42008-08-20 11:28:51 +0000503{
504 int ret;
505 struct iocb iocb;
506 struct iocb *iocbap[1];
507 static char buf[4 * 1024];
508
509 *ctx = 0;
510 ret = io_setup(16, ctx);
511 if (ret < 0) {
vapierc8b68a42009-08-28 12:26:07 +0000512 errno = -ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800513 tst_resm(TINFO | TERRNO, "io_setup error");
subrata_modaka5b38e42008-08-20 11:28:51 +0000514 return -1;
515 }
516
517 *fd = open("testfile", O_RDWR | O_CREAT, 0644);
518 if (*fd == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800519 tst_resm(TINFO | TERRNO, "open(testfile) failed");
subrata_modaka5b38e42008-08-20 11:28:51 +0000520 goto err_io_destroy;
521 }
522
523 ret = set_counter(evfd, UINT64_MAX - 1);
524 if (ret == -1) {
525 tst_resm(TINFO, "error setting counter to UINT64_MAX-1");
526 goto err_close_file;
527 }
528
529 io_prep_pwrite(&iocb, *fd, buf, sizeof(buf), 0);
530 io_set_eventfd(&iocb, evfd);
subrata_modakbdbaec52009-02-26 12:14:51 +0000531
subrata_modaka5b38e42008-08-20 11:28:51 +0000532 iocbap[0] = &iocb;
533 ret = io_submit(*ctx, 1, iocbap);
534 if (ret < 0) {
vapierc8b68a42009-08-28 12:26:07 +0000535 errno = -ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800536 tst_resm(TINFO | TERRNO, "error submitting iocb");
subrata_modaka5b38e42008-08-20 11:28:51 +0000537 goto err_close_file;
538 }
539
540 return 0;
541
yaberauneyae70b30b2009-11-27 07:40:16 +0000542err_close_file:
subrata_modaka5b38e42008-08-20 11:28:51 +0000543 close(*fd);
544
yaberauneyae70b30b2009-11-27 07:40:16 +0000545err_io_destroy:
subrata_modaka5b38e42008-08-20 11:28:51 +0000546 io_destroy(*ctx);
547
548 return -1;
549}
550
subrata_modak56207ce2009-03-23 13:35:39 +0000551static void cleanup_overflow(int fd, io_context_t ctx)
subrata_modaka5b38e42008-08-20 11:28:51 +0000552{
553 close(fd);
554 io_destroy(ctx);
555}
556
subrata_modak56207ce2009-03-23 13:35:39 +0000557static void overflow_select_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000558{
559 struct timeval timeout = { 10, 0 };
560 fd_set readfds;
561 int fd;
562 io_context_t ctx;
563 int ret;
564
565 ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
566 if (ret == -1) {
567 tst_resm(TBROK, "error triggering eventfd overflow");
568 return;
569 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000570
subrata_modaka5b38e42008-08-20 11:28:51 +0000571 FD_ZERO(&readfds);
572 FD_SET(evfd, &readfds);
573 ret = select(evfd + 1, &readfds, NULL, NULL, &timeout);
Garrett Cooper80678cf2010-12-21 10:49:20 -0800574 if (ret == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800575 tst_resm(TBROK | TERRNO,
576 "error getting evfd status with select");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800577 else {
yaberauneyae70b30b2009-11-27 07:40:16 +0000578 if (FD_ISSET(evfd, &readfds))
579 tst_resm(TPASS, "read fd set as expected");
580 else
581 tst_resm(TFAIL, "read fd not set");
subrata_modaka5b38e42008-08-20 11:28:51 +0000582 }
subrata_modaka5b38e42008-08-20 11:28:51 +0000583 cleanup_overflow(fd, ctx);
584}
585
subrata_modak56207ce2009-03-23 13:35:39 +0000586static void overflow_poll_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000587{
588 struct pollfd pollfd;
589 int fd;
590 io_context_t ctx;
591 int ret;
592
593 ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
Subrata Modakf0be8b02010-05-07 10:33:00 +0530594 if (ret == -1) {
subrata_modaka5b38e42008-08-20 11:28:51 +0000595 tst_resm(TBROK, "error triggering eventfd overflow");
596 return;
597 }
598
599 pollfd.fd = evfd;
600 pollfd.events = POLLIN;
601 pollfd.revents = 0;
602 ret = poll(&pollfd, 1, 10000);
Garrett Cooper80678cf2010-12-21 10:49:20 -0800603 if (ret == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800604 tst_resm(TBROK | TERRNO, "error getting evfd status with poll");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800605 else {
yaberauneyae70b30b2009-11-27 07:40:16 +0000606 if (pollfd.revents & POLLERR)
607 tst_resm(TPASS, "POLLERR occurred as expected");
608 else
609 tst_resm(TFAIL, "POLLERR did not occur");
subrata_modaka5b38e42008-08-20 11:28:51 +0000610 }
subrata_modaka5b38e42008-08-20 11:28:51 +0000611 cleanup_overflow(fd, ctx);
612}
613
subrata_modak56207ce2009-03-23 13:35:39 +0000614static void overflow_read_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000615{
616 uint64_t count;
617 io_context_t ctx;
618 int fd;
619 int ret;
620
621 ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
622 if (ret == -1) {
623 tst_resm(TBROK, "error triggering eventfd overflow");
624 return;
625 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000626
subrata_modak4bb656a2009-02-26 12:02:09 +0000627 ret = read(evfd, &count, sizeof(count));
Garrett Cooper80678cf2010-12-21 10:49:20 -0800628 if (ret == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800629 tst_resm(TBROK | TERRNO, "error reading eventfd");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800630 else {
yaberauneyae70b30b2009-11-27 07:40:16 +0000631
632 if (count == UINT64_MAX)
633 tst_resm(TPASS, "overflow occurred as expected");
634 else
635 tst_resm(TFAIL, "overflow did not occur");
subrata_modaka5b38e42008-08-20 11:28:51 +0000636 }
subrata_modaka5b38e42008-08-20 11:28:51 +0000637 cleanup_overflow(fd, ctx);
638}
639#else
subrata_modak56207ce2009-03-23 13:35:39 +0000640static void overflow_select_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000641{
642 tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
643}
644
subrata_modak56207ce2009-03-23 13:35:39 +0000645static void overflow_poll_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000646{
647 tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
648}
649
subrata_modak56207ce2009-03-23 13:35:39 +0000650static void overflow_read_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000651{
652 tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
653}
654#endif
655
subrata_modak56207ce2009-03-23 13:35:39 +0000656int main(int argc, char **argv)
subrata_modak66b84472008-08-11 09:56:25 +0000657{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200658 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200659 const char *msg;
subrata_modak66b84472008-08-11 09:56:25 +0000660 int fd;
661
Garrett Cooper80678cf2010-12-21 10:49:20 -0800662 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
subrata_modak66b84472008-08-11 09:56:25 +0000663 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modak66b84472008-08-11 09:56:25 +0000664
665 setup();
666
subrata_modak66b84472008-08-11 09:56:25 +0000667 for (lc = 0; TEST_LOOPING(lc); lc++) {
668 int ret;
669 uint64_t einit = 10;
670
Caspar Zhangd59a6592013-03-07 14:59:12 +0800671 tst_count = 0;
subrata_modak66b84472008-08-11 09:56:25 +0000672
673 fd = myeventfd(einit, 0);
674 if (fd == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800675 tst_brkm(TBROK | TERRNO, CLEANUP,
676 "error creating eventfd");
subrata_modak66b84472008-08-11 09:56:25 +0000677
678 ret = fcntl(fd, F_SETFL, O_NONBLOCK);
679 if (ret == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800680 tst_brkm(TBROK | TERRNO, CLEANUP,
681 "error setting non-block mode");
subrata_modak66b84472008-08-11 09:56:25 +0000682
683 read_test(fd, einit);
684 read_eagain_test(fd);
685 write_test(fd);
686 write_eagain_test(fd);
687 read_einval_test(fd);
688 write_einval_test(fd);
689 write_einval2_test(fd);
690 readfd_set_test(fd);
691 readfd_not_set_test(fd);
692 writefd_set_test(fd);
693 writefd_not_set_test(fd);
694 child_inherit_test(fd);
subrata_modaka5b38e42008-08-20 11:28:51 +0000695 overflow_select_test(fd);
696 overflow_poll_test(fd);
697 overflow_read_test(fd);
subrata_modak66b84472008-08-11 09:56:25 +0000698
699 close(fd);
700 }
701
702 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800703
yaberauneyae70b30b2009-11-27 07:40:16 +0000704 tst_exit();
subrata_modak66b84472008-08-11 09:56:25 +0000705}
706
subrata_modak56207ce2009-03-23 13:35:39 +0000707static void setup(void)
subrata_modak66b84472008-08-11 09:56:25 +0000708{
Garrett Cooper2c282152010-12-16 00:55:50 -0800709
subrata_modak66b84472008-08-11 09:56:25 +0000710 tst_sig(FORK, DEF_HANDLER, cleanup);
711
712 if (tst_kvercmp(2, 6, 22) < 0)
Garrett Cooper53740502010-12-16 00:04:01 -0800713 tst_brkm(TCONF, NULL, "2.6.22 or greater kernel required");
subrata_modak66b84472008-08-11 09:56:25 +0000714
subrata_modak94e24dd2009-06-25 07:24:49 +0000715 tst_tmpdir();
Garrett Cooper80678cf2010-12-21 10:49:20 -0800716
subrata_modak66b84472008-08-11 09:56:25 +0000717 TEST_PAUSE;
718}
719
yaberauneya6aa27372009-12-06 19:54:10 +0000720static void cleanup(void)
subrata_modak66b84472008-08-11 09:56:25 +0000721{
subrata_modak94e24dd2009-06-25 07:24:49 +0000722 tst_rmdir();
Garrett Cooper02d739b2010-12-21 10:44:52 -0800723}