vfs_lockf.c revision 1.1
1/* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * 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 * from: @(#)ufs_lockf.c 7.7 (Berkeley) 7/2/91 37 * $Id: vfs_lockf.c,v 1.1 1994/03/09 21:23:50 ws Exp $ 38 */ 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/kernel.h> 43#include <sys/file.h> 44#include <sys/proc.h> 45#include <sys/vnode.h> 46#include <sys/malloc.h> 47#include <sys/fcntl.h> 48#include <sys/lockf.h> 49 50 51 52/* 53 * Advisory record locking support 54 */ 55lf_advlock(head, size, id, op, fl, flags) 56 struct lockf **head; 57 u_long size; 58 caddr_t id; 59 int op; 60 register struct flock *fl; 61 int flags; 62{ 63 register struct lockf *lock; 64 off_t start, end; 65 int error; 66 67 /* 68 * Avoid the common case of unlocking when inode has no locks. 69 */ 70 if (*head == (struct lockf *)0) { 71 if (op != F_SETLK) { 72 fl->l_type = F_UNLCK; 73 return (0); 74 } 75 } 76 77 /* 78 * Convert the flock structure into a start and end. 79 */ 80 switch (fl->l_whence) { 81 82 case SEEK_SET: 83 case SEEK_CUR: 84 /* 85 * Caller is responsible for adding any necessary offset 86 * when SEEK_CUR is used. 87 */ 88 start = fl->l_start; 89 break; 90 91 case SEEK_END: 92 start = size + fl->l_start; 93 break; 94 95 default: 96 return (EINVAL); 97 } 98 if (start < 0) 99 return (EINVAL); 100 if (fl->l_len == 0) 101 end = -1; 102 else 103 end = start + fl->l_len - 1; 104 /* 105 * Create the lockf structure 106 */ 107 MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK); 108 lock->lf_start = start; 109 lock->lf_end = end; 110 lock->lf_id = id; 111 lock->lf_head = head; 112 lock->lf_type = fl->l_type; 113 lock->lf_next = (struct lockf *)0; 114 lock->lf_block = (struct lockf *)0; 115 lock->lf_flags = flags; 116 /* 117 * Do the requested operation. 118 */ 119 switch(op) { 120 case F_SETLK: 121 return (lf_setlock(lock)); 122 123 case F_UNLCK: 124 error = lf_clearlock(lock); 125 FREE(lock, M_LOCKF); 126 return (error); 127 128 case F_GETLK: 129 error = lf_getlock(lock, fl); 130 FREE(lock, M_LOCKF); 131 return (error); 132 133 default: 134 free(lock, M_LOCKF); 135 return (EINVAL); 136 } 137 /* NOTREACHED */ 138} 139 140/* 141 * This variable controls the maximum number of processes that will 142 * be checked in doing deadlock detection. 143 */ 144int maxlockdepth = MAXDEPTH; 145 146#ifdef LOCKF_DEBUG 147int lockf_debug = 0; 148#endif /* LOCKF_DEBUG */ 149 150#define NOLOCKF (struct lockf *)0 151#define SELF 0x1 152#define OTHERS 0x2 153 154/* 155 * Set a byte-range lock. 156 */ 157lf_setlock(lock) 158 register struct lockf *lock; 159{ 160 register struct lockf *block; 161 struct lockf **head = lock->lf_head; 162 struct lockf **prev, *overlap, *ltmp; 163 static char lockstr[] = "lockf"; 164 int ovcase, priority, needtolink, error; 165 166#ifdef LOCKF_DEBUG 167 if (lockf_debug & 1) 168 lf_print("lf_setlock", lock); 169#endif /* LOCKF_DEBUG */ 170 171 /* 172 * Set the priority 173 */ 174 priority = PLOCK; 175 if (lock->lf_type == F_WRLCK) 176 priority += 4; 177 priority |= PCATCH; 178 /* 179 * Scan lock list for this file looking for locks that would block us. 180 */ 181 while (block = lf_getblock(lock)) { 182 /* 183 * Free the structure and return if nonblocking. 184 */ 185 if ((lock->lf_flags & F_WAIT) == 0) { 186 FREE(lock, M_LOCKF); 187 return (EAGAIN); 188 } 189 /* 190 * We are blocked. Since flock style locks cover 191 * the whole file, there is no chance for deadlock. 192 * For byte-range locks we must check for deadlock. 193 * 194 * Deadlock detection is done by looking through the 195 * wait channels to see if there are any cycles that 196 * involve us. MAXDEPTH is set just to make sure we 197 * do not go off into neverland. 198 */ 199 if ((lock->lf_flags & F_POSIX) && 200 (block->lf_flags & F_POSIX)) { 201 register struct proc *wproc; 202 register struct lockf *waitblock; 203 int i = 0; 204 205 /* The block is waiting on something */ 206 wproc = (struct proc *)block->lf_id; 207 while (wproc->p_wchan && 208 (wproc->p_wmesg == lockstr) && 209 (i++ < maxlockdepth)) { 210 waitblock = (struct lockf *)wproc->p_wchan; 211 /* Get the owner of the blocking lock */ 212 waitblock = waitblock->lf_next; 213 if ((waitblock->lf_flags & F_POSIX) == 0) 214 break; 215 wproc = (struct proc *)waitblock->lf_id; 216 if (wproc == (struct proc *)lock->lf_id) { 217 free(lock, M_LOCKF); 218 return (EDEADLK); 219 } 220 } 221 } 222 /* 223 * For flock type locks, we must first remove 224 * any shared locks that we hold before we sleep 225 * waiting for an exclusive lock. 226 */ 227 if ((lock->lf_flags & F_FLOCK) && 228 lock->lf_type == F_WRLCK) { 229 lock->lf_type = F_UNLCK; 230 (void) lf_clearlock(lock); 231 lock->lf_type = F_WRLCK; 232 } 233 /* 234 * Add our lock to the blocked list and sleep until we're free. 235 * Remember who blocked us (for deadlock detection). 236 */ 237 lock->lf_next = block; 238 lf_addblock(block, lock); 239#ifdef LOCKF_DEBUG 240 if (lockf_debug & 1) { 241 lf_print("lf_setlock: blocking on", block); 242 lf_printlist("lf_setlock", block); 243 } 244#endif /* LOCKF_DEBUG */ 245 if (error = tsleep((caddr_t)lock, priority, lockstr, 0)) { 246 /* 247 * Delete ourselves from the waiting to lock list. 248 */ 249 for (block = lock->lf_next; 250 block != NOLOCKF; 251 block = block->lf_block) { 252 if (block->lf_block != lock) 253 continue; 254 block->lf_block = block->lf_block->lf_block; 255 free(lock, M_LOCKF); 256 return (error); 257 } 258 panic("lf_setlock: lost lock"); 259 } 260 } 261 /* 262 * No blocks!! Add the lock. Note that we will 263 * downgrade or upgrade any overlapping locks this 264 * process already owns. 265 * 266 * Skip over locks owned by other processes. 267 * Handle any locks that overlap and are owned by ourselves. 268 */ 269 prev = head; 270 block = *head; 271 needtolink = 1; 272 for (;;) { 273 if (ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap)) 274 block = overlap->lf_next; 275 /* 276 * Six cases: 277 * 0) no overlap 278 * 1) overlap == lock 279 * 2) overlap contains lock 280 * 3) lock contains overlap 281 * 4) overlap starts before lock 282 * 5) overlap ends after lock 283 */ 284 switch (ovcase) { 285 case 0: /* no overlap */ 286 if (needtolink) { 287 *prev = lock; 288 lock->lf_next = overlap; 289 } 290 break; 291 292 case 1: /* overlap == lock */ 293 /* 294 * If downgrading lock, others may be 295 * able to acquire it. 296 */ 297 if (lock->lf_type == F_RDLCK && 298 overlap->lf_type == F_WRLCK) 299 lf_wakelock(overlap); 300 overlap->lf_type = lock->lf_type; 301 FREE(lock, M_LOCKF); 302 lock = overlap; /* for debug output below */ 303 break; 304 305 case 2: /* overlap contains lock */ 306 /* 307 * Check for common starting point and different types. 308 */ 309 if (overlap->lf_type == lock->lf_type) { 310 free(lock, M_LOCKF); 311 lock = overlap; /* for debug output below */ 312 break; 313 } 314 if (overlap->lf_start == lock->lf_start) { 315 *prev = lock; 316 lock->lf_next = overlap; 317 overlap->lf_start = lock->lf_end + 1; 318 } else 319 lf_split(overlap, lock); 320 lf_wakelock(overlap); 321 break; 322 323 case 3: /* lock contains overlap */ 324 /* 325 * If downgrading lock, others may be able to 326 * acquire it, otherwise take the list. 327 */ 328 if (lock->lf_type == F_RDLCK && 329 overlap->lf_type == F_WRLCK) { 330 lf_wakelock(overlap); 331 } else { 332 ltmp = lock->lf_block; 333 lock->lf_block = overlap->lf_block; 334 lf_addblock(lock, ltmp); 335 } 336 /* 337 * Add the new lock if necessary and delete the overlap. 338 */ 339 if (needtolink) { 340 *prev = lock; 341 lock->lf_next = overlap->lf_next; 342 prev = &lock->lf_next; 343 needtolink = 0; 344 } else 345 *prev = overlap->lf_next; 346 free(overlap, M_LOCKF); 347 continue; 348 349 case 4: /* overlap starts before lock */ 350 /* 351 * Add lock after overlap on the list. 352 */ 353 lock->lf_next = overlap->lf_next; 354 overlap->lf_next = lock; 355 overlap->lf_end = lock->lf_start - 1; 356 prev = &lock->lf_next; 357 lf_wakelock(overlap); 358 needtolink = 0; 359 continue; 360 361 case 5: /* overlap ends after lock */ 362 /* 363 * Add the new lock before overlap. 364 */ 365 if (needtolink) { 366 *prev = lock; 367 lock->lf_next = overlap; 368 } 369 overlap->lf_start = lock->lf_end + 1; 370 lf_wakelock(overlap); 371 break; 372 } 373 break; 374 } 375#ifdef LOCKF_DEBUG 376 if (lockf_debug & 1) { 377 lf_print("lf_setlock: got the lock", lock); 378 lf_printlist("lf_setlock", lock); 379 } 380#endif /* LOCKF_DEBUG */ 381 return (0); 382} 383 384/* 385 * Remove a byte-range lock on an inode. 386 * 387 * Generally, find the lock (or an overlap to that lock) 388 * and remove it (or shrink it), then wakeup anyone we can. 389 */ 390lf_clearlock(unlock) 391 register struct lockf *unlock; 392{ 393 struct lockf **head = unlock->lf_head; 394 register struct lockf *lf = *head; 395 struct lockf *overlap, **prev; 396 int ovcase; 397 398 if (lf == NOLOCKF) 399 return (0); 400#ifdef LOCKF_DEBUG 401 if (unlock->lf_type != F_UNLCK) 402 panic("lf_clearlock: bad type"); 403 if (lockf_debug & 1) 404 lf_print("lf_clearlock", unlock); 405#endif /* LOCKF_DEBUG */ 406 prev = head; 407 while (ovcase = lf_findoverlap(lf, unlock, SELF, &prev, &overlap)) { 408 /* 409 * Wakeup the list of locks to be retried. 410 */ 411 lf_wakelock(overlap); 412 413 switch (ovcase) { 414 415 case 1: /* overlap == lock */ 416 *prev = overlap->lf_next; 417 FREE(overlap, M_LOCKF); 418 break; 419 420 case 2: /* overlap contains lock: split it */ 421 if (overlap->lf_start == unlock->lf_start) { 422 overlap->lf_start = unlock->lf_end + 1; 423 break; 424 } 425 lf_split(overlap, unlock); 426 overlap->lf_next = unlock->lf_next; 427 break; 428 429 case 3: /* lock contains overlap */ 430 *prev = overlap->lf_next; 431 lf = overlap->lf_next; 432 free(overlap, M_LOCKF); 433 continue; 434 435 case 4: /* overlap starts before lock */ 436 overlap->lf_end = unlock->lf_start - 1; 437 prev = &overlap->lf_next; 438 lf = overlap->lf_next; 439 continue; 440 441 case 5: /* overlap ends after lock */ 442 overlap->lf_start = unlock->lf_end + 1; 443 break; 444 } 445 break; 446 } 447#ifdef LOCKF_DEBUG 448 if (lockf_debug & 1) 449 lf_printlist("lf_clearlock", unlock); 450#endif /* LOCKF_DEBUG */ 451 return (0); 452} 453 454/* 455 * Check whether there is a blocking lock, 456 * and if so return its process identifier. 457 */ 458lf_getlock(lock, fl) 459 register struct lockf *lock; 460 register struct flock *fl; 461{ 462 register struct lockf *block; 463 off_t start, end; 464 465#ifdef LOCKF_DEBUG 466 if (lockf_debug & 1) 467 lf_print("lf_getlock", lock); 468#endif /* LOCKF_DEBUG */ 469 470 if (block = lf_getblock(lock)) { 471 fl->l_type = block->lf_type; 472 fl->l_whence = SEEK_SET; 473 fl->l_start = block->lf_start; 474 if (block->lf_end == -1) 475 fl->l_len = 0; 476 else 477 fl->l_len = block->lf_end - block->lf_start + 1; 478 if (block->lf_flags & F_POSIX) 479 fl->l_pid = ((struct proc *)(block->lf_id))->p_pid; 480 else 481 fl->l_pid = -1; 482 } else { 483 fl->l_type = F_UNLCK; 484 } 485 return (0); 486} 487 488/* 489 * Walk the list of locks for an inode and 490 * return the first blocking lock. 491 */ 492struct lockf * 493lf_getblock(lock) 494 register struct lockf *lock; 495{ 496 struct lockf **prev, *overlap, *lf = *(lock->lf_head); 497 int ovcase; 498 499 prev = lock->lf_head; 500 while (ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap)) { 501 /* 502 * We've found an overlap, see if it blocks us 503 */ 504 if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) 505 return (overlap); 506 /* 507 * Nope, point to the next one on the list and 508 * see if it blocks us 509 */ 510 lf = overlap->lf_next; 511 } 512 return (NOLOCKF); 513} 514 515/* 516 * Walk the list of locks for an inode to 517 * find an overlapping lock (if any). 518 * 519 * NOTE: this returns only the FIRST overlapping lock. There 520 * may be more than one. 521 */ 522lf_findoverlap(lf, lock, type, prev, overlap) 523 register struct lockf *lf; 524 struct lockf *lock; 525 int type; 526 struct lockf ***prev; 527 struct lockf **overlap; 528{ 529 off_t start, end; 530 531 *overlap = lf; 532 if (lf == NOLOCKF) 533 return (0); 534#ifdef LOCKF_DEBUG 535 if (lockf_debug & 2) 536 lf_print("lf_findoverlap: looking for overlap in", lock); 537#endif /* LOCKF_DEBUG */ 538 start = lock->lf_start; 539 end = lock->lf_end; 540 while (lf != NOLOCKF) { 541 if (((type & SELF) && lf->lf_id != lock->lf_id) || 542 ((type & OTHERS) && lf->lf_id == lock->lf_id)) { 543 *prev = &lf->lf_next; 544 *overlap = lf = lf->lf_next; 545 continue; 546 } 547#ifdef LOCKF_DEBUG 548 if (lockf_debug & 2) 549 lf_print("\tchecking", lf); 550#endif /* LOCKF_DEBUG */ 551 /* 552 * OK, check for overlap 553 * 554 * Six cases: 555 * 0) no overlap 556 * 1) overlap == lock 557 * 2) overlap contains lock 558 * 3) lock contains overlap 559 * 4) overlap starts before lock 560 * 5) overlap ends after lock 561 */ 562 if ((lf->lf_end != -1 && start > lf->lf_end) || 563 (end != -1 && lf->lf_start > end)) { 564 /* Case 0 */ 565#ifdef LOCKF_DEBUG 566 if (lockf_debug & 2) 567 printf("no overlap\n"); 568#endif /* LOCKF_DEBUG */ 569 if ((type & SELF) && end != -1 && lf->lf_start > end) 570 return (0); 571 *prev = &lf->lf_next; 572 *overlap = lf = lf->lf_next; 573 continue; 574 } 575 if ((lf->lf_start == start) && (lf->lf_end == end)) { 576 /* Case 1 */ 577#ifdef LOCKF_DEBUG 578 if (lockf_debug & 2) 579 printf("overlap == lock\n"); 580#endif /* LOCKF_DEBUG */ 581 return (1); 582 } 583 if ((lf->lf_start <= start) && 584 (end != -1) && 585 ((lf->lf_end >= end) || (lf->lf_end == -1))) { 586 /* Case 2 */ 587#ifdef LOCKF_DEBUG 588 if (lockf_debug & 2) 589 printf("overlap contains lock\n"); 590#endif /* LOCKF_DEBUG */ 591 return (2); 592 } 593 if (start <= lf->lf_start && 594 (end == -1 || 595 (lf->lf_end != -1 && end >= lf->lf_end))) { 596 /* Case 3 */ 597#ifdef LOCKF_DEBUG 598 if (lockf_debug & 2) 599 printf("lock contains overlap\n"); 600#endif /* LOCKF_DEBUG */ 601 return (3); 602 } 603 if ((lf->lf_start < start) && 604 ((lf->lf_end >= start) || (lf->lf_end == -1))) { 605 /* Case 4 */ 606#ifdef LOCKF_DEBUG 607 if (lockf_debug & 2) 608 printf("overlap starts before lock\n"); 609#endif /* LOCKF_DEBUG */ 610 return (4); 611 } 612 if ((lf->lf_start > start) && 613 (end != -1) && 614 ((lf->lf_end > end) || (lf->lf_end == -1))) { 615 /* Case 5 */ 616#ifdef LOCKF_DEBUG 617 if (lockf_debug & 2) 618 printf("overlap ends after lock\n"); 619#endif /* LOCKF_DEBUG */ 620 return (5); 621 } 622 panic("lf_findoverlap: default"); 623 } 624 return (0); 625} 626 627/* 628 * Add a lock to the end of the blocked list. 629 */ 630lf_addblock(lock, blocked) 631 struct lockf *lock; 632 struct lockf *blocked; 633{ 634 register struct lockf *lf; 635 636 if (blocked == NOLOCKF) 637 return; 638#ifdef LOCKF_DEBUG 639 if (lockf_debug & 2) { 640 lf_print("addblock: adding", blocked); 641 lf_print("to blocked list of", lock); 642 } 643#endif /* LOCKF_DEBUG */ 644 if ((lf = lock->lf_block) == NOLOCKF) { 645 lock->lf_block = blocked; 646 return; 647 } 648 while (lf->lf_block != NOLOCKF) 649 lf = lf->lf_block; 650 lf->lf_block = blocked; 651 return; 652} 653 654/* 655 * Split a lock and a contained region into 656 * two or three locks as necessary. 657 */ 658lf_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 splitlock->lf_block = NOLOCKF; 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 */ 704lf_wakelock(listhead) 705 struct lockf *listhead; 706{ 707 register struct lockf *blocklist, *wakelock; 708 709 blocklist = listhead->lf_block; 710 listhead->lf_block = NOLOCKF; 711 while (blocklist != NOLOCKF) { 712 wakelock = blocklist; 713 blocklist = blocklist->lf_block; 714 wakelock->lf_block = NOLOCKF; 715 wakelock->lf_next = NOLOCKF; 716#ifdef LOCKF_DEBUG 717 if (lockf_debug & 2) 718 lf_print("lf_wakelock: awakening", wakelock); 719#endif /* LOCKF_DEBUG */ 720 wakeup((caddr_t)wakelock); 721 } 722} 723 724#ifdef LOCKF_DEBUG 725/* 726 * Print out a lock. 727 */ 728lf_print(tag, lock) 729 char *tag; 730 register struct lockf *lock; 731{ 732 733 printf("%s: lock 0x%lx for ", tag, lock); 734 if (lock->lf_flags & F_POSIX) 735 printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid); 736 else 737 printf("id 0x%x", lock->lf_id); 738 printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d", 739 lock->lf_inode->i_number, 740 major(lock->lf_inode->i_dev), 741 minor(lock->lf_inode->i_dev), 742 lock->lf_type == F_RDLCK ? "shared" : 743 lock->lf_type == F_WRLCK ? "exclusive" : 744 lock->lf_type == F_UNLCK ? "unlock" : 745 "unknown", lock->lf_start, lock->lf_end); 746 if (lock->lf_block) 747 printf(" block 0x%x\n", lock->lf_block); 748 else 749 printf("\n"); 750} 751 752lf_printlist(tag, lock) 753 char *tag; 754 struct lockf *lock; 755{ 756 register struct lockf *lf; 757 758 printf("%s: Lock list for ino %d on dev <%d, %d>:\n", 759 tag, lock->lf_inode->i_number, 760 major(lock->lf_inode->i_dev), 761 minor(lock->lf_inode->i_dev)); 762 for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) { 763 printf("\tlock 0x%lx for ", lf); 764 if (lf->lf_flags & F_POSIX) 765 printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid); 766 else 767 printf("id 0x%x", lf->lf_id); 768 printf(", %s, start %d, end %d", 769 lf->lf_type == F_RDLCK ? "shared" : 770 lf->lf_type == F_WRLCK ? "exclusive" : 771 lf->lf_type == F_UNLCK ? "unlock" : 772 "unknown", lf->lf_start, lf->lf_end); 773 if (lf->lf_block) 774 printf(" block 0x%x\n", lf->lf_block); 775 else 776 printf("\n"); 777 } 778} 779#endif /* LOCKF_DEBUG */ 780