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