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