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