1 /*- 2 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 3 * Authors: Doug Rabson <dfr@rabson.org> 4 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/file.h> 30 #include <sys/time.h> 31 #ifdef __FreeBSD__ 32 #include <sys/mount.h> 33 #endif 34 #include <sys/stat.h> 35 #include <sys/wait.h> 36 37 #include <err.h> 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <pthread.h> 41 #include <signal.h> 42 #include <stdint.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <unistd.h> 47 48 #ifdef __FreeBSD__ 49 #if __FreeBSD_version >= 800028 50 #define HAVE_SYSID 51 #endif 52 #include <sys/cdefs.h> 53 #else 54 #ifndef nitems 55 #define nitems(x) (sizeof((x)) / sizeof((x)[0])) 56 #endif 57 58 #ifndef __unused 59 #ifdef __GNUC__ 60 #define __unused __attribute__((__unused__)) 61 #else 62 #define __unused 63 #endif 64 #endif 65 #endif 66 67 static int verbose = 0; 68 69 static int 70 make_file(const char *pathname, off_t sz) 71 { 72 struct stat st; 73 const char *template = "/flocktempXXXXXX"; 74 size_t len; 75 char *filename; 76 int fd; 77 78 if (stat(pathname, &st) == 0) { 79 if (S_ISREG(st.st_mode)) { 80 fd = open(pathname, O_RDWR); 81 if (fd < 0) 82 err(1, "open(%s)", pathname); 83 if (ftruncate(fd, sz) < 0) 84 err(1, "ftruncate"); 85 return (fd); 86 } 87 } 88 89 len = strlen(pathname) + strlen(template) + 1; 90 filename = malloc(len); 91 strcpy(filename, pathname); 92 strcat(filename, template); 93 fd = mkstemp(filename); 94 if (fd < 0) 95 err(1, "mkstemp"); 96 if (ftruncate(fd, sz) < 0) 97 err(1, "ftruncate"); 98 if (unlink(filename) < 0) 99 err(1, "unlink"); 100 free(filename); 101 102 return (fd); 103 } 104 105 static void 106 ignore_alarm(int __unused sig) 107 { 108 } 109 110 static int 111 safe_waitpid(pid_t pid) 112 { 113 int save_errno; 114 int status; 115 116 save_errno = errno; 117 errno = 0; 118 while (waitpid(pid, &status, 0) != pid) { 119 if (errno == EINTR) 120 continue; 121 err(1, "waitpid"); 122 } 123 errno = save_errno; 124 125 return (status); 126 } 127 128 #define FAIL(test) \ 129 do { \ 130 if (test) { \ 131 printf("FAIL (%s)\n", #test); \ 132 return -1; \ 133 } \ 134 } while (0) 135 136 #define SUCCEED \ 137 do { printf("SUCCEED\n"); return 0; } while (0) 138 139 /* 140 * Test 1 - F_GETLK on unlocked region 141 * 142 * If no lock is found that would prevent this lock from being 143 * created, the structure is left unchanged by this function call 144 * except for the lock type which is set to F_UNLCK. 145 */ 146 static int 147 test1(int fd, __unused int argc, const __unused char **argv) 148 { 149 struct flock fl1, fl2; 150 151 memset(&fl1, 1, sizeof(fl1)); 152 fl1.l_type = F_WRLCK; 153 fl1.l_whence = SEEK_SET; 154 fl2 = fl1; 155 156 if (fcntl(fd, F_GETLK, &fl1) < 0) 157 err(1, "F_GETLK"); 158 159 printf("1 - F_GETLK on unlocked region: "); 160 FAIL(fl1.l_start != fl2.l_start); 161 FAIL(fl1.l_len != fl2.l_len); 162 FAIL(fl1.l_pid != fl2.l_pid); 163 FAIL(fl1.l_type != F_UNLCK); 164 FAIL(fl1.l_whence != fl2.l_whence); 165 #ifdef HAVE_SYSID 166 FAIL(fl1.l_sysid != fl2.l_sysid); 167 #endif 168 169 SUCCEED; 170 } 171 172 /* 173 * Test 2 - F_SETLK on locked region 174 * 175 * If a shared or exclusive lock cannot be set, fcntl returns 176 * immediately with EACCES or EAGAIN. 177 */ 178 static int 179 test2(int fd, __unused int argc, const __unused char **argv) 180 { 181 /* 182 * We create a child process to hold the lock which we will 183 * test. We use a pipe to communicate with the child. 184 */ 185 int pid; 186 int pfd[2]; 187 struct flock fl; 188 char ch; 189 int res; 190 191 if (pipe(pfd) < 0) 192 err(1, "pipe"); 193 194 fl.l_start = 0; 195 fl.l_len = 0; 196 fl.l_type = F_WRLCK; 197 fl.l_whence = SEEK_SET; 198 199 pid = fork(); 200 if (pid < 0) 201 err(1, "fork"); 202 203 if (pid == 0) { 204 /* 205 * We are the child. We set a write lock and then 206 * write one byte back to the parent to tell it. The 207 * parent will kill us when its done. 208 */ 209 if (fcntl(fd, F_SETLK, &fl) < 0) 210 err(1, "F_SETLK (child)"); 211 if (write(pfd[1], "a", 1) < 0) 212 err(1, "writing to pipe (child)"); 213 pause(); 214 exit(0); 215 } 216 217 /* 218 * Wait until the child has set its lock and then perform the 219 * test. 220 */ 221 if (read(pfd[0], &ch, 1) != 1) 222 err(1, "reading from pipe (child)"); 223 224 /* 225 * fcntl should return -1 with errno set to either EACCES or 226 * EAGAIN. 227 */ 228 printf("2 - F_SETLK on locked region: "); 229 res = fcntl(fd, F_SETLK, &fl); 230 kill(pid, SIGTERM); 231 safe_waitpid(pid); 232 close(pfd[0]); 233 close(pfd[1]); 234 FAIL(res == 0); 235 FAIL(errno != EACCES && errno != EAGAIN); 236 237 SUCCEED; 238 } 239 240 /* 241 * Test 3 - F_SETLKW on locked region 242 * 243 * If a shared or exclusive lock is blocked by other locks, the 244 * process waits until the request can be satisfied. 245 * 246 * XXX this test hangs on FreeBSD NFS filesystems due to limitations 247 * in FreeBSD's client (and server) lockd implementation. 248 */ 249 static int 250 test3(int fd, __unused int argc, const __unused char **argv) 251 { 252 /* 253 * We create a child process to hold the lock which we will 254 * test. We use a pipe to communicate with the child. 255 */ 256 int pid; 257 int pfd[2]; 258 struct flock fl; 259 char ch; 260 int res; 261 262 if (pipe(pfd) < 0) 263 err(1, "pipe"); 264 265 fl.l_start = 0; 266 fl.l_len = 0; 267 fl.l_type = F_WRLCK; 268 fl.l_whence = SEEK_SET; 269 270 pid = fork(); 271 if (pid < 0) 272 err(1, "fork"); 273 274 if (pid == 0) { 275 /* 276 * We are the child. We set a write lock and then 277 * write one byte back to the parent to tell it. The 278 * parent will kill us when its done. 279 */ 280 if (fcntl(fd, F_SETLK, &fl) < 0) 281 err(1, "F_SETLK (child)"); 282 if (write(pfd[1], "a", 1) < 0) 283 err(1, "writing to pipe (child)"); 284 pause(); 285 exit(0); 286 } 287 288 /* 289 * Wait until the child has set its lock and then perform the 290 * test. 291 */ 292 if (read(pfd[0], &ch, 1) != 1) 293 err(1, "reading from pipe (child)"); 294 295 /* 296 * fcntl should wait until the alarm and then return -1 with 297 * errno set to EINTR. 298 */ 299 printf("3 - F_SETLKW on locked region: "); 300 301 alarm(1); 302 303 res = fcntl(fd, F_SETLKW, &fl); 304 kill(pid, SIGTERM); 305 safe_waitpid(pid); 306 close(pfd[0]); 307 close(pfd[1]); 308 FAIL(res == 0); 309 FAIL(errno != EINTR); 310 311 SUCCEED; 312 } 313 314 /* 315 * Test 4 - F_GETLK on locked region 316 * 317 * Get the first lock that blocks the lock. 318 */ 319 static int 320 test4(int fd, __unused int argc, const __unused char **argv) 321 { 322 /* 323 * We create a child process to hold the lock which we will 324 * test. We use a pipe to communicate with the child. 325 */ 326 int pid; 327 int pfd[2]; 328 struct flock fl; 329 char ch; 330 331 if (pipe(pfd) < 0) 332 err(1, "pipe"); 333 334 fl.l_start = 0; 335 fl.l_len = 99; 336 fl.l_type = F_WRLCK; 337 fl.l_whence = SEEK_SET; 338 339 pid = fork(); 340 if (pid < 0) 341 err(1, "fork"); 342 343 if (pid == 0) { 344 /* 345 * We are the child. We set a write lock and then 346 * write one byte back to the parent to tell it. The 347 * parent will kill us when its done. 348 */ 349 if (fcntl(fd, F_SETLK, &fl) < 0) 350 err(1, "F_SETLK (child)"); 351 if (write(pfd[1], "a", 1) < 0) 352 err(1, "writing to pipe (child)"); 353 pause(); 354 exit(0); 355 } 356 357 /* 358 * Wait until the child has set its lock and then perform the 359 * test. 360 */ 361 if (read(pfd[0], &ch, 1) != 1) 362 err(1, "reading from pipe (child)"); 363 364 /* 365 * fcntl should return a lock structure reflecting the lock we 366 * made in the child process. 367 */ 368 if (fcntl(fd, F_GETLK, &fl) < 0) 369 err(1, "F_GETLK"); 370 371 printf("4 - F_GETLK on locked region: "); 372 FAIL(fl.l_start != 0); 373 FAIL(fl.l_len != 99); 374 FAIL(fl.l_type != F_WRLCK); 375 FAIL(fl.l_pid != pid); 376 #ifdef HAVE_SYSID 377 FAIL(fl.l_sysid != 0); 378 #endif 379 380 kill(pid, SIGTERM); 381 safe_waitpid(pid); 382 close(pfd[0]); 383 close(pfd[1]); 384 385 SUCCEED; 386 } 387 388 /* 389 * Test 5 - F_SETLKW simple deadlock 390 * 391 * If a blocking shared lock request would cause a deadlock (i.e. the 392 * lock request is blocked by a process which is itself blocked on a 393 * lock currently owned by the process making the new request), 394 * EDEADLK is returned. 395 */ 396 static int 397 test5(int fd, __unused int argc, const __unused char **argv) 398 { 399 /* 400 * We create a child process to hold the lock which we will 401 * test. Because our test relies on the child process being 402 * blocked on the parent's lock, we can't easily use a pipe to 403 * synchronize so we just sleep in the parent to given the 404 * child a chance to setup. 405 * 406 * To create the deadlock condition, we arrange for the parent 407 * to lock the first byte of the file and the child to lock 408 * the second byte. After locking the second byte, the child 409 * will attempt to lock the first byte of the file, and 410 * block. The parent will then attempt to lock the second byte 411 * (owned by the child) which should cause deadlock. 412 */ 413 int pid; 414 struct flock fl; 415 int res; 416 417 /* 418 * Lock the first byte in the parent. 419 */ 420 fl.l_start = 0; 421 fl.l_len = 1; 422 fl.l_type = F_WRLCK; 423 fl.l_whence = SEEK_SET; 424 if (fcntl(fd, F_SETLK, &fl) < 0) 425 err(1, "F_SETLK 1 (parent)"); 426 427 pid = fork(); 428 if (pid < 0) 429 err(1, "fork"); 430 431 if (pid == 0) { 432 /* 433 * Lock the second byte in the child and then block on 434 * the parent's lock. 435 */ 436 fl.l_start = 1; 437 if (fcntl(fd, F_SETLK, &fl) < 0) 438 err(1, "F_SETLK (child)"); 439 fl.l_start = 0; 440 if (fcntl(fd, F_SETLKW, &fl) < 0) 441 err(1, "F_SETLKW (child)"); 442 exit(0); 443 } 444 445 /* 446 * Wait until the child has set its lock and then perform the 447 * test. 448 */ 449 sleep(1); 450 451 /* 452 * fcntl should immediately return -1 with errno set to 453 * EDEADLK. If the alarm fires, we failed to detect the 454 * deadlock. 455 */ 456 alarm(1); 457 printf("5 - F_SETLKW simple deadlock: "); 458 459 fl.l_start = 1; 460 res = fcntl(fd, F_SETLKW, &fl); 461 kill(pid, SIGTERM); 462 safe_waitpid(pid); 463 464 FAIL(res == 0); 465 FAIL(errno != EDEADLK); 466 467 fl.l_start = 0; 468 fl.l_len = 0; 469 fl.l_type = F_UNLCK; 470 if (fcntl(fd, F_SETLK, &fl) < 0) 471 err(1, "F_UNLCK"); 472 473 /* 474 * Cancel the alarm to avoid confusing later tests. 475 */ 476 alarm(0); 477 478 SUCCEED; 479 } 480 481 /* 482 * Test 6 - F_SETLKW complex deadlock. 483 * 484 * This test involves three process, P, C1 and C2. We set things up so 485 * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We 486 * also block C2 by attempting to lock byte zero. Lastly, P attempts 487 * to lock a range including byte 1 and 2. This represents a deadlock 488 * (due to C2's blocking attempt to lock byte zero). 489 */ 490 static int 491 test6(int fd, __unused int argc, const __unused char **argv) 492 { 493 /* 494 * Because our test relies on the child process being blocked 495 * on the parent's lock, we can't easily use a pipe to 496 * synchronize so we just sleep in the parent to given the 497 * children a chance to setup. 498 */ 499 int pid1, pid2; 500 struct flock fl; 501 int res; 502 503 /* 504 * Lock the first byte in the parent. 505 */ 506 fl.l_start = 0; 507 fl.l_len = 1; 508 fl.l_type = F_WRLCK; 509 fl.l_whence = SEEK_SET; 510 if (fcntl(fd, F_SETLK, &fl) < 0) 511 err(1, "F_SETLK 1 (parent)"); 512 513 pid1 = fork(); 514 if (pid1 < 0) 515 err(1, "fork"); 516 517 if (pid1 == 0) { 518 /* 519 * C1 520 * Lock the second byte in the child and then sleep 521 */ 522 fl.l_start = 1; 523 if (fcntl(fd, F_SETLK, &fl) < 0) 524 err(1, "F_SETLK (child1)"); 525 pause(); 526 exit(0); 527 } 528 529 pid2 = fork(); 530 if (pid2 < 0) 531 err(1, "fork"); 532 533 if (pid2 == 0) { 534 /* 535 * C2 536 * Lock the third byte in the child and then block on 537 * the parent's lock. 538 */ 539 fl.l_start = 2; 540 if (fcntl(fd, F_SETLK, &fl) < 0) 541 err(1, "F_SETLK (child2)"); 542 fl.l_start = 0; 543 if (fcntl(fd, F_SETLKW, &fl) < 0) 544 err(1, "F_SETLKW (child2)"); 545 exit(0); 546 } 547 548 /* 549 * Wait until the children have set their locks and then 550 * perform the test. 551 */ 552 sleep(1); 553 554 /* 555 * fcntl should immediately return -1 with errno set to 556 * EDEADLK. If the alarm fires, we failed to detect the 557 * deadlock. 558 */ 559 alarm(1); 560 printf("6 - F_SETLKW complex deadlock: "); 561 562 fl.l_start = 1; 563 fl.l_len = 2; 564 res = fcntl(fd, F_SETLKW, &fl); 565 kill(pid1, SIGTERM); 566 safe_waitpid(pid1); 567 kill(pid2, SIGTERM); 568 safe_waitpid(pid2); 569 570 fl.l_start = 0; 571 fl.l_len = 0; 572 fl.l_type = F_UNLCK; 573 if (fcntl(fd, F_SETLK, &fl) < 0) 574 err(1, "F_UNLCK"); 575 576 FAIL(res == 0); 577 FAIL(errno != EDEADLK); 578 579 /* 580 * Cancel the alarm to avoid confusing later tests. 581 */ 582 alarm(0); 583 584 SUCCEED; 585 } 586 587 /* 588 * Test 7 - F_SETLK shared lock on exclusive locked region 589 * 590 * If a shared or exclusive lock cannot be set, fcntl returns 591 * immediately with EACCES or EAGAIN. 592 */ 593 static int 594 test7(int fd, __unused int argc, const __unused char **argv) 595 { 596 /* 597 * We create a child process to hold the lock which we will 598 * test. We use a pipe to communicate with the child. 599 */ 600 int pid; 601 int pfd[2]; 602 struct flock fl; 603 char ch; 604 int res; 605 606 if (pipe(pfd) < 0) 607 err(1, "pipe"); 608 609 fl.l_start = 0; 610 fl.l_len = 0; 611 fl.l_type = F_WRLCK; 612 fl.l_whence = SEEK_SET; 613 614 pid = fork(); 615 if (pid < 0) 616 err(1, "fork"); 617 618 if (pid == 0) { 619 /* 620 * We are the child. We set a write lock and then 621 * write one byte back to the parent to tell it. The 622 * parent will kill us when its done. 623 */ 624 if (fcntl(fd, F_SETLK, &fl) < 0) 625 err(1, "F_SETLK (child)"); 626 if (write(pfd[1], "a", 1) < 0) 627 err(1, "writing to pipe (child)"); 628 pause(); 629 exit(0); 630 } 631 632 /* 633 * Wait until the child has set its lock and then perform the 634 * test. 635 */ 636 if (read(pfd[0], &ch, 1) != 1) 637 err(1, "reading from pipe (child)"); 638 639 /* 640 * fcntl should wait until the alarm and then return -1 with 641 * errno set to EINTR. 642 */ 643 printf("7 - F_SETLK shared lock on exclusive locked region: "); 644 645 fl.l_type = F_RDLCK; 646 res = fcntl(fd, F_SETLK, &fl); 647 kill(pid, SIGTERM); 648 safe_waitpid(pid); 649 close(pfd[0]); 650 close(pfd[1]); 651 652 FAIL(res == 0); 653 FAIL(errno != EACCES && errno != EAGAIN); 654 655 SUCCEED; 656 } 657 658 /* 659 * Test 8 - F_SETLK shared lock on share locked region 660 * 661 * When a shared lock is set on a segment of a file, other processes 662 * shall be able to set shared locks on that segment or a portion of 663 * it. 664 */ 665 static int 666 test8(int fd, __unused int argc, const __unused char **argv) 667 { 668 /* 669 * We create a child process to hold the lock which we will 670 * test. We use a pipe to communicate with the child. 671 */ 672 int pid; 673 int pfd[2]; 674 struct flock fl; 675 char ch; 676 int res; 677 678 if (pipe(pfd) < 0) 679 err(1, "pipe"); 680 681 fl.l_start = 0; 682 fl.l_len = 0; 683 fl.l_type = F_RDLCK; 684 fl.l_whence = SEEK_SET; 685 686 pid = fork(); 687 if (pid < 0) 688 err(1, "fork"); 689 690 if (pid == 0) { 691 /* 692 * We are the child. We set a write lock and then 693 * write one byte back to the parent to tell it. The 694 * parent will kill us when its done. 695 */ 696 if (fcntl(fd, F_SETLK, &fl) < 0) 697 err(1, "F_SETLK (child)"); 698 if (write(pfd[1], "a", 1) < 0) 699 err(1, "writing to pipe (child)"); 700 pause(); 701 exit(0); 702 } 703 704 /* 705 * Wait until the child has set its lock and then perform the 706 * test. 707 */ 708 if (read(pfd[0], &ch, 1) != 1) 709 err(1, "reading from pipe (child)"); 710 711 /* 712 * fcntl should wait until the alarm and then return -1 with 713 * errno set to EINTR. 714 */ 715 printf("8 - F_SETLK shared lock on share locked region: "); 716 717 fl.l_type = F_RDLCK; 718 res = fcntl(fd, F_SETLK, &fl); 719 720 kill(pid, SIGTERM); 721 safe_waitpid(pid); 722 close(pfd[0]); 723 close(pfd[1]); 724 725 fl.l_start = 0; 726 fl.l_len = 0; 727 fl.l_type = F_UNLCK; 728 if (fcntl(fd, F_SETLK, &fl) < 0) 729 err(1, "F_UNLCK"); 730 731 FAIL(res != 0); 732 733 SUCCEED; 734 } 735 736 /* 737 * Test 9 - F_SETLK exclusive lock on share locked region 738 * 739 * If a shared or exclusive lock cannot be set, fcntl returns 740 * immediately with EACCES or EAGAIN. 741 */ 742 static int 743 test9(int fd, __unused int argc, const __unused char **argv) 744 { 745 /* 746 * We create a child process to hold the lock which we will 747 * test. We use a pipe to communicate with the child. 748 */ 749 int pid; 750 int pfd[2]; 751 struct flock fl; 752 char ch; 753 int res; 754 755 if (pipe(pfd) < 0) 756 err(1, "pipe"); 757 758 fl.l_start = 0; 759 fl.l_len = 0; 760 fl.l_type = F_RDLCK; 761 fl.l_whence = SEEK_SET; 762 763 pid = fork(); 764 if (pid < 0) 765 err(1, "fork"); 766 767 if (pid == 0) { 768 /* 769 * We are the child. We set a write lock and then 770 * write one byte back to the parent to tell it. The 771 * parent will kill us when its done. 772 */ 773 if (fcntl(fd, F_SETLK, &fl) < 0) 774 err(1, "F_SETLK (child)"); 775 if (write(pfd[1], "a", 1) < 0) 776 err(1, "writing to pipe (child)"); 777 pause(); 778 exit(0); 779 } 780 781 /* 782 * Wait until the child has set its lock and then perform the 783 * test. 784 */ 785 if (read(pfd[0], &ch, 1) != 1) 786 err(1, "reading from pipe (child)"); 787 788 /* 789 * fcntl should wait until the alarm and then return -1 with 790 * errno set to EINTR. 791 */ 792 printf("9 - F_SETLK exclusive lock on share locked region: "); 793 794 fl.l_type = F_WRLCK; 795 res = fcntl(fd, F_SETLK, &fl); 796 kill(pid, SIGTERM); 797 safe_waitpid(pid); 798 close(pfd[0]); 799 close(pfd[1]); 800 801 FAIL(res == 0); 802 FAIL(errno != EACCES && errno != EAGAIN); 803 804 SUCCEED; 805 } 806 807 /* 808 * Test 10 - trying to set bogus pid or sysid values 809 * 810 * The l_pid and l_sysid fields are only used with F_GETLK to return 811 * the process ID of the process holding a blocking lock and the 812 * system ID of the system that owns that process 813 */ 814 static int 815 test10(int fd, __unused int argc, const __unused char **argv) 816 { 817 /* 818 * We create a child process to hold the lock which we will 819 * test. We use a pipe to communicate with the child. 820 */ 821 int pid; 822 int pfd[2]; 823 struct flock fl; 824 char ch; 825 826 if (pipe(pfd) < 0) 827 err(1, "pipe"); 828 829 fl.l_start = 0; 830 fl.l_len = 0; 831 fl.l_type = F_WRLCK; 832 fl.l_whence = SEEK_SET; 833 fl.l_pid = 9999; 834 #ifdef HAVE_SYSID 835 fl.l_sysid = 9999; 836 #endif 837 838 pid = fork(); 839 if (pid < 0) 840 err(1, "fork"); 841 842 if (pid == 0) { 843 /* 844 * We are the child. We set a write lock and then 845 * write one byte back to the parent to tell it. The 846 * parent will kill us when its done. 847 */ 848 if (fcntl(fd, F_SETLK, &fl) < 0) 849 err(1, "F_SETLK (child)"); 850 if (write(pfd[1], "a", 1) < 0) 851 err(1, "writing to pipe (child)"); 852 pause(); 853 exit(0); 854 } 855 856 /* 857 * Wait until the child has set its lock and then perform the 858 * test. 859 */ 860 if (read(pfd[0], &ch, 1) != 1) 861 err(1, "reading from pipe (child)"); 862 863 printf("10 - trying to set bogus pid or sysid values: "); 864 865 if (fcntl(fd, F_GETLK, &fl) < 0) 866 err(1, "F_GETLK"); 867 868 kill(pid, SIGTERM); 869 safe_waitpid(pid); 870 close(pfd[0]); 871 close(pfd[1]); 872 873 FAIL(fl.l_pid != pid); 874 #ifdef HAVE_SYSID 875 FAIL(fl.l_sysid != 0); 876 #endif 877 878 SUCCEED; 879 } 880 881 /* 882 * Test 11 - remote locks 883 * 884 * XXX temporary interface which will be removed when the kernel lockd 885 * is added. 886 */ 887 static int 888 test11(int fd, __unused int argc, const __unused char **argv) 889 { 890 #ifdef F_SETLK_REMOTE 891 struct flock fl; 892 int res; 893 894 if (geteuid() != 0) 895 return 0; 896 897 fl.l_start = 0; 898 fl.l_len = 0; 899 fl.l_type = F_WRLCK; 900 fl.l_whence = SEEK_SET; 901 fl.l_pid = 9999; 902 fl.l_sysid = 1001; 903 904 printf("11 - remote locks: "); 905 906 res = fcntl(fd, F_SETLK_REMOTE, &fl); 907 FAIL(res != 0); 908 909 fl.l_sysid = 1002; 910 res = fcntl(fd, F_SETLK_REMOTE, &fl); 911 FAIL(res == 0); 912 FAIL(errno != EACCES && errno != EAGAIN); 913 914 res = fcntl(fd, F_GETLK, &fl); 915 FAIL(res != 0); 916 FAIL(fl.l_pid != 9999); 917 FAIL(fl.l_sysid != 1001); 918 919 fl.l_type = F_UNLCK; 920 fl.l_sysid = 1001; 921 fl.l_start = 0; 922 fl.l_len = 0; 923 res = fcntl(fd, F_SETLK_REMOTE, &fl); 924 FAIL(res != 0); 925 926 fl.l_pid = 1234; 927 fl.l_sysid = 1001; 928 fl.l_start = 0; 929 fl.l_len = 1; 930 fl.l_whence = SEEK_SET; 931 fl.l_type = F_RDLCK; 932 res = fcntl(fd, F_SETLK_REMOTE, &fl); 933 FAIL(res != 0); 934 935 fl.l_sysid = 1002; 936 res = fcntl(fd, F_SETLK_REMOTE, &fl); 937 FAIL(res != 0); 938 939 fl.l_type = F_UNLCKSYS; 940 fl.l_sysid = 1001; 941 res = fcntl(fd, F_SETLK_REMOTE, &fl); 942 FAIL(res != 0); 943 944 fl.l_type = F_WRLCK; 945 res = fcntl(fd, F_GETLK, &fl); 946 FAIL(res != 0); 947 FAIL(fl.l_pid != 1234); 948 FAIL(fl.l_sysid != 1002); 949 950 fl.l_type = F_UNLCKSYS; 951 fl.l_sysid = 1002; 952 res = fcntl(fd, F_SETLK_REMOTE, &fl); 953 FAIL(res != 0); 954 955 SUCCEED; 956 #else 957 return 0; 958 #endif 959 } 960 961 /* 962 * Test 12 - F_SETLKW on locked region which is then unlocked 963 * 964 * If a shared or exclusive lock is blocked by other locks, the 965 * process waits until the request can be satisfied. 966 */ 967 static int 968 test12(int fd, __unused int argc, const __unused char **argv) 969 { 970 /* 971 * We create a child process to hold the lock which we will 972 * test. We use a pipe to communicate with the child. 973 */ 974 int pid; 975 int pfd[2]; 976 struct flock fl; 977 char ch; 978 int res; 979 980 if (pipe(pfd) < 0) 981 err(1, "pipe"); 982 983 fl.l_start = 0; 984 fl.l_len = 0; 985 fl.l_type = F_WRLCK; 986 fl.l_whence = SEEK_SET; 987 988 pid = fork(); 989 if (pid < 0) 990 err(1, "fork"); 991 992 if (pid == 0) { 993 /* 994 * We are the child. We set a write lock and then 995 * write one byte back to the parent to tell it. The 996 * parent will kill us when its done. 997 */ 998 if (fcntl(fd, F_SETLK, &fl) < 0) 999 err(1, "F_SETLK (child)"); 1000 if (write(pfd[1], "a", 1) < 0) 1001 err(1, "writing to pipe (child)"); 1002 1003 sleep(1); 1004 exit(0); 1005 } 1006 1007 /* 1008 * Wait until the child has set its lock and then perform the 1009 * test. 1010 */ 1011 if (read(pfd[0], &ch, 1) != 1) 1012 err(1, "reading from pipe (child)"); 1013 1014 /* 1015 * fcntl should wait until the alarm and then return -1 with 1016 * errno set to EINTR. 1017 */ 1018 printf("12 - F_SETLKW on locked region which is then unlocked: "); 1019 1020 //alarm(1); 1021 1022 res = fcntl(fd, F_SETLKW, &fl); 1023 kill(pid, SIGTERM); 1024 safe_waitpid(pid); 1025 close(pfd[0]); 1026 close(pfd[1]); 1027 FAIL(res != 0); 1028 1029 fl.l_start = 0; 1030 fl.l_len = 0; 1031 fl.l_type = F_UNLCK; 1032 if (fcntl(fd, F_SETLK, &fl) < 0) 1033 err(1, "F_UNLCK"); 1034 1035 SUCCEED; 1036 } 1037 1038 /* 1039 * Test 13 - F_SETLKW on locked region, race with owner 1040 * 1041 * If a shared or exclusive lock is blocked by other locks, the 1042 * process waits until the request can be satisfied. 1043 */ 1044 static int 1045 test13(int fd, __unused int argc, const __unused char **argv) 1046 { 1047 /* 1048 * We create a child process to hold the lock which we will 1049 * test. We use a pipe to communicate with the child. 1050 */ 1051 int i; 1052 int pid; 1053 int pfd[2]; 1054 struct flock fl; 1055 char ch; 1056 int res; 1057 struct itimerval itv; 1058 1059 printf("13 - F_SETLKW on locked region, race with owner: "); 1060 fflush(stdout); 1061 1062 for (i = 0; i < 100; i++) { 1063 if (pipe(pfd) < 0) 1064 err(1, "pipe"); 1065 1066 fl.l_start = 0; 1067 fl.l_len = 0; 1068 fl.l_type = F_WRLCK; 1069 fl.l_whence = SEEK_SET; 1070 1071 pid = fork(); 1072 if (pid < 0) 1073 err(1, "fork"); 1074 1075 if (pid == 0) { 1076 /* 1077 * We are the child. We set a write lock and then 1078 * write one byte back to the parent to tell it. The 1079 * parent will kill us when its done. 1080 */ 1081 if (fcntl(fd, F_SETLK, &fl) < 0) 1082 err(1, "F_SETLK (child)"); 1083 if (write(pfd[1], "a", 1) < 0) 1084 err(1, "writing to pipe (child)"); 1085 1086 usleep(1); 1087 exit(0); 1088 } 1089 1090 /* 1091 * Wait until the child has set its lock and then perform the 1092 * test. 1093 */ 1094 while (read(pfd[0], &ch, 1) != 1) { 1095 if (errno == EINTR) 1096 continue; 1097 err(1, "reading from pipe (child)"); 1098 } 1099 1100 /* 1101 * fcntl should wait until the alarm and then return -1 with 1102 * errno set to EINTR. 1103 */ 1104 itv.it_interval.tv_sec = 0; 1105 itv.it_interval.tv_usec = 0; 1106 itv.it_value.tv_sec = 0; 1107 itv.it_value.tv_usec = 2; 1108 setitimer(ITIMER_REAL, &itv, NULL); 1109 1110 res = fcntl(fd, F_SETLKW, &fl); 1111 kill(pid, SIGTERM); 1112 safe_waitpid(pid); 1113 close(pfd[0]); 1114 close(pfd[1]); 1115 FAIL(!(res == 0 || (res == -1 && errno == EINTR))); 1116 1117 fl.l_start = 0; 1118 fl.l_len = 0; 1119 fl.l_type = F_UNLCK; 1120 if (fcntl(fd, F_SETLK, &fl) < 0) 1121 err(1, "F_UNLCK"); 1122 } 1123 SUCCEED; 1124 } 1125 1126 /* 1127 * Test 14 - soak test 1128 */ 1129 static int 1130 test14(int fd, int argc, const char **argv) 1131 { 1132 #define CHILD_COUNT 20 1133 /* 1134 * We create a set of child processes and let each one run 1135 * through a random sequence of locks and unlocks. 1136 */ 1137 int i, j, id, id_base; 1138 int pids[CHILD_COUNT], pid; 1139 char buf[128]; 1140 char tbuf[128]; 1141 int map[128]; 1142 char outbuf[512]; 1143 struct flock fl; 1144 struct itimerval itv; 1145 int status; 1146 1147 id_base = 0; 1148 if (argc >= 2) 1149 id_base = strtol(argv[1], NULL, 0); 1150 1151 printf("14 - soak test: "); 1152 fflush(stdout); 1153 1154 for (i = 0; i < 128; i++) 1155 map[i] = F_UNLCK; 1156 1157 for (i = 0; i < CHILD_COUNT; i++) { 1158 1159 pid = fork(); 1160 if (pid < 0) 1161 err(1, "fork"); 1162 if (pid) { 1163 /* 1164 * Parent - record the pid and continue. 1165 */ 1166 pids[i] = pid; 1167 continue; 1168 } 1169 1170 /* 1171 * Child - do some work and exit. 1172 */ 1173 id = id_base + i; 1174 srandom(getpid()); 1175 1176 for (j = 0; j < 50; j++) { 1177 int start, end, len; 1178 int set, wrlock; 1179 1180 do { 1181 start = random() & 127; 1182 end = random() & 127; 1183 } while (end <= start); 1184 1185 set = random() & 1; 1186 wrlock = random() & 1; 1187 1188 len = end - start; 1189 fl.l_start = start; 1190 fl.l_len = len; 1191 fl.l_whence = SEEK_SET; 1192 if (set) 1193 fl.l_type = wrlock ? F_WRLCK : F_RDLCK; 1194 else 1195 fl.l_type = F_UNLCK; 1196 1197 itv.it_interval.tv_sec = 0; 1198 itv.it_interval.tv_usec = 0; 1199 itv.it_value.tv_sec = 0; 1200 itv.it_value.tv_usec = 3000; 1201 setitimer(ITIMER_REAL, &itv, NULL); 1202 1203 if (fcntl(fd, F_SETLKW, &fl) < 0) { 1204 if (errno == EDEADLK || errno == EINTR) { 1205 if (verbose) { 1206 snprintf(outbuf, sizeof(outbuf), 1207 "%d[%d]: %s [%d .. %d] %s\n", 1208 id, j, 1209 set ? (wrlock ? "write lock" 1210 : "read lock") 1211 : "unlock", start, end, 1212 errno == EDEADLK 1213 ? "deadlock" 1214 : "interrupted"); 1215 write(1, outbuf, 1216 strlen(outbuf)); 1217 } 1218 continue; 1219 } else { 1220 perror("fcntl"); 1221 } 1222 } 1223 1224 itv.it_interval.tv_sec = 0; 1225 itv.it_interval.tv_usec = 0; 1226 itv.it_value.tv_sec = 0; 1227 itv.it_value.tv_usec = 0; 1228 setitimer(ITIMER_REAL, &itv, NULL); 1229 1230 if (verbose) { 1231 snprintf(outbuf, sizeof(outbuf), 1232 "%d[%d]: %s [%d .. %d] succeeded\n", 1233 id, j, 1234 set ? (wrlock ? "write lock" : "read lock") 1235 : "unlock", start, end); 1236 write(1, outbuf, strlen(outbuf)); 1237 } 1238 1239 if (set) { 1240 if (wrlock) { 1241 /* 1242 * We got a write lock - write 1243 * our ID to each byte that we 1244 * managed to claim. 1245 */ 1246 for (i = start; i < end; i++) 1247 map[i] = F_WRLCK; 1248 memset(&buf[start], id, len); 1249 if (pwrite(fd, &buf[start], len, 1250 start) != len) { 1251 printf("%d: short write\n", id); 1252 exit(1); 1253 } 1254 } else { 1255 /* 1256 * We got a read lock - read 1257 * the bytes which we claimed 1258 * so that we can check that 1259 * they don't change 1260 * unexpectedly. 1261 */ 1262 for (i = start; i < end; i++) 1263 map[i] = F_RDLCK; 1264 if (pread(fd, &buf[start], len, 1265 start) != len) { 1266 printf("%d: short read\n", id); 1267 exit(1); 1268 } 1269 } 1270 } else { 1271 for (i = start; i < end; i++) 1272 map[i] = F_UNLCK; 1273 } 1274 1275 usleep(1000); 1276 1277 /* 1278 * Read back the whole region so that we can 1279 * check that all the bytes we have some kind 1280 * of claim to have the correct value. 1281 */ 1282 if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) { 1283 printf("%d: short read\n", id); 1284 exit(1); 1285 } 1286 1287 for (i = 0; i < 128; i++) { 1288 if (map[i] != F_UNLCK && buf[i] != tbuf[i]) { 1289 snprintf(outbuf, sizeof(outbuf), 1290 "%d: byte %d expected %d, " 1291 "got %d\n", id, i, buf[i], tbuf[i]); 1292 write(1, outbuf, strlen(outbuf)); 1293 exit(1); 1294 } 1295 } 1296 } 1297 if (verbose) 1298 printf("%d[%d]: done\n", id, j); 1299 1300 exit(0); 1301 } 1302 1303 status = 0; 1304 for (i = 0; i < CHILD_COUNT; i++) { 1305 status += safe_waitpid(pids[i]); 1306 } 1307 if (status) 1308 FAIL(status != 0); 1309 1310 SUCCEED; 1311 } 1312 1313 /* 1314 * Test 15 - flock(2) semantcs 1315 * 1316 * When a lock holder has a shared lock and attempts to upgrade that 1317 * shared lock to exclusive, it must drop the shared lock before 1318 * blocking on the exclusive lock. 1319 * 1320 * To test this, we first arrange for two shared locks on the file, 1321 * and then attempt to upgrade one of them to exclusive. This should 1322 * drop one of the shared locks and block. We interrupt the blocking 1323 * lock request and examine the lock state of the file after dropping 1324 * the other shared lock - there should be no active locks at this 1325 * point. 1326 */ 1327 static int 1328 test15(int fd, __unused int argc, const __unused char **argv) 1329 { 1330 #ifdef LOCK_EX 1331 /* 1332 * We create a child process to hold the lock which we will 1333 * test. We use a pipe to communicate with the child. 1334 * 1335 * Since we only have one file descriptors and lock ownership 1336 * for flock(2) goes with the file descriptor, we use fcntl to 1337 * set the child's shared lock. 1338 */ 1339 int pid; 1340 int pfd[2]; 1341 struct flock fl; 1342 char ch; 1343 int res; 1344 1345 if (pipe(pfd) < 0) 1346 err(1, "pipe"); 1347 1348 pid = fork(); 1349 if (pid < 0) 1350 err(1, "fork"); 1351 1352 if (pid == 0) { 1353 /* 1354 * We are the child. We set a shared lock and then 1355 * write one byte back to the parent to tell it. The 1356 * parent will kill us when its done. 1357 */ 1358 fl.l_start = 0; 1359 fl.l_len = 0; 1360 fl.l_type = F_RDLCK; 1361 fl.l_whence = SEEK_SET; 1362 if (fcntl(fd, F_SETLK, &fl) < 0) 1363 err(1, "fcntl(F_SETLK) (child)"); 1364 if (write(pfd[1], "a", 1) < 0) 1365 err(1, "writing to pipe (child)"); 1366 pause(); 1367 exit(0); 1368 } 1369 1370 /* 1371 * Wait until the child has set its lock and then perform the 1372 * test. 1373 */ 1374 if (read(pfd[0], &ch, 1) != 1) 1375 err(1, "reading from pipe (child)"); 1376 1377 (void)dup(fd); 1378 if (flock(fd, LOCK_SH) < 0) 1379 err(1, "flock shared"); 1380 1381 /* 1382 * flock should wait until the alarm and then return -1 with 1383 * errno set to EINTR. 1384 */ 1385 printf("15 - flock(2) semantics: "); 1386 1387 alarm(1); 1388 flock(fd, LOCK_EX); 1389 1390 /* 1391 * Kill the child to force it to drop its locks. 1392 */ 1393 kill(pid, SIGTERM); 1394 safe_waitpid(pid); 1395 1396 fl.l_start = 0; 1397 fl.l_len = 0; 1398 fl.l_type = F_WRLCK; 1399 fl.l_whence = SEEK_SET; 1400 res = fcntl(fd, F_GETLK, &fl); 1401 1402 close(pfd[0]); 1403 close(pfd[1]); 1404 FAIL(res != 0); 1405 FAIL(fl.l_type != F_UNLCK); 1406 1407 SUCCEED; 1408 #else 1409 return 0; 1410 #endif 1411 } 1412 1413 struct test_ctx { 1414 struct flock tc_fl; 1415 int tc_fd; 1416 }; 1417 1418 static void * 1419 test16_func(void *tc_in) 1420 { 1421 uintptr_t error; 1422 struct test_ctx *tc = tc_in; 1423 1424 error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl); 1425 1426 pthread_exit((void *)error); 1427 } 1428 1429 #define THREADS 10 1430 1431 /* 1432 * Test 16 - F_SETLKW from two threads 1433 * 1434 * If two threads within a process are blocked on a lock and the lock 1435 * is granted, make sure things are sane. 1436 */ 1437 static int 1438 test16(int fd, __unused int argc, const __unused char **argv) 1439 { 1440 /* 1441 * We create a child process to hold the lock which we will 1442 * test. We use a pipe to communicate with the child. 1443 */ 1444 int pid; 1445 int pfd[2]; 1446 struct test_ctx tc = { .tc_fd = fd }; 1447 char ch; 1448 int i; 1449 int error; 1450 pthread_t thr[THREADS]; 1451 1452 if (pipe(pfd) < 0) 1453 err(1, "pipe"); 1454 1455 tc.tc_fl.l_start = 0; 1456 tc.tc_fl.l_len = 0; 1457 tc.tc_fl.l_type = F_WRLCK; 1458 tc.tc_fl.l_whence = SEEK_SET; 1459 1460 pid = fork(); 1461 if (pid < 0) 1462 err(1, "fork"); 1463 1464 if (pid == 0) { 1465 /* 1466 * We are the child. We set a write lock and then 1467 * write one byte back to the parent to tell it. The 1468 * parent will kill us when its done. 1469 */ 1470 if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0) 1471 err(1, "F_SETLK (child)"); 1472 if (write(pfd[1], "a", 1) < 0) 1473 err(1, "writing to pipe (child)"); 1474 pause(); 1475 exit(0); 1476 } 1477 1478 /* 1479 * Wait until the child has set its lock and then perform the 1480 * test. 1481 */ 1482 if (read(pfd[0], &ch, 1) != 1) 1483 err(1, "reading from pipe (child)"); 1484 1485 /* 1486 * fcntl should wait until the alarm and then return -1 with 1487 * errno set to EINTR. 1488 */ 1489 printf("16 - F_SETLKW on locked region by two threads: "); 1490 1491 for (i = 0; i < THREADS; i++) { 1492 error = pthread_create(&thr[i], NULL, test16_func, &tc); 1493 if (error) 1494 err(1, "pthread_create"); 1495 } 1496 1497 /* 1498 * Sleep, then kill the child. This makes me a little sad, but it's 1499 * tricky to tell whether the threads are all really blocked by this 1500 * point. 1501 */ 1502 sleep(1); 1503 kill(pid, SIGTERM); 1504 safe_waitpid(pid); 1505 close(pfd[0]); 1506 close(pfd[1]); 1507 1508 for (i = 0; i < THREADS; i++) { 1509 void *res; 1510 error = pthread_join(thr[i], &res); 1511 if (error) 1512 err(1, "pthread_join"); 1513 FAIL((uintptr_t)res != 0); 1514 } 1515 1516 SUCCEED; 1517 } 1518 1519 struct test { 1520 int (*testfn)(int, int, const char **); /* function to perform the test */ 1521 int num; /* test number */ 1522 int intr; /* non-zero if the test interrupts a lock */ 1523 }; 1524 1525 static struct test tests[] = { 1526 { test1, 1, 0 }, 1527 { test2, 2, 0 }, 1528 { test3, 3, 1 }, 1529 { test4, 4, 0 }, 1530 { test5, 5, 1 }, 1531 { test6, 6, 1 }, 1532 { test7, 7, 0 }, 1533 { test8, 8, 0 }, 1534 { test9, 9, 0 }, 1535 { test10, 10, 0 }, 1536 { test11, 11, 1 }, 1537 { test12, 12, 0 }, 1538 { test13, 13, 1 }, 1539 { test14, 14, 0 }, 1540 { test15, 15, 1 }, 1541 { test16, 16, 1 }, 1542 }; 1543 1544 int 1545 main(int argc, const char *argv[]) 1546 { 1547 int testnum; 1548 int fd; 1549 int nointr; 1550 unsigned i; 1551 struct sigaction sa; 1552 int test_argc; 1553 const char **test_argv; 1554 1555 if (argc < 2) { 1556 errx(1, "usage: flock <directory> [test number] ..."); 1557 } 1558 1559 fd = make_file(argv[1], 1024); 1560 if (argc >= 3) { 1561 testnum = strtol(argv[2], NULL, 0); 1562 test_argc = argc - 2; 1563 test_argv = argv + 2; 1564 } else { 1565 testnum = 0; 1566 test_argc = 0; 1567 test_argv = NULL; 1568 } 1569 1570 sa.sa_handler = ignore_alarm; 1571 sigemptyset(&sa.sa_mask); 1572 sa.sa_flags = 0; 1573 sigaction(SIGALRM, &sa, 0); 1574 1575 nointr = 0; 1576 #if defined(__FreeBSD__) && __FreeBSD_version < 800040 1577 { 1578 /* 1579 * FreeBSD with userland NLM can't interrupt a blocked 1580 * lock request on an NFS mounted filesystem. 1581 */ 1582 struct statfs st; 1583 fstatfs(fd, &st); 1584 nointr = !strcmp(st.f_fstypename, "nfs"); 1585 } 1586 #endif 1587 1588 for (i = 0; i < nitems(tests); i++) { 1589 if (tests[i].intr && nointr) 1590 continue; 1591 if (!testnum || tests[i].num == testnum) 1592 tests[i].testfn(fd, test_argc, test_argv); 1593 } 1594 1595 return 0; 1596 } 1597