Home | History | Annotate | Download | only in eventfd
      1 /*
      2  *   Copyright (c) 2008 Vijay Kumar B. <vijaykumar (at) 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 
     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  */
     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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 		tst_resm(TINFO | TERRNO, "io_setup error");
    514 		return -1;
    515 	}
    516 
    517 	*fd = open("testfile", O_RDWR | O_CREAT, 0644);
    518 	if (*fd == -1) {
    519 		tst_resm(TINFO | TERRNO, "open(testfile) failed");
    520 		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);
    531 
    532 	iocbap[0] = &iocb;
    533 	ret = io_submit(*ctx, 1, iocbap);
    534 	if (ret < 0) {
    535 		errno = -ret;
    536 		tst_resm(TINFO | TERRNO, "error submitting iocb");
    537 		goto err_close_file;
    538 	}
    539 
    540 	ret = io_getevents(*ctx, 1, 1, &ioev, NULL);
    541 	if (ret < 0) {
    542 		errno = -ret;
    543 		tst_resm(TINFO | TERRNO, "error waiting for event");
    544 		goto err_close_file;
    545 	}
    546 
    547 	return 0;
    548 
    549 err_close_file:
    550 	close(*fd);
    551 
    552 err_io_destroy:
    553 	io_destroy(*ctx);
    554 
    555 	return -1;
    556 }
    557 
    558 static void cleanup_overflow(int fd, io_context_t ctx)
    559 {
    560 	close(fd);
    561 	io_destroy(ctx);
    562 }
    563 
    564 static void overflow_select_test(int evfd)
    565 {
    566 	struct timeval timeout = { 10, 0 };
    567 	fd_set readfds;
    568 	int fd;
    569 	io_context_t ctx;
    570 	int ret;
    571 
    572 	ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
    573 	if (ret == -1) {
    574 		tst_resm(TBROK, "error triggering eventfd overflow");
    575 		return;
    576 	}
    577 
    578 	FD_ZERO(&readfds);
    579 	FD_SET(evfd, &readfds);
    580 	ret = select(evfd + 1, &readfds, NULL, NULL, &timeout);
    581 	if (ret == -1)
    582 		tst_resm(TBROK | TERRNO,
    583 			 "error getting evfd status with select");
    584 	else {
    585 		if (FD_ISSET(evfd, &readfds))
    586 			tst_resm(TPASS, "read fd set as expected");
    587 		else
    588 			tst_resm(TFAIL, "read fd not set");
    589 	}
    590 	cleanup_overflow(fd, ctx);
    591 }
    592 
    593 static void overflow_poll_test(int evfd)
    594 {
    595 	struct pollfd pollfd;
    596 	int fd;
    597 	io_context_t ctx;
    598 	int ret;
    599 
    600 	ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
    601 	if (ret == -1) {
    602 		tst_resm(TBROK, "error triggering eventfd overflow");
    603 		return;
    604 	}
    605 
    606 	pollfd.fd = evfd;
    607 	pollfd.events = POLLIN;
    608 	pollfd.revents = 0;
    609 	ret = poll(&pollfd, 1, 10000);
    610 	if (ret == -1)
    611 		tst_resm(TBROK | TERRNO, "error getting evfd status with poll");
    612 	else {
    613 		if (pollfd.revents & POLLERR)
    614 			tst_resm(TPASS, "POLLERR occurred as expected");
    615 		else
    616 			tst_resm(TFAIL, "POLLERR did not occur");
    617 	}
    618 	cleanup_overflow(fd, ctx);
    619 }
    620 
    621 static void overflow_read_test(int evfd)
    622 {
    623 	uint64_t count;
    624 	io_context_t ctx;
    625 	int fd;
    626 	int ret;
    627 
    628 	ret = trigger_eventfd_overflow(evfd, &fd, &ctx);
    629 	if (ret == -1) {
    630 		tst_resm(TBROK, "error triggering eventfd overflow");
    631 		return;
    632 	}
    633 
    634 	ret = read(evfd, &count, sizeof(count));
    635 	if (ret == -1)
    636 		tst_resm(TBROK | TERRNO, "error reading eventfd");
    637 	else {
    638 
    639 		if (count == UINT64_MAX)
    640 			tst_resm(TPASS, "overflow occurred as expected");
    641 		else
    642 			tst_resm(TFAIL, "overflow did not occur");
    643 	}
    644 	cleanup_overflow(fd, ctx);
    645 }
    646 #else
    647 static void overflow_select_test(int evfd)
    648 {
    649 	tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
    650 }
    651 
    652 static void overflow_poll_test(int evfd)
    653 {
    654 	tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
    655 }
    656 
    657 static void overflow_read_test(int evfd)
    658 {
    659 	tst_resm(TCONF, "eventfd support is not available in AIO subsystem");
    660 }
    661 #endif
    662 
    663 int main(int argc, char **argv)
    664 {
    665 	int lc;
    666 	int fd;
    667 
    668 	tst_parse_opts(argc, argv, NULL, NULL);
    669 
    670 	setup();
    671 
    672 	for (lc = 0; TEST_LOOPING(lc); lc++) {
    673 		int ret;
    674 		uint64_t einit = 10;
    675 
    676 		tst_count = 0;
    677 
    678 		fd = myeventfd(einit, 0);
    679 		if (fd == -1)
    680 			tst_brkm(TBROK | TERRNO, CLEANUP,
    681 				 "error creating eventfd");
    682 
    683 		ret = fcntl(fd, F_SETFL, O_NONBLOCK);
    684 		if (ret == -1)
    685 			tst_brkm(TBROK | TERRNO, CLEANUP,
    686 				 "error setting non-block mode");
    687 
    688 		read_test(fd, einit);
    689 		read_eagain_test(fd);
    690 		write_test(fd);
    691 		write_eagain_test(fd);
    692 		read_einval_test(fd);
    693 		write_einval_test(fd);
    694 		write_einval2_test(fd);
    695 		readfd_set_test(fd);
    696 		readfd_not_set_test(fd);
    697 		writefd_set_test(fd);
    698 		writefd_not_set_test(fd);
    699 		child_inherit_test(fd);
    700 		overflow_select_test(fd);
    701 		overflow_poll_test(fd);
    702 		overflow_read_test(fd);
    703 
    704 		close(fd);
    705 	}
    706 
    707 	cleanup();
    708 
    709 	tst_exit();
    710 }
    711 
    712 static void setup(void)
    713 {
    714 
    715 	tst_sig(FORK, DEF_HANDLER, cleanup);
    716 
    717 	if (tst_kvercmp(2, 6, 22) < 0)
    718 		tst_brkm(TCONF, NULL, "2.6.22 or greater kernel required");
    719 
    720 	tst_tmpdir();
    721 
    722 	TEST_PAUSE;
    723 }
    724 
    725 static void cleanup(void)
    726 {
    727 	tst_rmdir();
    728 }
    729 
    730 #else
    731 int main(void)
    732 {
    733 	tst_brkm(TCONF, NULL, "test requires libaio and it's development packages");
    734 }
    735 #endif
    736