blob: 31c992d15ef5245f2134edc08425de3be955874f [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"
61#include "usctest.h"
yaberauneya6aa27372009-12-06 19:54:10 +000062#define CLEANUP cleanup
63#include "linux_syscall_numbers.h"
subrata_modak66b84472008-08-11 09:56:25 +000064
subrata_modak4fc9f542009-01-16 09:03:14 +000065#ifdef HAVE_LIBAIO_H
subrata_modaka5b38e42008-08-20 11:28:51 +000066#include <libaio.h>
67#endif
68
subrata_modak66b84472008-08-11 09:56:25 +000069static void setup(void);
subrata_modak66b84472008-08-11 09:56:25 +000070
subrata_modak4fc9f542009-01-16 09:03:14 +000071TCID_DEFINE(eventfd01);
subrata_modaka5b38e42008-08-20 11:28:51 +000072int TST_TOTAL = 15;
subrata_modak66b84472008-08-11 09:56:25 +000073
subrata_modak56207ce2009-03-23 13:35:39 +000074static int myeventfd(unsigned int initval, int flags)
subrata_modak66b84472008-08-11 09:56:25 +000075{
subrata_modak56207ce2009-03-23 13:35:39 +000076 /* eventfd2 uses FLAGS but eventfd doesn't take FLAGS. */
Jan Stancek359980f2013-02-15 10:16:05 +010077 return ltp_syscall(__NR_eventfd, initval);
subrata_modak66b84472008-08-11 09:56:25 +000078}
79
80/*
81 * clear_counter() - clears the counter by performing a dummy read
82 * @fd: the eventfd
83 *
84 * RETURNS:
85 * 0 on success, and -1 on failure
86 */
subrata_modak56207ce2009-03-23 13:35:39 +000087static int clear_counter(int fd)
subrata_modak66b84472008-08-11 09:56:25 +000088{
89 uint64_t dummy;
90 int ret;
91
92 ret = read(fd, &dummy, sizeof(dummy));
93 if (ret == -1) {
94 if (errno != EAGAIN) {
Wanlong Gao354ebb42012-12-07 10:10:04 +080095 tst_resm(TINFO | TERRNO, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +000096 return -1;
97 }
98 }
99
100 return 0;
101}
102
103/*
104 * set_counter() - sets the count to specified value
105 * @fd: the eventfd
106 * @val: the value to be set
107 *
108 * Clears the counter and sets the counter to @val.
109 *
110 * RETURNS:
111 * 0 on success, -1 on failure
112 */
subrata_modak56207ce2009-03-23 13:35:39 +0000113static int set_counter(int fd, uint64_t val)
subrata_modak66b84472008-08-11 09:56:25 +0000114{
115 int ret;
116
117 ret = clear_counter(fd);
Garrett Cooper80678cf2010-12-21 10:49:20 -0800118 if (ret == -1)
subrata_modak66b84472008-08-11 09:56:25 +0000119 return -1;
subrata_modak66b84472008-08-11 09:56:25 +0000120
121 ret = write(fd, &val, sizeof(val));
122 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800123 tst_resm(TINFO | TERRNO, "error setting counter value");
subrata_modak66b84472008-08-11 09:56:25 +0000124 return -1;
125 }
126
127 return 0;
128}
129
130/*
131 * Test whether the current value of the counter matches @required.
132 */
subrata_modak56207ce2009-03-23 13:35:39 +0000133static void read_test(int fd, uint64_t required)
subrata_modak66b84472008-08-11 09:56:25 +0000134{
135 int ret;
136 uint64_t val;
137
138 ret = read(fd, &val, sizeof(val));
139 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 tst_resm(TBROK | TERRNO, "error reading eventfd");
subrata_modak66b84472008-08-11 09:56:25 +0000141 return;
142 }
143
144 if (val == required)
145 tst_resm(TPASS, "counter value matches required");
146 else
147 tst_resm(TFAIL, "counter value mismatch: "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800148 "required: %" PRIu64 ", got: %" PRIu64, required, val);
subrata_modak66b84472008-08-11 09:56:25 +0000149}
150
151/*
152 * Test whether read returns with error EAGAIN when counter is at 0.
153 */
subrata_modak56207ce2009-03-23 13:35:39 +0000154static void read_eagain_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000155{
156 int ret;
157 uint64_t val;
158
159 ret = clear_counter(fd);
subrata_modaka5b38e42008-08-20 11:28:51 +0000160 if (ret == -1) {
161 tst_resm(TBROK, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +0000162 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000163 }
subrata_modak66b84472008-08-11 09:56:25 +0000164
165 ret = read(fd, &val, sizeof(val));
166 if (ret == -1) {
167 if (errno == EAGAIN)
168 tst_resm(TPASS, "read failed with EAGAIN as expected");
169 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800170 tst_resm(TFAIL | TERRNO, "read failed (wanted EAGAIN)");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800171 } else
vapierc8b68a42009-08-28 12:26:07 +0000172 tst_resm(TFAIL, "read returned with %d", ret);
subrata_modak66b84472008-08-11 09:56:25 +0000173}
174
175/*
176 * Test whether writing to counter works.
177 */
subrata_modak56207ce2009-03-23 13:35:39 +0000178static void write_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000179{
180 int ret;
181 uint64_t val;
182
183 val = 12;
184
185 ret = set_counter(fd, val);
subrata_modaka5b38e42008-08-20 11:28:51 +0000186 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800187 tst_resm(TBROK, "error setting counter value to %" PRIu64, val);
subrata_modak66b84472008-08-11 09:56:25 +0000188 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000189 }
subrata_modak66b84472008-08-11 09:56:25 +0000190
191 read_test(fd, val);
192}
193
194/*
195 * Test whether write returns with error EAGAIN when counter is at
196 * (UINT64_MAX - 1).
197 */
subrata_modak56207ce2009-03-23 13:35:39 +0000198static void write_eagain_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000199{
200 int ret;
201 uint64_t val;
202
203 ret = set_counter(fd, UINT64_MAX - 1);
subrata_modaka5b38e42008-08-20 11:28:51 +0000204 if (ret == -1) {
205 tst_resm(TBROK, "error setting counter value to UINT64_MAX-1");
subrata_modak66b84472008-08-11 09:56:25 +0000206 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000207 }
subrata_modak66b84472008-08-11 09:56:25 +0000208
209 val = 1;
210 ret = write(fd, &val, sizeof(val));
211 if (ret == -1) {
212 if (errno == EAGAIN)
vapierc8b68a42009-08-28 12:26:07 +0000213 tst_resm(TPASS, "write failed with EAGAIN as expected");
subrata_modak66b84472008-08-11 09:56:25 +0000214 else
vapierc8b68a42009-08-28 12:26:07 +0000215 tst_resm(TFAIL, "write failed (wanted EAGAIN)");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800216 } else
subrata_modak66b84472008-08-11 09:56:25 +0000217 tst_resm(TFAIL, "write returned with %d", ret);
subrata_modak66b84472008-08-11 09:56:25 +0000218}
219
220/*
221 * Test whether read returns with error EINVAL, if buffer size is less
222 * than 8 bytes.
223 */
subrata_modak56207ce2009-03-23 13:35:39 +0000224static void read_einval_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000225{
226 uint32_t invalid;
227 int ret;
228
229 ret = read(fd, &invalid, sizeof(invalid));
230 if (ret == -1) {
Garrett Cooper80678cf2010-12-21 10:49:20 -0800231 if (errno == EINVAL)
subrata_modak66b84472008-08-11 09:56:25 +0000232 tst_resm(TPASS, "read failed with EINVAL as expected");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800233 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800234 tst_resm(TFAIL | TERRNO, "read failed (wanted EINVAL)");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800235 } else
subrata_modak66b84472008-08-11 09:56:25 +0000236 tst_resm(TFAIL, "read returned with %d", ret);
subrata_modak66b84472008-08-11 09:56:25 +0000237}
238
239/*
240 * Test whether write returns with error EINVAL, if buffer size is
241 * less than 8 bytes.
242 */
subrata_modak56207ce2009-03-23 13:35:39 +0000243static void write_einval_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000244{
245 uint32_t invalid;
246 int ret;
247
248 ret = write(fd, &invalid, sizeof(invalid));
249 if (ret == -1) {
Garrett Cooper80678cf2010-12-21 10:49:20 -0800250 if (errno == EINVAL)
vapierc8b68a42009-08-28 12:26:07 +0000251 tst_resm(TPASS, "write failed with EINVAL as expected");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800252 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800253 tst_resm(TFAIL | TERRNO,
254 "write failed (wanted EINVAL)");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800255 } else
subrata_modak66b84472008-08-11 09:56:25 +0000256 tst_resm(TFAIL, "write returned with %d", ret);
subrata_modak66b84472008-08-11 09:56:25 +0000257}
258
259/*
260 * Test wheter write returns with error EINVAL, when the written value
261 * is 0xFFFFFFFFFFFFFFFF.
262 */
subrata_modak56207ce2009-03-23 13:35:39 +0000263static void write_einval2_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000264{
265 int ret;
266 uint64_t val;
267
268 ret = clear_counter(fd);
subrata_modaka5b38e42008-08-20 11:28:51 +0000269 if (ret == -1) {
270 tst_resm(TBROK, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +0000271 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000272 }
subrata_modak66b84472008-08-11 09:56:25 +0000273
274 val = 0xffffffffffffffffLL;
275 ret = write(fd, &val, sizeof(val));
276 if (ret == -1) {
277 if (errno == EINVAL)
vapierc8b68a42009-08-28 12:26:07 +0000278 tst_resm(TPASS, "write failed with EINVAL as expected");
subrata_modak66b84472008-08-11 09:56:25 +0000279 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800280 tst_resm(TFAIL | TERRNO,
281 "write failed (wanted EINVAL)");
subrata_modak66b84472008-08-11 09:56:25 +0000282 } else {
283 tst_resm(TFAIL, "write returned with %d", ret);
284 }
285}
286
287/*
288 * Test whether readfd is set by select when counter value is
289 * non-zero.
290 */
subrata_modak56207ce2009-03-23 13:35:39 +0000291static void readfd_set_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000292{
293 int ret;
294 fd_set readfds;
295 struct timeval timeout = { 0, 0 };
296 uint64_t non_zero = 10;
297
298 FD_ZERO(&readfds);
299 FD_SET(fd, &readfds);
300
301 ret = set_counter(fd, non_zero);
subrata_modaka5b38e42008-08-20 11:28:51 +0000302 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800303 tst_resm(TBROK, "error setting counter value to %" PRIu64,
subrata_modaka5b38e42008-08-20 11:28:51 +0000304 non_zero);
subrata_modak66b84472008-08-11 09:56:25 +0000305 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000306 }
subrata_modak66b84472008-08-11 09:56:25 +0000307
308 ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
309 if (ret == -1) {
310 /* EINTR cannot occur, since we don't block. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800311 tst_resm(TBROK | TERRNO, "select() failed");
subrata_modak66b84472008-08-11 09:56:25 +0000312 return;
313 }
314
315 if (FD_ISSET(fd, &readfds))
316 tst_resm(TPASS, "fd is set in readfds");
317 else
318 tst_resm(TFAIL, "fd is not set in readfds");
319}
320
321/*
322 * Test whether readfd is not set by select when counter value is
323 * zero.
324 */
subrata_modak56207ce2009-03-23 13:35:39 +0000325static void readfd_not_set_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000326{
327 int ret;
328 fd_set readfds;
329 struct timeval timeout = { 0, 0 };
330
331 FD_ZERO(&readfds);
332 FD_SET(fd, &readfds);
333
334 ret = clear_counter(fd);
subrata_modaka5b38e42008-08-20 11:28:51 +0000335 if (ret == -1) {
336 tst_resm(TBROK, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +0000337 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000338 }
subrata_modak66b84472008-08-11 09:56:25 +0000339
340 ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
341 if (ret == -1) {
342 /* EINTR cannot occur, since we don't block. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800343 tst_resm(TBROK | TERRNO, "select() failed");
subrata_modak66b84472008-08-11 09:56:25 +0000344 return;
345 }
346
347 if (!FD_ISSET(fd, &readfds))
348 tst_resm(TPASS, "fd is not set in readfds");
349 else
350 tst_resm(TFAIL, "fd is set in readfds");
351}
352
353/*
354 * Test whether writefd is set by select when counter value is not the
355 * maximum counter value.
356 */
subrata_modak56207ce2009-03-23 13:35:39 +0000357static void writefd_set_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000358{
359 int ret;
360 fd_set writefds;
361 struct timeval timeout = { 0, 0 };
362 uint64_t non_max = 10;
363
364 FD_ZERO(&writefds);
365 FD_SET(fd, &writefds);
366
367 ret = set_counter(fd, non_max);
subrata_modaka5b38e42008-08-20 11:28:51 +0000368 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800369 tst_resm(TBROK, "error setting counter value to %" PRIu64,
370 non_max);
subrata_modak66b84472008-08-11 09:56:25 +0000371 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000372 }
subrata_modak66b84472008-08-11 09:56:25 +0000373
374 ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
375 if (ret == -1) {
376 /* EINTR cannot occur, since we don't block. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800377 tst_resm(TBROK | TERRNO, "select: error getting fd status");
subrata_modak66b84472008-08-11 09:56:25 +0000378 return;
379 }
380
381 if (FD_ISSET(fd, &writefds))
382 tst_resm(TPASS, "fd is set in writefds");
383 else
384 tst_resm(TFAIL, "fd is not set in writefds");
385}
386
387/*
388 * Test whether writefd is not set by select when counter value is at
389 * (UINT64_MAX - 1).
390 */
subrata_modak56207ce2009-03-23 13:35:39 +0000391static void writefd_not_set_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000392{
393 int ret;
394 fd_set writefds;
395 struct timeval timeout = { 0, 0 };
396
397 FD_ZERO(&writefds);
398 FD_SET(fd, &writefds);
399
400 ret = set_counter(fd, UINT64_MAX - 1);
subrata_modaka5b38e42008-08-20 11:28:51 +0000401 if (ret == -1) {
402 tst_resm(TBROK, "error setting counter value to UINT64_MAX-1");
subrata_modak66b84472008-08-11 09:56:25 +0000403 return;
subrata_modaka5b38e42008-08-20 11:28:51 +0000404 }
subrata_modak66b84472008-08-11 09:56:25 +0000405
406 ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
407 if (ret == -1) {
408 /* EINTR cannot occur, since we don't block. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800409 tst_resm(TBROK | TERRNO, "select: error getting fd status");
subrata_modak66b84472008-08-11 09:56:25 +0000410 return;
411 }
412
413 if (!FD_ISSET(fd, &writefds))
414 tst_resm(TPASS, "fd is not set in writefds");
415 else
416 tst_resm(TFAIL, "fd is set in writefds");
417}
418
419/*
420 * Test whether counter update in child is reflected in the parent.
421 */
subrata_modak56207ce2009-03-23 13:35:39 +0000422static void child_inherit_test(int fd)
subrata_modak66b84472008-08-11 09:56:25 +0000423{
424 uint64_t val;
425 pid_t cpid;
426 int ret;
427 int status;
428 uint64_t to_parent = 0xdeadbeef;
429 uint64_t dummy;
430
431 cpid = fork();
432 if (cpid == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800433 tst_resm(TBROK | TERRNO, "fork failed");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800434 else if (cpid != 0) {
subrata_modak66b84472008-08-11 09:56:25 +0000435 ret = wait(&status);
436 if (ret == -1) {
437 tst_resm(TBROK, "error getting child exit status");
438 return;
439 }
440
441 if (WEXITSTATUS(status) == 1) {
442 tst_resm(TBROK, "counter value write not "
Garrett Cooper80678cf2010-12-21 10:49:20 -0800443 "successful in child");
subrata_modak66b84472008-08-11 09:56:25 +0000444 return;
445 }
446
447 ret = read(fd, &val, sizeof(val));
448 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800449 tst_resm(TBROK | TERRNO, "error reading eventfd");
subrata_modak66b84472008-08-11 09:56:25 +0000450 return;
451 }
452
453 if (val == to_parent)
454 tst_resm(TPASS, "counter value write from "
455 "child successful");
456 else
457 tst_resm(TFAIL, "counter value write in child "
458 "failed");
459 } else {
460 /* Child */
461 ret = read(fd, &dummy, sizeof(dummy));
462 if (ret == -1 && errno != EAGAIN) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800463 tst_resm(TWARN | TERRNO, "error clearing counter");
subrata_modak66b84472008-08-11 09:56:25 +0000464 exit(1);
465 }
466
467 ret = write(fd, &to_parent, sizeof(to_parent));
468 if (ret == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800469 tst_resm(TWARN | TERRNO, "error writing eventfd");
subrata_modak66b84472008-08-11 09:56:25 +0000470 exit(1);
471 }
472
473 exit(0);
474 }
475}
476
subrata_modak4fc9f542009-01-16 09:03:14 +0000477#ifdef HAVE_IO_SET_EVENTFD
subrata_modaka5b38e42008-08-20 11:28:51 +0000478/*
subrata_modak4bb656a2009-02-26 12:02:09 +0000479 * Test whether counter overflow is detected and handled correctly.
subrata_modaka5b38e42008-08-20 11:28:51 +0000480 *
481 * It is not possible to directly overflow the counter using the
482 * write() syscall. Overflows occur when the counter is incremented
483 * from kernel space, in an irq context, when it is not possible to
484 * block the calling thread of execution.
485 *
486 * The AIO subsystem internally uses eventfd mechanism for
487 * notification of completion of read or write requests. In this test
488 * we trigger a counter overflow, by setting the counter value to the
489 * max possible value initially. When the AIO subsystem notifies
490 * through the eventfd counter, the counter overflows.
491 *
492 * NOTE: If the the counter starts from an initial value of 0, it will
493 * take decades for an overflow to occur. But since we set the initial
494 * value to the max possible counter value, we are able to cause it to
495 * overflow with a single increment.
496 *
497 * When the counter overflows, the following are tested
498 * 1. Check whether POLLERR event occurs in poll() for the eventfd.
499 * 2. Check whether readfd_set/writefd_set is set in select() for the
500 eventfd.
501 * 3. The counter value is UINT64_MAX.
502 */
subrata_modak56207ce2009-03-23 13:35:39 +0000503static int trigger_eventfd_overflow(int evfd, int *fd, io_context_t * ctx)
subrata_modaka5b38e42008-08-20 11:28:51 +0000504{
505 int ret;
506 struct iocb iocb;
507 struct iocb *iocbap[1];
508 static char buf[4 * 1024];
509
510 *ctx = 0;
511 ret = io_setup(16, ctx);
512 if (ret < 0) {
vapierc8b68a42009-08-28 12:26:07 +0000513 errno = -ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800514 tst_resm(TINFO | TERRNO, "io_setup error");
subrata_modaka5b38e42008-08-20 11:28:51 +0000515 return -1;
516 }
517
518 *fd = open("testfile", O_RDWR | O_CREAT, 0644);
519 if (*fd == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800520 tst_resm(TINFO | TERRNO, "open(testfile) failed");
subrata_modaka5b38e42008-08-20 11:28:51 +0000521 goto err_io_destroy;
522 }
523
524 ret = set_counter(evfd, UINT64_MAX - 1);
525 if (ret == -1) {
526 tst_resm(TINFO, "error setting counter to UINT64_MAX-1");
527 goto err_close_file;
528 }
529
530 io_prep_pwrite(&iocb, *fd, buf, sizeof(buf), 0);
531 io_set_eventfd(&iocb, evfd);
subrata_modakbdbaec52009-02-26 12:14:51 +0000532
subrata_modaka5b38e42008-08-20 11:28:51 +0000533 iocbap[0] = &iocb;
534 ret = io_submit(*ctx, 1, iocbap);
535 if (ret < 0) {
vapierc8b68a42009-08-28 12:26:07 +0000536 errno = -ret;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800537 tst_resm(TINFO | TERRNO, "error submitting iocb");
subrata_modaka5b38e42008-08-20 11:28:51 +0000538 goto err_close_file;
539 }
540
541 return 0;
542
yaberauneyae70b30b2009-11-27 07:40:16 +0000543err_close_file:
subrata_modaka5b38e42008-08-20 11:28:51 +0000544 close(*fd);
545
yaberauneyae70b30b2009-11-27 07:40:16 +0000546err_io_destroy:
subrata_modaka5b38e42008-08-20 11:28:51 +0000547 io_destroy(*ctx);
548
549 return -1;
550}
551
subrata_modak56207ce2009-03-23 13:35:39 +0000552static void cleanup_overflow(int fd, io_context_t ctx)
subrata_modaka5b38e42008-08-20 11:28:51 +0000553{
554 close(fd);
555 io_destroy(ctx);
556}
557
subrata_modak56207ce2009-03-23 13:35:39 +0000558static void overflow_select_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000559{
560 struct timeval timeout = { 10, 0 };
561 fd_set readfds;
562 int fd;
563 io_context_t ctx;
564 int ret;
565
566 ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
567 if (ret == -1) {
568 tst_resm(TBROK, "error triggering eventfd overflow");
569 return;
570 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000571
subrata_modaka5b38e42008-08-20 11:28:51 +0000572 FD_ZERO(&readfds);
573 FD_SET(evfd, &readfds);
574 ret = select(evfd + 1, &readfds, NULL, NULL, &timeout);
Garrett Cooper80678cf2010-12-21 10:49:20 -0800575 if (ret == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800576 tst_resm(TBROK | TERRNO,
577 "error getting evfd status with select");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800578 else {
yaberauneyae70b30b2009-11-27 07:40:16 +0000579 if (FD_ISSET(evfd, &readfds))
580 tst_resm(TPASS, "read fd set as expected");
581 else
582 tst_resm(TFAIL, "read fd not set");
subrata_modaka5b38e42008-08-20 11:28:51 +0000583 }
subrata_modaka5b38e42008-08-20 11:28:51 +0000584 cleanup_overflow(fd, ctx);
585}
586
subrata_modak56207ce2009-03-23 13:35:39 +0000587static void overflow_poll_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000588{
589 struct pollfd pollfd;
590 int fd;
591 io_context_t ctx;
592 int ret;
593
594 ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
Subrata Modakf0be8b02010-05-07 10:33:00 +0530595 if (ret == -1) {
subrata_modaka5b38e42008-08-20 11:28:51 +0000596 tst_resm(TBROK, "error triggering eventfd overflow");
597 return;
598 }
599
600 pollfd.fd = evfd;
601 pollfd.events = POLLIN;
602 pollfd.revents = 0;
603 ret = poll(&pollfd, 1, 10000);
Garrett Cooper80678cf2010-12-21 10:49:20 -0800604 if (ret == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800605 tst_resm(TBROK | TERRNO, "error getting evfd status with poll");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800606 else {
yaberauneyae70b30b2009-11-27 07:40:16 +0000607 if (pollfd.revents & POLLERR)
608 tst_resm(TPASS, "POLLERR occurred as expected");
609 else
610 tst_resm(TFAIL, "POLLERR did not occur");
subrata_modaka5b38e42008-08-20 11:28:51 +0000611 }
subrata_modaka5b38e42008-08-20 11:28:51 +0000612 cleanup_overflow(fd, ctx);
613}
614
subrata_modak56207ce2009-03-23 13:35:39 +0000615static void overflow_read_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000616{
617 uint64_t count;
618 io_context_t ctx;
619 int fd;
620 int ret;
621
622 ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
623 if (ret == -1) {
624 tst_resm(TBROK, "error triggering eventfd overflow");
625 return;
626 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000627
subrata_modak4bb656a2009-02-26 12:02:09 +0000628 ret = read(evfd, &count, sizeof(count));
Garrett Cooper80678cf2010-12-21 10:49:20 -0800629 if (ret == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800630 tst_resm(TBROK | TERRNO, "error reading eventfd");
Garrett Cooper80678cf2010-12-21 10:49:20 -0800631 else {
yaberauneyae70b30b2009-11-27 07:40:16 +0000632
633 if (count == UINT64_MAX)
634 tst_resm(TPASS, "overflow occurred as expected");
635 else
636 tst_resm(TFAIL, "overflow did not occur");
subrata_modaka5b38e42008-08-20 11:28:51 +0000637 }
subrata_modaka5b38e42008-08-20 11:28:51 +0000638 cleanup_overflow(fd, ctx);
639}
640#else
subrata_modak56207ce2009-03-23 13:35:39 +0000641static void overflow_select_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000642{
643 tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
644}
645
subrata_modak56207ce2009-03-23 13:35:39 +0000646static void overflow_poll_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000647{
648 tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
649}
650
subrata_modak56207ce2009-03-23 13:35:39 +0000651static void overflow_read_test(int evfd)
subrata_modaka5b38e42008-08-20 11:28:51 +0000652{
653 tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
654}
655#endif
656
subrata_modak56207ce2009-03-23 13:35:39 +0000657int main(int argc, char **argv)
subrata_modak66b84472008-08-11 09:56:25 +0000658{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200659 int lc;
660 char *msg;
subrata_modak66b84472008-08-11 09:56:25 +0000661 int fd;
662
Garrett Cooper80678cf2010-12-21 10:49:20 -0800663 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
subrata_modak66b84472008-08-11 09:56:25 +0000664 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modak66b84472008-08-11 09:56:25 +0000665
666 setup();
667
subrata_modak66b84472008-08-11 09:56:25 +0000668 for (lc = 0; TEST_LOOPING(lc); lc++) {
669 int ret;
670 uint64_t einit = 10;
671
subrata_modak66b84472008-08-11 09:56:25 +0000672 Tst_count = 0;
673
674 fd = myeventfd(einit, 0);
675 if (fd == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800676 tst_brkm(TBROK | TERRNO, CLEANUP,
677 "error creating eventfd");
subrata_modak66b84472008-08-11 09:56:25 +0000678
679 ret = fcntl(fd, F_SETFL, O_NONBLOCK);
680 if (ret == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800681 tst_brkm(TBROK | TERRNO, CLEANUP,
682 "error setting non-block mode");
subrata_modak66b84472008-08-11 09:56:25 +0000683
684 read_test(fd, einit);
685 read_eagain_test(fd);
686 write_test(fd);
687 write_eagain_test(fd);
688 read_einval_test(fd);
689 write_einval_test(fd);
690 write_einval2_test(fd);
691 readfd_set_test(fd);
692 readfd_not_set_test(fd);
693 writefd_set_test(fd);
694 writefd_not_set_test(fd);
695 child_inherit_test(fd);
subrata_modaka5b38e42008-08-20 11:28:51 +0000696 overflow_select_test(fd);
697 overflow_poll_test(fd);
698 overflow_read_test(fd);
subrata_modak66b84472008-08-11 09:56:25 +0000699
700 close(fd);
701 }
702
703 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800704
yaberauneyae70b30b2009-11-27 07:40:16 +0000705 tst_exit();
subrata_modak66b84472008-08-11 09:56:25 +0000706}
707
subrata_modak56207ce2009-03-23 13:35:39 +0000708static void setup(void)
subrata_modak66b84472008-08-11 09:56:25 +0000709{
Garrett Cooper2c282152010-12-16 00:55:50 -0800710
subrata_modak66b84472008-08-11 09:56:25 +0000711 tst_sig(FORK, DEF_HANDLER, cleanup);
712
713 if (tst_kvercmp(2, 6, 22) < 0)
Garrett Cooper53740502010-12-16 00:04:01 -0800714 tst_brkm(TCONF, NULL, "2.6.22 or greater kernel required");
subrata_modak66b84472008-08-11 09:56:25 +0000715
subrata_modak94e24dd2009-06-25 07:24:49 +0000716 tst_tmpdir();
Garrett Cooper80678cf2010-12-21 10:49:20 -0800717
subrata_modak66b84472008-08-11 09:56:25 +0000718 TEST_PAUSE;
719}
720
yaberauneya6aa27372009-12-06 19:54:10 +0000721static void cleanup(void)
subrata_modak66b84472008-08-11 09:56:25 +0000722{
subrata_modak66b84472008-08-11 09:56:25 +0000723 TEST_CLEANUP;
724
subrata_modak94e24dd2009-06-25 07:24:49 +0000725 tst_rmdir();
Garrett Cooper02d739b2010-12-21 10:44:52 -0800726}