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