1 /* $NetBSD: vfs_lockf.c,v 1.20 2002/10/22 03:32:17 simonb Exp $ */ 2 3 /* 4 * Copyright (c) 1982, 1986, 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Scooter Morris at Genentech Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)ufs_lockf.c 8.4 (Berkeley) 10/26/94 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: vfs_lockf.c,v 1.20 2002/10/22 03:32:17 simonb Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/file.h> 48 #include <sys/proc.h> 49 #include <sys/vnode.h> 50 #include <sys/malloc.h> 51 #include <sys/fcntl.h> 52 #include <sys/lockf.h> 53 54 /* 55 * This variable controls the maximum number of processes that will 56 * be checked in doing deadlock detection. 57 */ 58 int maxlockdepth = MAXDEPTH; 59 60 #ifdef LOCKF_DEBUG 61 int lockf_debug = 0; 62 #endif 63 64 #define NOLOCKF (struct lockf *)0 65 #define SELF 0x1 66 #define OTHERS 0x2 67 68 /* 69 * XXX TODO 70 * Misc cleanups: "caddr_t id" should be visible in the API as a 71 * "struct proc *". 72 * (This requires rototilling all VFS's which support advisory locking). 73 * 74 * Use pools for lock allocation. 75 */ 76 77 /* 78 * XXXSMP TODO: Using either (a) a global lock, or (b) the vnode's 79 * interlock should be sufficient; (b) requires a change to the API 80 * because the vnode isn't visible here. 81 * 82 * If there's a lot of lock contention on a single vnode, locking 83 * schemes which allow for more paralleism would be needed. Given how 84 * infrequently byte-range locks are actually used in typical BSD 85 * code, a more complex approach probably isn't worth it. 86 */ 87 88 /* 89 * Do an advisory lock operation. 90 */ 91 int 92 lf_advlock(ap, head, size) 93 struct vop_advlock_args *ap; 94 struct lockf **head; 95 off_t size; 96 { 97 struct flock *fl = ap->a_fl; 98 struct lockf *lock; 99 off_t start, end; 100 int error; 101 102 /* 103 * Convert the flock structure into a start and end. 104 */ 105 switch (fl->l_whence) { 106 case SEEK_SET: 107 case SEEK_CUR: 108 /* 109 * Caller is responsible for adding any necessary offset 110 * when SEEK_CUR is used. 111 */ 112 start = fl->l_start; 113 break; 114 115 case SEEK_END: 116 start = size + fl->l_start; 117 break; 118 119 default: 120 return (EINVAL); 121 } 122 if (start < 0) 123 return (EINVAL); 124 125 /* 126 * Avoid the common case of unlocking when inode has no locks. 127 */ 128 if (*head == (struct lockf *)0) { 129 if (ap->a_op != F_SETLK) { 130 fl->l_type = F_UNLCK; 131 return (0); 132 } 133 } 134 135 if (fl->l_len == 0) 136 end = -1; 137 else 138 end = start + fl->l_len - 1; 139 /* 140 * Create the lockf structure. 141 */ 142 MALLOC(lock, struct lockf *, sizeof(*lock), M_LOCKF, M_WAITOK); 143 lock->lf_start = start; 144 lock->lf_end = end; 145 lock->lf_id = ap->a_id; 146 lock->lf_head = head; 147 lock->lf_type = fl->l_type; 148 lock->lf_next = (struct lockf *)0; 149 TAILQ_INIT(&lock->lf_blkhd); 150 lock->lf_flags = ap->a_flags; 151 /* 152 * Do the requested operation. 153 */ 154 switch (ap->a_op) { 155 156 case F_SETLK: 157 return (lf_setlock(lock)); 158 159 case F_UNLCK: 160 error = lf_clearlock(lock); 161 FREE(lock, M_LOCKF); 162 return (error); 163 164 case F_GETLK: 165 error = lf_getlock(lock, fl); 166 FREE(lock, M_LOCKF); 167 return (error); 168 169 default: 170 FREE(lock, M_LOCKF); 171 return (EINVAL); 172 } 173 /* NOTREACHED */ 174 } 175 176 /* 177 * Set a byte-range lock. 178 */ 179 int 180 lf_setlock(lock) 181 struct lockf *lock; 182 { 183 struct lockf *block; 184 struct lockf **head = lock->lf_head; 185 struct lockf **prev, *overlap, *ltmp; 186 static char lockstr[] = "lockf"; 187 int ovcase, priority, needtolink, error; 188 189 #ifdef LOCKF_DEBUG 190 if (lockf_debug & 1) 191 lf_print("lf_setlock", lock); 192 #endif /* LOCKF_DEBUG */ 193 194 /* 195 * Set the priority 196 */ 197 priority = PLOCK; 198 if (lock->lf_type == F_WRLCK) 199 priority += 4; 200 priority |= PCATCH; 201 /* 202 * Scan lock list for this file looking for locks that would block us. 203 */ 204 while ((block = lf_getblock(lock)) != NULL) { 205 /* 206 * Free the structure and return if nonblocking. 207 */ 208 if ((lock->lf_flags & F_WAIT) == 0) { 209 FREE(lock, M_LOCKF); 210 return (EAGAIN); 211 } 212 /* 213 * We are blocked. Since flock style locks cover 214 * the whole file, there is no chance for deadlock. 215 * For byte-range locks we must check for deadlock. 216 * 217 * Deadlock detection is done by looking through the 218 * wait channels to see if there are any cycles that 219 * involve us. MAXDEPTH is set just to make sure we 220 * do not go off into neverneverland. 221 */ 222 if ((lock->lf_flags & F_POSIX) && 223 (block->lf_flags & F_POSIX)) { 224 struct proc *wproc; 225 struct lockf *waitblock; 226 int i = 0; 227 228 /* The block is waiting on something */ 229 wproc = (struct proc *)block->lf_id; 230 while (wproc->p_wchan && 231 (wproc->p_wmesg == lockstr) && 232 (i++ < maxlockdepth)) { 233 waitblock = (struct lockf *)wproc->p_wchan; 234 /* Get the owner of the blocking lock */ 235 waitblock = waitblock->lf_next; 236 if ((waitblock->lf_flags & F_POSIX) == 0) 237 break; 238 wproc = (struct proc *)waitblock->lf_id; 239 if (wproc == (struct proc *)lock->lf_id) { 240 free(lock, M_LOCKF); 241 return (EDEADLK); 242 } 243 } 244 /* 245 * If we're still following a dependancy chain 246 * after maxlockdepth iterations, assume we're in 247 * a cycle to be safe. 248 */ 249 if (i >= maxlockdepth) { 250 free(lock, M_LOCKF); 251 return (EDEADLK); 252 } 253 } 254 /* 255 * For flock type locks, we must first remove 256 * any shared locks that we hold before we sleep 257 * waiting for an exclusive lock. 258 */ 259 if ((lock->lf_flags & F_FLOCK) && 260 lock->lf_type == F_WRLCK) { 261 lock->lf_type = F_UNLCK; 262 (void) lf_clearlock(lock); 263 lock->lf_type = F_WRLCK; 264 } 265 /* 266 * Add our lock to the blocked list and sleep until we're free. 267 * Remember who blocked us (for deadlock detection). 268 */ 269 lock->lf_next = block; 270 TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block); 271 #ifdef LOCKF_DEBUG 272 if (lockf_debug & 1) { 273 lf_print("lf_setlock: blocking on", block); 274 lf_printlist("lf_setlock", block); 275 } 276 #endif /* LOCKF_DEBUG */ 277 error = tsleep((caddr_t)lock, priority, lockstr, 0); 278 279 /* 280 * We may have been awakened by a signal (in 281 * which case we must remove ourselves from the 282 * blocked list) and/or by another process 283 * releasing a lock (in which case we have already 284 * been removed from the blocked list and our 285 * lf_next field set to NOLOCKF). 286 */ 287 if (lock->lf_next != NOLOCKF) { 288 TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, lf_block); 289 lock->lf_next = NOLOCKF; 290 } 291 if (error) { 292 free(lock, M_LOCKF); 293 return (error); 294 } 295 } 296 /* 297 * No blocks!! Add the lock. Note that we will 298 * downgrade or upgrade any overlapping locks this 299 * process already owns. 300 * 301 * Skip over locks owned by other processes. 302 * Handle any locks that overlap and are owned by ourselves. 303 */ 304 prev = head; 305 block = *head; 306 needtolink = 1; 307 for (;;) { 308 ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap); 309 if (ovcase) 310 block = overlap->lf_next; 311 /* 312 * Six cases: 313 * 0) no overlap 314 * 1) overlap == lock 315 * 2) overlap contains lock 316 * 3) lock contains overlap 317 * 4) overlap starts before lock 318 * 5) overlap ends after lock 319 */ 320 switch (ovcase) { 321 case 0: /* no overlap */ 322 if (needtolink) { 323 *prev = lock; 324 lock->lf_next = overlap; 325 } 326 break; 327 328 case 1: /* overlap == lock */ 329 /* 330 * If downgrading lock, others may be 331 * able to acquire it. 332 */ 333 if (lock->lf_type == F_RDLCK && 334 overlap->lf_type == F_WRLCK) 335 lf_wakelock(overlap); 336 overlap->lf_type = lock->lf_type; 337 FREE(lock, M_LOCKF); 338 lock = overlap; /* for debug output below */ 339 break; 340 341 case 2: /* overlap contains lock */ 342 /* 343 * Check for common starting point and different types. 344 */ 345 if (overlap->lf_type == lock->lf_type) { 346 free(lock, M_LOCKF); 347 lock = overlap; /* for debug output below */ 348 break; 349 } 350 if (overlap->lf_start == lock->lf_start) { 351 *prev = lock; 352 lock->lf_next = overlap; 353 overlap->lf_start = lock->lf_end + 1; 354 } else 355 lf_split(overlap, lock); 356 lf_wakelock(overlap); 357 break; 358 359 case 3: /* lock contains overlap */ 360 /* 361 * If downgrading lock, others may be able to 362 * acquire it, otherwise take the list. 363 */ 364 if (lock->lf_type == F_RDLCK && 365 overlap->lf_type == F_WRLCK) { 366 lf_wakelock(overlap); 367 } else { 368 while ((ltmp = TAILQ_FIRST(&overlap->lf_blkhd))) { 369 KASSERT(ltmp->lf_next == overlap); 370 TAILQ_REMOVE(&overlap->lf_blkhd, ltmp, 371 lf_block); 372 ltmp->lf_next = lock; 373 TAILQ_INSERT_TAIL(&lock->lf_blkhd, 374 ltmp, lf_block); 375 } 376 } 377 /* 378 * Add the new lock if necessary and delete the overlap. 379 */ 380 if (needtolink) { 381 *prev = lock; 382 lock->lf_next = overlap->lf_next; 383 prev = &lock->lf_next; 384 needtolink = 0; 385 } else 386 *prev = overlap->lf_next; 387 free(overlap, M_LOCKF); 388 continue; 389 390 case 4: /* overlap starts before lock */ 391 /* 392 * Add lock after overlap on the list. 393 */ 394 lock->lf_next = overlap->lf_next; 395 overlap->lf_next = lock; 396 overlap->lf_end = lock->lf_start - 1; 397 prev = &lock->lf_next; 398 lf_wakelock(overlap); 399 needtolink = 0; 400 continue; 401 402 case 5: /* overlap ends after lock */ 403 /* 404 * Add the new lock before overlap. 405 */ 406 if (needtolink) { 407 *prev = lock; 408 lock->lf_next = overlap; 409 } 410 overlap->lf_start = lock->lf_end + 1; 411 lf_wakelock(overlap); 412 break; 413 } 414 break; 415 } 416 #ifdef LOCKF_DEBUG 417 if (lockf_debug & 1) { 418 lf_print("lf_setlock: got the lock", lock); 419 lf_printlist("lf_setlock", lock); 420 } 421 #endif /* LOCKF_DEBUG */ 422 return (0); 423 } 424 425 /* 426 * Remove a byte-range lock on an inode. 427 * 428 * Generally, find the lock (or an overlap to that lock) 429 * and remove it (or shrink it), then wakeup anyone we can. 430 */ 431 int 432 lf_clearlock(unlock) 433 struct lockf *unlock; 434 { 435 struct lockf **head = unlock->lf_head; 436 struct lockf *lf = *head; 437 struct lockf *overlap, **prev; 438 int ovcase; 439 440 if (lf == NOLOCKF) 441 return (0); 442 #ifdef LOCKF_DEBUG 443 if (unlock->lf_type != F_UNLCK) 444 panic("lf_clearlock: bad type"); 445 if (lockf_debug & 1) 446 lf_print("lf_clearlock", unlock); 447 #endif /* LOCKF_DEBUG */ 448 prev = head; 449 while ((ovcase = lf_findoverlap(lf, unlock, SELF, 450 &prev, &overlap)) != 0) { 451 /* 452 * Wakeup the list of locks to be retried. 453 */ 454 lf_wakelock(overlap); 455 456 switch (ovcase) { 457 458 case 1: /* overlap == lock */ 459 *prev = overlap->lf_next; 460 FREE(overlap, M_LOCKF); 461 break; 462 463 case 2: /* overlap contains lock: split it */ 464 if (overlap->lf_start == unlock->lf_start) { 465 overlap->lf_start = unlock->lf_end + 1; 466 break; 467 } 468 lf_split(overlap, unlock); 469 overlap->lf_next = unlock->lf_next; 470 break; 471 472 case 3: /* lock contains overlap */ 473 *prev = overlap->lf_next; 474 lf = overlap->lf_next; 475 free(overlap, M_LOCKF); 476 continue; 477 478 case 4: /* overlap starts before lock */ 479 overlap->lf_end = unlock->lf_start - 1; 480 prev = &overlap->lf_next; 481 lf = overlap->lf_next; 482 continue; 483 484 case 5: /* overlap ends after lock */ 485 overlap->lf_start = unlock->lf_end + 1; 486 break; 487 } 488 break; 489 } 490 #ifdef LOCKF_DEBUG 491 if (lockf_debug & 1) 492 lf_printlist("lf_clearlock", unlock); 493 #endif /* LOCKF_DEBUG */ 494 return (0); 495 } 496 497 /* 498 * Check whether there is a blocking lock, 499 * and if so return its process identifier. 500 */ 501 int 502 lf_getlock(lock, fl) 503 struct lockf *lock; 504 struct flock *fl; 505 { 506 struct lockf *block; 507 508 #ifdef LOCKF_DEBUG 509 if (lockf_debug & 1) 510 lf_print("lf_getlock", lock); 511 #endif /* LOCKF_DEBUG */ 512 513 if ((block = lf_getblock(lock)) != NULL) { 514 fl->l_type = block->lf_type; 515 fl->l_whence = SEEK_SET; 516 fl->l_start = block->lf_start; 517 if (block->lf_end == -1) 518 fl->l_len = 0; 519 else 520 fl->l_len = block->lf_end - block->lf_start + 1; 521 if (block->lf_flags & F_POSIX) 522 fl->l_pid = ((struct proc *)(block->lf_id))->p_pid; 523 else 524 fl->l_pid = -1; 525 } else { 526 fl->l_type = F_UNLCK; 527 } 528 return (0); 529 } 530 531 /* 532 * Walk the list of locks for an inode and 533 * return the first blocking lock. 534 */ 535 struct lockf * 536 lf_getblock(lock) 537 struct lockf *lock; 538 { 539 struct lockf **prev, *overlap, *lf = *(lock->lf_head); 540 541 prev = lock->lf_head; 542 while (lf_findoverlap(lf, lock, OTHERS, &prev, &overlap) != 0) { 543 /* 544 * We've found an overlap, see if it blocks us 545 */ 546 if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) 547 return (overlap); 548 /* 549 * Nope, point to the next one on the list and 550 * see if it blocks us 551 */ 552 lf = overlap->lf_next; 553 } 554 return (NOLOCKF); 555 } 556 557 /* 558 * Walk the list of locks for an inode to 559 * find an overlapping lock (if any). 560 * 561 * NOTE: this returns only the FIRST overlapping lock. There 562 * may be more than one. 563 */ 564 int 565 lf_findoverlap(lf, lock, type, prev, overlap) 566 struct lockf *lf; 567 struct lockf *lock; 568 int type; 569 struct lockf ***prev; 570 struct lockf **overlap; 571 { 572 off_t start, end; 573 574 *overlap = lf; 575 if (lf == NOLOCKF) 576 return (0); 577 #ifdef LOCKF_DEBUG 578 if (lockf_debug & 2) 579 lf_print("lf_findoverlap: looking for overlap in", lock); 580 #endif /* LOCKF_DEBUG */ 581 start = lock->lf_start; 582 end = lock->lf_end; 583 while (lf != NOLOCKF) { 584 if (((type & SELF) && lf->lf_id != lock->lf_id) || 585 ((type & OTHERS) && lf->lf_id == lock->lf_id)) { 586 *prev = &lf->lf_next; 587 *overlap = lf = lf->lf_next; 588 continue; 589 } 590 #ifdef LOCKF_DEBUG 591 if (lockf_debug & 2) 592 lf_print("\tchecking", lf); 593 #endif /* LOCKF_DEBUG */ 594 /* 595 * OK, check for overlap 596 * 597 * Six cases: 598 * 0) no overlap 599 * 1) overlap == lock 600 * 2) overlap contains lock 601 * 3) lock contains overlap 602 * 4) overlap starts before lock 603 * 5) overlap ends after lock 604 */ 605 if ((lf->lf_end != -1 && start > lf->lf_end) || 606 (end != -1 && lf->lf_start > end)) { 607 /* Case 0 */ 608 #ifdef LOCKF_DEBUG 609 if (lockf_debug & 2) 610 printf("no overlap\n"); 611 #endif /* LOCKF_DEBUG */ 612 if ((type & SELF) && end != -1 && lf->lf_start > end) 613 return (0); 614 *prev = &lf->lf_next; 615 *overlap = lf = lf->lf_next; 616 continue; 617 } 618 if ((lf->lf_start == start) && (lf->lf_end == end)) { 619 /* Case 1 */ 620 #ifdef LOCKF_DEBUG 621 if (lockf_debug & 2) 622 printf("overlap == lock\n"); 623 #endif /* LOCKF_DEBUG */ 624 return (1); 625 } 626 if ((lf->lf_start <= start) && 627 (end != -1) && 628 ((lf->lf_end >= end) || (lf->lf_end == -1))) { 629 /* Case 2 */ 630 #ifdef LOCKF_DEBUG 631 if (lockf_debug & 2) 632 printf("overlap contains lock\n"); 633 #endif /* LOCKF_DEBUG */ 634 return (2); 635 } 636 if (start <= lf->lf_start && 637 (end == -1 || 638 (lf->lf_end != -1 && end >= lf->lf_end))) { 639 /* Case 3 */ 640 #ifdef LOCKF_DEBUG 641 if (lockf_debug & 2) 642 printf("lock contains overlap\n"); 643 #endif /* LOCKF_DEBUG */ 644 return (3); 645 } 646 if ((lf->lf_start < start) && 647 ((lf->lf_end >= start) || (lf->lf_end == -1))) { 648 /* Case 4 */ 649 #ifdef LOCKF_DEBUG 650 if (lockf_debug & 2) 651 printf("overlap starts before lock\n"); 652 #endif /* LOCKF_DEBUG */ 653 return (4); 654 } 655 if ((lf->lf_start > start) && 656 (end != -1) && 657 ((lf->lf_end > end) || (lf->lf_end == -1))) { 658 /* Case 5 */ 659 #ifdef LOCKF_DEBUG 660 if (lockf_debug & 2) 661 printf("overlap ends after lock\n"); 662 #endif /* LOCKF_DEBUG */ 663 return (5); 664 } 665 panic("lf_findoverlap: default"); 666 } 667 return (0); 668 } 669 670 /* 671 * Split a lock and a contained region into 672 * two or three locks as necessary. 673 */ 674 void 675 lf_split(lock1, lock2) 676 struct lockf *lock1; 677 struct lockf *lock2; 678 { 679 struct lockf *splitlock; 680 681 #ifdef LOCKF_DEBUG 682 if (lockf_debug & 2) { 683 lf_print("lf_split", lock1); 684 lf_print("splitting from", lock2); 685 } 686 #endif /* LOCKF_DEBUG */ 687 /* 688 * Check to see if spliting into only two pieces. 689 */ 690 if (lock1->lf_start == lock2->lf_start) { 691 lock1->lf_start = lock2->lf_end + 1; 692 lock2->lf_next = lock1; 693 return; 694 } 695 if (lock1->lf_end == lock2->lf_end) { 696 lock1->lf_end = lock2->lf_start - 1; 697 lock2->lf_next = lock1->lf_next; 698 lock1->lf_next = lock2; 699 return; 700 } 701 /* 702 * Make a new lock consisting of the last part of 703 * the encompassing lock 704 */ 705 MALLOC(splitlock, struct lockf *, sizeof(*splitlock), M_LOCKF, M_WAITOK); 706 memcpy((caddr_t)splitlock, (caddr_t)lock1, sizeof(*splitlock)); 707 splitlock->lf_start = lock2->lf_end + 1; 708 TAILQ_INIT(&splitlock->lf_blkhd); 709 lock1->lf_end = lock2->lf_start - 1; 710 /* 711 * OK, now link it in 712 */ 713 splitlock->lf_next = lock1->lf_next; 714 lock2->lf_next = splitlock; 715 lock1->lf_next = lock2; 716 } 717 718 /* 719 * Wakeup a blocklist 720 */ 721 void 722 lf_wakelock(listhead) 723 struct lockf *listhead; 724 { 725 struct lockf *wakelock; 726 727 while ((wakelock = TAILQ_FIRST(&listhead->lf_blkhd))) { 728 KASSERT(wakelock->lf_next == listhead); 729 TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block); 730 wakelock->lf_next = NOLOCKF; 731 #ifdef LOCKF_DEBUG 732 if (lockf_debug & 2) 733 lf_print("lf_wakelock: awakening", wakelock); 734 #endif 735 wakeup((caddr_t)wakelock); 736 } 737 } 738 739 #ifdef LOCKF_DEBUG 740 /* 741 * Print out a lock. 742 */ 743 void 744 lf_print(tag, lock) 745 char *tag; 746 struct lockf *lock; 747 { 748 749 printf("%s: lock %p for ", tag, lock); 750 if (lock->lf_flags & F_POSIX) 751 printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid); 752 else 753 printf("id 0x%p", lock->lf_id); 754 printf(" %s, start %qx, end %qx", 755 lock->lf_type == F_RDLCK ? "shared" : 756 lock->lf_type == F_WRLCK ? "exclusive" : 757 lock->lf_type == F_UNLCK ? "unlock" : 758 "unknown", lock->lf_start, lock->lf_end); 759 if (TAILQ_FIRST(&lock->lf_blkhd)) 760 printf(" block %p\n", TAILQ_FIRST(&lock->lf_blkhd)); 761 else 762 printf("\n"); 763 } 764 765 void 766 lf_printlist(tag, lock) 767 char *tag; 768 struct lockf *lock; 769 { 770 struct lockf *lf, *blk; 771 772 printf("%s: Lock list:\n", tag); 773 for (lf = *lock->lf_head; lf; lf = lf->lf_next) { 774 printf("\tlock %p for ", lf); 775 if (lf->lf_flags & F_POSIX) 776 printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid); 777 else 778 printf("id 0x%p", lf->lf_id); 779 printf(", %s, start %qx, end %qx", 780 lf->lf_type == F_RDLCK ? "shared" : 781 lf->lf_type == F_WRLCK ? "exclusive" : 782 lf->lf_type == F_UNLCK ? "unlock" : 783 "unknown", lf->lf_start, lf->lf_end); 784 TAILQ_FOREACH(blk, &lf->lf_blkhd, lf_block) { 785 if (blk->lf_flags & F_POSIX) 786 printf("proc %d", 787 ((struct proc *)(blk->lf_id))->p_pid); 788 else 789 printf("id 0x%p", blk->lf_id); 790 printf(", %s, start %qx, end %qx", 791 blk->lf_type == F_RDLCK ? "shared" : 792 blk->lf_type == F_WRLCK ? "exclusive" : 793 blk->lf_type == F_UNLCK ? "unlock" : 794 "unknown", blk->lf_start, blk->lf_end); 795 if (TAILQ_FIRST(&blk->lf_blkhd)) 796 panic("lf_printlist: bad list"); 797 } 798 printf("\n"); 799 } 800 } 801 #endif /* LOCKF_DEBUG */ 802