• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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
21  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
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.
37  *
38  * History
39  *	07/2008 Vijay Kumar
40  *		Initial Version.
41  *
42  * Restrictions
43  *	None
44  */
45 
46 #include "config.h"
47 
48 #include <sys/types.h>
49 #include <sys/select.h>
50 #include <sys/wait.h>
51 #include <errno.h>
52 #include <fcntl.h>
53 #include <inttypes.h>
54 #include <poll.h>
55 #include <signal.h>
56 #include <stdint.h>
57 #include <string.h>
58 #include <unistd.h>
59 
60 #include "test.h"
61 #define CLEANUP cleanup
62 #include "lapi/syscalls.h"
63 
64 TCID_DEFINE(eventfd01);
65 int TST_TOTAL = 15;
66 
67 #ifdef HAVE_LIBAIO
68 #include <libaio.h>
69 
70 static void setup(void);
71 
myeventfd(unsigned int initval,int flags)72 static int myeventfd(unsigned int initval, int flags)
73 {
74 	/* eventfd2 uses FLAGS but eventfd doesn't take FLAGS. */
75 	return ltp_syscall(__NR_eventfd, initval);
76 }
77 
78 /*
79  * clear_counter() - clears the counter by performing a dummy read
80  * @fd: the eventfd
81  *
82  * RETURNS:
83  * 0 on success, and -1 on failure
84  */
clear_counter(int fd)85 static int clear_counter(int fd)
86 {
87 	uint64_t dummy;
88 	int ret;
89 
90 	ret = read(fd, &dummy, sizeof(dummy));
91 	if (ret == -1) {
92 		if (errno != EAGAIN) {
93 			tst_resm(TINFO | TERRNO, "error clearing counter");
94 			return -1;
95 		}
96 	}
97 
98 	return 0;
99 }
100 
101 /*
102  * set_counter() - sets the count to specified value
103  * @fd: the eventfd
104  * @val: the value to be set
105  *
106  * Clears the counter and sets the counter to @val.
107  *
108  * RETURNS:
109  * 0 on success, -1 on failure
110  */
set_counter(int fd,uint64_t val)111 static int set_counter(int fd, uint64_t val)
112 {
113 	int ret;
114 
115 	ret = clear_counter(fd);
116 	if (ret == -1)
117 		return -1;
118 
119 	ret = write(fd, &val, sizeof(val));
120 	if (ret == -1) {
121 		tst_resm(TINFO | TERRNO, "error setting counter value");
122 		return -1;
123 	}
124 
125 	return 0;
126 }
127 
128 /*
129  * Test whether the current value of the counter matches @required.
130  */
read_test(int fd,uint64_t required)131 static void read_test(int fd, uint64_t required)
132 {
133 	int ret;
134 	uint64_t val;
135 
136 	ret = read(fd, &val, sizeof(val));
137 	if (ret == -1) {
138 		tst_resm(TBROK | TERRNO, "error reading eventfd");
139 		return;
140 	}
141 
142 	if (val == required)
143 		tst_resm(TPASS, "counter value matches required");
144 	else
145 		tst_resm(TFAIL, "counter value mismatch: "
146 			 "required: %" PRIu64 ", got: %" PRIu64, required, val);
147 }
148 
149 /*
150  * Test whether read returns with error EAGAIN when counter is at 0.
151  */
read_eagain_test(int fd)152 static void read_eagain_test(int fd)
153 {
154 	int ret;
155 	uint64_t val;
156 
157 	ret = clear_counter(fd);
158 	if (ret == -1) {
159 		tst_resm(TBROK, "error clearing counter");
160 		return;
161 	}
162 
163 	ret = read(fd, &val, sizeof(val));
164 	if (ret == -1) {
165 		if (errno == EAGAIN)
166 			tst_resm(TPASS, "read failed with EAGAIN as expected");
167 		else
168 			tst_resm(TFAIL | TERRNO, "read failed (wanted EAGAIN)");
169 	} else
170 		tst_resm(TFAIL, "read returned with %d", ret);
171 }
172 
173 /*
174  * Test whether writing to counter works.
175  */
write_test(int fd)176 static void write_test(int fd)
177 {
178 	int ret;
179 	uint64_t val;
180 
181 	val = 12;
182 
183 	ret = set_counter(fd, val);
184 	if (ret == -1) {
185 		tst_resm(TBROK, "error setting counter value to %" PRIu64, val);
186 		return;
187 	}
188 
189 	read_test(fd, val);
190 }
191 
192 /*
193  * Test whether write returns with error EAGAIN when counter is at
194  * (UINT64_MAX - 1).
195  */
write_eagain_test(int fd)196 static void write_eagain_test(int fd)
197 {
198 	int ret;
199 	uint64_t val;
200 
201 	ret = set_counter(fd, UINT64_MAX - 1);
202 	if (ret == -1) {
203 		tst_resm(TBROK, "error setting counter value to UINT64_MAX-1");
204 		return;
205 	}
206 
207 	val = 1;
208 	ret = write(fd, &val, sizeof(val));
209 	if (ret == -1) {
210 		if (errno == EAGAIN)
211 			tst_resm(TPASS, "write failed with EAGAIN as expected");
212 		else
213 			tst_resm(TFAIL, "write failed (wanted EAGAIN)");
214 	} else
215 		tst_resm(TFAIL, "write returned with %d", ret);
216 }
217 
218 /*
219  * Test whether read returns with error EINVAL, if buffer size is less
220  * than 8 bytes.
221  */
read_einval_test(int fd)222 static void read_einval_test(int fd)
223 {
224 	uint32_t invalid;
225 	int ret;
226 
227 	ret = read(fd, &invalid, sizeof(invalid));
228 	if (ret == -1) {
229 		if (errno == EINVAL)
230 			tst_resm(TPASS, "read failed with EINVAL as expected");
231 		else
232 			tst_resm(TFAIL | TERRNO, "read failed (wanted EINVAL)");
233 	} else
234 		tst_resm(TFAIL, "read returned with %d", ret);
235 }
236 
237 /*
238  * Test whether write returns with error EINVAL, if buffer size is
239  * less than 8 bytes.
240  */
write_einval_test(int fd)241 static void write_einval_test(int fd)
242 {
243 	uint32_t invalid;
244 	int ret;
245 
246 	ret = write(fd, &invalid, sizeof(invalid));
247 	if (ret == -1) {
248 		if (errno == EINVAL)
249 			tst_resm(TPASS, "write failed with EINVAL as expected");
250 		else
251 			tst_resm(TFAIL | TERRNO,
252 				 "write failed (wanted EINVAL)");
253 	} else
254 		tst_resm(TFAIL, "write returned with %d", ret);
255 }
256 
257 /*
258  * Test wheter write returns with error EINVAL, when the written value
259  * is 0xFFFFFFFFFFFFFFFF.
260  */
write_einval2_test(int fd)261 static void write_einval2_test(int fd)
262 {
263 	int ret;
264 	uint64_t val;
265 
266 	ret = clear_counter(fd);
267 	if (ret == -1) {
268 		tst_resm(TBROK, "error clearing counter");
269 		return;
270 	}
271 
272 	val = 0xffffffffffffffffLL;
273 	ret = write(fd, &val, sizeof(val));
274 	if (ret == -1) {
275 		if (errno == EINVAL)
276 			tst_resm(TPASS, "write failed with EINVAL as expected");
277 		else
278 			tst_resm(TFAIL | TERRNO,
279 				 "write failed (wanted EINVAL)");
280 	} else {
281 		tst_resm(TFAIL, "write returned with %d", ret);
282 	}
283 }
284 
285 /*
286  * Test whether readfd is set by select when counter value is
287  * non-zero.
288  */
readfd_set_test(int fd)289 static void readfd_set_test(int fd)
290 {
291 	int ret;
292 	fd_set readfds;
293 	struct timeval timeout = { 0, 0 };
294 	uint64_t non_zero = 10;
295 
296 	FD_ZERO(&readfds);
297 	FD_SET(fd, &readfds);
298 
299 	ret = set_counter(fd, non_zero);
300 	if (ret == -1) {
301 		tst_resm(TBROK, "error setting counter value to %" PRIu64,
302 			 non_zero);
303 		return;
304 	}
305 
306 	ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
307 	if (ret == -1) {
308 		/* EINTR cannot occur, since we don't block. */
309 		tst_resm(TBROK | TERRNO, "select() failed");
310 		return;
311 	}
312 
313 	if (FD_ISSET(fd, &readfds))
314 		tst_resm(TPASS, "fd is set in readfds");
315 	else
316 		tst_resm(TFAIL, "fd is not set in readfds");
317 }
318 
319 /*
320  * Test whether readfd is not set by select when counter value is
321  * zero.
322  */
readfd_not_set_test(int fd)323 static void readfd_not_set_test(int fd)
324 {
325 	int ret;
326 	fd_set readfds;
327 	struct timeval timeout = { 0, 0 };
328 
329 	FD_ZERO(&readfds);
330 	FD_SET(fd, &readfds);
331 
332 	ret = clear_counter(fd);
333 	if (ret == -1) {
334 		tst_resm(TBROK, "error clearing counter");
335 		return;
336 	}
337 
338 	ret = select(fd + 1, &readfds, NULL, NULL, &timeout);
339 	if (ret == -1) {
340 		/* EINTR cannot occur, since we don't block. */
341 		tst_resm(TBROK | TERRNO, "select() failed");
342 		return;
343 	}
344 
345 	if (!FD_ISSET(fd, &readfds))
346 		tst_resm(TPASS, "fd is not set in readfds");
347 	else
348 		tst_resm(TFAIL, "fd is set in readfds");
349 }
350 
351 /*
352  * Test whether writefd is set by select when counter value is not the
353  * maximum counter value.
354  */
writefd_set_test(int fd)355 static void writefd_set_test(int fd)
356 {
357 	int ret;
358 	fd_set writefds;
359 	struct timeval timeout = { 0, 0 };
360 	uint64_t non_max = 10;
361 
362 	FD_ZERO(&writefds);
363 	FD_SET(fd, &writefds);
364 
365 	ret = set_counter(fd, non_max);
366 	if (ret == -1) {
367 		tst_resm(TBROK, "error setting counter value to %" PRIu64,
368 			 non_max);
369 		return;
370 	}
371 
372 	ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
373 	if (ret == -1) {
374 		/* EINTR cannot occur, since we don't block. */
375 		tst_resm(TBROK | TERRNO, "select: error getting fd status");
376 		return;
377 	}
378 
379 	if (FD_ISSET(fd, &writefds))
380 		tst_resm(TPASS, "fd is set in writefds");
381 	else
382 		tst_resm(TFAIL, "fd is not set in writefds");
383 }
384 
385 /*
386  * Test whether writefd is not set by select when counter value is at
387  * (UINT64_MAX - 1).
388  */
writefd_not_set_test(int fd)389 static void writefd_not_set_test(int fd)
390 {
391 	int ret;
392 	fd_set writefds;
393 	struct timeval timeout = { 0, 0 };
394 
395 	FD_ZERO(&writefds);
396 	FD_SET(fd, &writefds);
397 
398 	ret = set_counter(fd, UINT64_MAX - 1);
399 	if (ret == -1) {
400 		tst_resm(TBROK, "error setting counter value to UINT64_MAX-1");
401 		return;
402 	}
403 
404 	ret = select(fd + 1, NULL, &writefds, NULL, &timeout);
405 	if (ret == -1) {
406 		/* EINTR cannot occur, since we don't block. */
407 		tst_resm(TBROK | TERRNO, "select: error getting fd status");
408 		return;
409 	}
410 
411 	if (!FD_ISSET(fd, &writefds))
412 		tst_resm(TPASS, "fd is not set in writefds");
413 	else
414 		tst_resm(TFAIL, "fd is set in writefds");
415 }
416 
417 /*
418  * Test whether counter update in child is reflected in the parent.
419  */
child_inherit_test(int fd)420 static void child_inherit_test(int fd)
421 {
422 	uint64_t val;
423 	pid_t cpid;
424 	int ret;
425 	int status;
426 	uint64_t to_parent = 0xdeadbeef;
427 	uint64_t dummy;
428 
429 	cpid = fork();
430 	if (cpid == -1)
431 		tst_resm(TBROK | TERRNO, "fork failed");
432 	else if (cpid != 0) {
433 		ret = wait(&status);
434 		if (ret == -1) {
435 			tst_resm(TBROK, "error getting child exit status");
436 			return;
437 		}
438 
439 		if (WEXITSTATUS(status) == 1) {
440 			tst_resm(TBROK, "counter value write not "
441 				 "successful in child");
442 			return;
443 		}
444 
445 		ret = read(fd, &val, sizeof(val));
446 		if (ret == -1) {
447 			tst_resm(TBROK | TERRNO, "error reading eventfd");
448 			return;
449 		}
450 
451 		if (val == to_parent)
452 			tst_resm(TPASS, "counter value write from "
453 				 "child successful");
454 		else
455 			tst_resm(TFAIL, "counter value write in child "
456 				 "failed");
457 	} else {
458 		/* Child */
459 		ret = read(fd, &dummy, sizeof(dummy));
460 		if (ret == -1 && errno != EAGAIN) {
461 			tst_resm(TWARN | TERRNO, "error clearing counter");
462 			exit(1);
463 		}
464 
465 		ret = write(fd, &to_parent, sizeof(to_parent));
466 		if (ret == -1) {
467 			tst_resm(TWARN | TERRNO, "error writing eventfd");
468 			exit(1);
469 		}
470 
471 		exit(0);
472 	}
473 }
474 
475 #ifdef HAVE_IO_SET_EVENTFD
476 /*
477  * Test whether counter overflow is detected and handled correctly.
478  *
479  * It is not possible to directly overflow the counter using the
480  * write() syscall. Overflows occur when the counter is incremented
481  * from kernel space, in an irq context, when it is not possible to
482  * block the calling thread of execution.
483  *
484  * The AIO subsystem internally uses eventfd mechanism for
485  * notification of completion of read or write requests. In this test
486  * we trigger a counter overflow, by setting the counter value to the
487  * max possible value initially. When the AIO subsystem notifies
488  * through the eventfd counter, the counter overflows.
489  *
490  * NOTE: If the the counter starts from an initial value of 0, it will
491  * take decades for an overflow to occur. But since we set the initial
492  * value to the max possible counter value, we are able to cause it to
493  * overflow with a single increment.
494  *
495  * When the counter overflows, the following are tested
496  *   1. Check whether POLLERR event occurs in poll() for the eventfd.
497  *   2. Check whether readfd_set/writefd_set is set in select() for the
498         eventfd.
499  *   3. The counter value is UINT64_MAX.
500  */
trigger_eventfd_overflow(int evfd,int * fd,io_context_t * ctx)501 static int trigger_eventfd_overflow(int evfd, int *fd, io_context_t * ctx)
502 {
503 	int ret;
504 	struct iocb iocb;
505 	struct iocb *iocbap[1];
506 	struct io_event ioev;
507 	static char buf[4 * 1024];
508 
509 	*ctx = 0;
510 	ret = io_setup(16, ctx);
511 	if (ret < 0) {
512 		errno = -ret;
513 		if (errno == ENOSYS) {
514 			tst_brkm(TCONF | TERRNO, cleanup,
515 				 "io_setup(): AIO not supported by kernel");
516 		}
517 
518 		tst_resm(TINFO | TERRNO, "io_setup error");
519 		return -1;
520 	}
521 
522 	*fd = open("testfile", O_RDWR | O_CREAT, 0644);
523 	if (*fd == -1) {
524 		tst_resm(TINFO | TERRNO, "open(testfile) failed");
525 		goto err_io_destroy;
526 	}
527 
528 	ret = set_counter(evfd, UINT64_MAX - 1);
529 	if (ret == -1) {
530 		tst_resm(TINFO, "error setting counter to UINT64_MAX-1");
531 		goto err_close_file;
532 	}
533 
534 	io_prep_pwrite(&iocb, *fd, buf, sizeof(buf), 0);
535 	io_set_eventfd(&iocb, evfd);
536 
537 	iocbap[0] = &iocb;
538 	ret = io_submit(*ctx, 1, iocbap);
539 	if (ret < 0) {
540 		errno = -ret;
541 		tst_resm(TINFO | TERRNO, "error submitting iocb");
542 		goto err_close_file;
543 	}
544 
545 	ret = io_getevents(*ctx, 1, 1, &ioev, NULL);
546 	if (ret < 0) {
547 		errno = -ret;
548 		tst_resm(TINFO | TERRNO, "error waiting for event");
549 		goto err_close_file;
550 	}
551 
552 	return 0;
553 
554 err_close_file:
555 	close(*fd);
556 
557 err_io_destroy:
558 	io_destroy(*ctx);
559 
560 	return -1;
561 }
562 
cleanup_overflow(int fd,io_context_t ctx)563 static void cleanup_overflow(int fd, io_context_t ctx)
564 {
565 	close(fd);
566 	io_destroy(ctx);
567 }
568 
overflow_select_test(int evfd)569 static void overflow_select_test(int evfd)
570 {
571 	struct timeval timeout = { 10, 0 };
572 	fd_set readfds;
573 	int fd;
574 	io_context_t ctx;
575 	int ret;
576 
577 	ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
578 	if (ret == -1) {
579 		tst_resm(TBROK, "error triggering eventfd overflow");
580 		return;
581 	}
582 
583 	FD_ZERO(&readfds);
584 	FD_SET(evfd, &readfds);
585 	ret = select(evfd + 1, &readfds, NULL, NULL, &timeout);
586 	if (ret == -1)
587 		tst_resm(TBROK | TERRNO,
588 			 "error getting evfd status with select");
589 	else {
590 		if (FD_ISSET(evfd, &readfds))
591 			tst_resm(TPASS, "read fd set as expected");
592 		else
593 			tst_resm(TFAIL, "read fd not set");
594 	}
595 	cleanup_overflow(fd, ctx);
596 }
597 
overflow_poll_test(int evfd)598 static void overflow_poll_test(int evfd)
599 {
600 	struct pollfd pollfd;
601 	int fd;
602 	io_context_t ctx;
603 	int ret;
604 
605 	ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
606 	if (ret == -1) {
607 		tst_resm(TBROK, "error triggering eventfd overflow");
608 		return;
609 	}
610 
611 	pollfd.fd = evfd;
612 	pollfd.events = POLLIN;
613 	pollfd.revents = 0;
614 	ret = poll(&pollfd, 1, 10000);
615 	if (ret == -1)
616 		tst_resm(TBROK | TERRNO, "error getting evfd status with poll");
617 	else {
618 		if (pollfd.revents & POLLERR)
619 			tst_resm(TPASS, "POLLERR occurred as expected");
620 		else
621 			tst_resm(TFAIL, "POLLERR did not occur");
622 	}
623 	cleanup_overflow(fd, ctx);
624 }
625 
overflow_read_test(int evfd)626 static void overflow_read_test(int evfd)
627 {
628 	uint64_t count;
629 	io_context_t ctx;
630 	int fd;
631 	int ret;
632 
633 	ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
634 	if (ret == -1) {
635 		tst_resm(TBROK, "error triggering eventfd overflow");
636 		return;
637 	}
638 
639 	ret = read(evfd, &count, sizeof(count));
640 	if (ret == -1)
641 		tst_resm(TBROK | TERRNO, "error reading eventfd");
642 	else {
643 
644 		if (count == UINT64_MAX)
645 			tst_resm(TPASS, "overflow occurred as expected");
646 		else
647 			tst_resm(TFAIL, "overflow did not occur");
648 	}
649 	cleanup_overflow(fd, ctx);
650 }
651 #else
overflow_select_test(int evfd)652 static void overflow_select_test(int evfd)
653 {
654 	tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
655 }
656 
overflow_poll_test(int evfd)657 static void overflow_poll_test(int evfd)
658 {
659 	tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
660 }
661 
overflow_read_test(int evfd)662 static void overflow_read_test(int evfd)
663 {
664 	tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
665 }
666 #endif
667 
main(int argc,char ** argv)668 int main(int argc, char **argv)
669 {
670 	int lc;
671 	int fd;
672 
673 	tst_parse_opts(argc, argv, NULL, NULL);
674 
675 	setup();
676 
677 	for (lc = 0; TEST_LOOPING(lc); lc++) {
678 		int ret;
679 		uint64_t einit = 10;
680 
681 		tst_count = 0;
682 
683 		fd = myeventfd(einit, 0);
684 		if (fd == -1)
685 			tst_brkm(TBROK | TERRNO, CLEANUP,
686 				 "error creating eventfd");
687 
688 		ret = fcntl(fd, F_SETFL, O_NONBLOCK);
689 		if (ret == -1)
690 			tst_brkm(TBROK | TERRNO, CLEANUP,
691 				 "error setting non-block mode");
692 
693 		read_test(fd, einit);
694 		read_eagain_test(fd);
695 		write_test(fd);
696 		write_eagain_test(fd);
697 		read_einval_test(fd);
698 		write_einval_test(fd);
699 		write_einval2_test(fd);
700 		readfd_set_test(fd);
701 		readfd_not_set_test(fd);
702 		writefd_set_test(fd);
703 		writefd_not_set_test(fd);
704 		child_inherit_test(fd);
705 		overflow_select_test(fd);
706 		overflow_poll_test(fd);
707 		overflow_read_test(fd);
708 
709 		close(fd);
710 	}
711 
712 	cleanup();
713 
714 	tst_exit();
715 }
716 
setup(void)717 static void setup(void)
718 {
719 
720 	tst_sig(FORK, DEF_HANDLER, cleanup);
721 
722 	if (tst_kvercmp(2, 6, 22) < 0)
723 		tst_brkm(TCONF, NULL, "2.6.22 or greater kernel required");
724 
725 	tst_tmpdir();
726 
727 	TEST_PAUSE;
728 }
729 
cleanup(void)730 static void cleanup(void)
731 {
732 	tst_rmdir();
733 }
734 
735 #else
main(void)736 int main(void)
737 {
738 	tst_brkm(TCONF, NULL, "test requires libaio and it's development packages");
739 }
740 #endif
741