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