vfs_lockf.c revision 1.4
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 * from: @(#)ufs_lockf.c 8.3 (Berkeley) 1/6/94 37 * $Id: vfs_lockf.c,v 1.4 1994/05/19 06:13:50 mycroft 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 * Do an advisory lock operation. 52 */ 53int 54lf_advlock(head, size, id, op, fl, flags) 55 struct lockf **head; 56 off_t size; 57 caddr_t id; 58 int op; 59 register struct flock *fl; 60 int flags; 61{ 62 register struct lockf *lock; 63 off_t start, end; 64 int error; 65 66 /* 67 * Avoid the common case of unlocking when inode has no locks. 68 */ 69 if (*head == (struct lockf *)0) { 70 if (op != F_SETLK) { 71 fl->l_type = F_UNLCK; 72 return (0); 73 } 74 } 75 /* 76 * Convert the flock structure into a start and end. 77 */ 78 switch (fl->l_whence) { 79 80 case SEEK_SET: 81 case SEEK_CUR: 82 /* 83 * Caller is responsible for adding any necessary offset 84 * when SEEK_CUR is used. 85 */ 86 start = fl->l_start; 87 break; 88 89 case SEEK_END: 90 start = size + fl->l_start; 91 break; 92 93 default: 94 return (EINVAL); 95 } 96 if (start < 0) 97 return (EINVAL); 98 if (fl->l_len == 0) 99 end = -1; 100 else 101 end = start + fl->l_len - 1; 102 /* 103 * Create the lockf structure. 104 */ 105 MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK); 106 lock->lf_start = start; 107 lock->lf_end = end; 108 lock->lf_id = id; 109 lock->lf_head = head; 110 lock->lf_type = fl->l_type; 111 lock->lf_next = (struct lockf *)0; 112 lock->lf_block = (struct lockf *)0; 113 lock->lf_flags = flags; 114 /* 115 * Do the requested operation. 116 */ 117 switch (op) { 118 119 case F_SETLK: 120 return (lf_setlock(lock)); 121 122 case F_UNLCK: 123 error = lf_clearlock(lock); 124 FREE(lock, M_LOCKF); 125 return (error); 126 127 case F_GETLK: 128 error = lf_getlock(lock, fl); 129 FREE(lock, M_LOCKF); 130 return (error); 131 132 default: 133 FREE(lock, M_LOCKF); 134 return (EINVAL); 135 } 136 /* NOTREACHED */ 137} 138 139/* 140 * This variable controls the maximum number of processes that will 141 * be checked in doing deadlock detection. 142 */ 143int maxlockdepth = MAXDEPTH; 144 145#ifdef LOCKF_DEBUG 146int lockf_debug = 0; 147#endif 148 149#define NOLOCKF (struct lockf *)0 150#define SELF 0x1 151#define OTHERS 0x2 152 153/* 154 * Set a byte-range lock. 155 */ 156int 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 break; 256 } 257 /* 258 * If we did not find ourselves on the list, but 259 * are still linked onto a lock list, then something 260 * is very wrong. 261 */ 262 if (block == NOLOCKF && lock->lf_next != NOLOCKF) 263 panic("lf_setlock: lost lock"); 264 free(lock, M_LOCKF); 265 return (error); 266 } 267 } 268 /* 269 * No blocks!! Add the lock. Note that we will 270 * downgrade or upgrade any overlapping locks this 271 * process already owns. 272 * 273 * Skip over locks owned by other processes. 274 * Handle any locks that overlap and are owned by ourselves. 275 */ 276 prev = head; 277 block = *head; 278 needtolink = 1; 279 for (;;) { 280 if (ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap)) 281 block = overlap->lf_next; 282 /* 283 * Six cases: 284 * 0) no overlap 285 * 1) overlap == lock 286 * 2) overlap contains lock 287 * 3) lock contains overlap 288 * 4) overlap starts before lock 289 * 5) overlap ends after lock 290 */ 291 switch (ovcase) { 292 case 0: /* no overlap */ 293 if (needtolink) { 294 *prev = lock; 295 lock->lf_next = overlap; 296 } 297 break; 298 299 case 1: /* overlap == lock */ 300 /* 301 * If downgrading lock, others may be 302 * able to acquire it. 303 */ 304 if (lock->lf_type == F_RDLCK && 305 overlap->lf_type == F_WRLCK) 306 lf_wakelock(overlap); 307 overlap->lf_type = lock->lf_type; 308 FREE(lock, M_LOCKF); 309 lock = overlap; /* for debug output below */ 310 break; 311 312 case 2: /* overlap contains lock */ 313 /* 314 * Check for common starting point and different types. 315 */ 316 if (overlap->lf_type == lock->lf_type) { 317 free(lock, M_LOCKF); 318 lock = overlap; /* for debug output below */ 319 break; 320 } 321 if (overlap->lf_start == lock->lf_start) { 322 *prev = lock; 323 lock->lf_next = overlap; 324 overlap->lf_start = lock->lf_end + 1; 325 } else 326 lf_split(overlap, lock); 327 lf_wakelock(overlap); 328 break; 329 330 case 3: /* lock contains overlap */ 331 /* 332 * If downgrading lock, others may be able to 333 * acquire it, otherwise take the list. 334 */ 335 if (lock->lf_type == F_RDLCK && 336 overlap->lf_type == F_WRLCK) { 337 lf_wakelock(overlap); 338 } else { 339 ltmp = lock->lf_block; 340 lock->lf_block = overlap->lf_block; 341 lf_addblock(lock, ltmp); 342 } 343 /* 344 * Add the new lock if necessary and delete the overlap. 345 */ 346 if (needtolink) { 347 *prev = lock; 348 lock->lf_next = overlap->lf_next; 349 prev = &lock->lf_next; 350 needtolink = 0; 351 } else 352 *prev = overlap->lf_next; 353 free(overlap, M_LOCKF); 354 continue; 355 356 case 4: /* overlap starts before lock */ 357 /* 358 * Add lock after overlap on the list. 359 */ 360 lock->lf_next = overlap->lf_next; 361 overlap->lf_next = lock; 362 overlap->lf_end = lock->lf_start - 1; 363 prev = &lock->lf_next; 364 lf_wakelock(overlap); 365 needtolink = 0; 366 continue; 367 368 case 5: /* overlap ends after lock */ 369 /* 370 * Add the new lock before overlap. 371 */ 372 if (needtolink) { 373 *prev = lock; 374 lock->lf_next = overlap; 375 } 376 overlap->lf_start = lock->lf_end + 1; 377 lf_wakelock(overlap); 378 break; 379 } 380 break; 381 } 382#ifdef LOCKF_DEBUG 383 if (lockf_debug & 1) { 384 lf_print("lf_setlock: got the lock", lock); 385 lf_printlist("lf_setlock", lock); 386 } 387#endif /* LOCKF_DEBUG */ 388 return (0); 389} 390 391/* 392 * Remove a byte-range lock on an inode. 393 * 394 * Generally, find the lock (or an overlap to that lock) 395 * and remove it (or shrink it), then wakeup anyone we can. 396 */ 397int 398lf_clearlock(unlock) 399 register struct lockf *unlock; 400{ 401 struct lockf **head = unlock->lf_head; 402 register struct lockf *lf = *head; 403 struct lockf *overlap, **prev; 404 int ovcase; 405 406 if (lf == NOLOCKF) 407 return (0); 408#ifdef LOCKF_DEBUG 409 if (unlock->lf_type != F_UNLCK) 410 panic("lf_clearlock: bad type"); 411 if (lockf_debug & 1) 412 lf_print("lf_clearlock", unlock); 413#endif /* LOCKF_DEBUG */ 414 prev = head; 415 while (ovcase = lf_findoverlap(lf, unlock, SELF, &prev, &overlap)) { 416 /* 417 * Wakeup the list of locks to be retried. 418 */ 419 lf_wakelock(overlap); 420 421 switch (ovcase) { 422 423 case 1: /* overlap == lock */ 424 *prev = overlap->lf_next; 425 FREE(overlap, M_LOCKF); 426 break; 427 428 case 2: /* overlap contains lock: split it */ 429 if (overlap->lf_start == unlock->lf_start) { 430 overlap->lf_start = unlock->lf_end + 1; 431 break; 432 } 433 lf_split(overlap, unlock); 434 overlap->lf_next = unlock->lf_next; 435 break; 436 437 case 3: /* lock contains overlap */ 438 *prev = overlap->lf_next; 439 lf = overlap->lf_next; 440 free(overlap, M_LOCKF); 441 continue; 442 443 case 4: /* overlap starts before lock */ 444 overlap->lf_end = unlock->lf_start - 1; 445 prev = &overlap->lf_next; 446 lf = overlap->lf_next; 447 continue; 448 449 case 5: /* overlap ends after lock */ 450 overlap->lf_start = unlock->lf_end + 1; 451 break; 452 } 453 break; 454 } 455#ifdef LOCKF_DEBUG 456 if (lockf_debug & 1) 457 lf_printlist("lf_clearlock", unlock); 458#endif /* LOCKF_DEBUG */ 459 return (0); 460} 461 462/* 463 * Check whether there is a blocking lock, 464 * and if so return its process identifier. 465 */ 466int 467lf_getlock(lock, fl) 468 register struct lockf *lock; 469 register struct flock *fl; 470{ 471 register struct lockf *block; 472 473#ifdef LOCKF_DEBUG 474 if (lockf_debug & 1) 475 lf_print("lf_getlock", lock); 476#endif /* LOCKF_DEBUG */ 477 478 if (block = lf_getblock(lock)) { 479 fl->l_type = block->lf_type; 480 fl->l_whence = SEEK_SET; 481 fl->l_start = block->lf_start; 482 if (block->lf_end == -1) 483 fl->l_len = 0; 484 else 485 fl->l_len = block->lf_end - block->lf_start + 1; 486 if (block->lf_flags & F_POSIX) 487 fl->l_pid = ((struct proc *)(block->lf_id))->p_pid; 488 else 489 fl->l_pid = -1; 490 } else { 491 fl->l_type = F_UNLCK; 492 } 493 return (0); 494} 495 496/* 497 * Walk the list of locks for an inode and 498 * return the first blocking lock. 499 */ 500struct lockf * 501lf_getblock(lock) 502 register struct lockf *lock; 503{ 504 struct lockf **prev, *overlap, *lf = *(lock->lf_head); 505 int ovcase; 506 507 prev = lock->lf_head; 508 while (ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap)) { 509 /* 510 * We've found an overlap, see if it blocks us 511 */ 512 if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) 513 return (overlap); 514 /* 515 * Nope, point to the next one on the list and 516 * see if it blocks us 517 */ 518 lf = overlap->lf_next; 519 } 520 return (NOLOCKF); 521} 522 523/* 524 * Walk the list of locks for an inode to 525 * find an overlapping lock (if any). 526 * 527 * NOTE: this returns only the FIRST overlapping lock. There 528 * may be more than one. 529 */ 530int 531lf_findoverlap(lf, lock, type, prev, overlap) 532 register struct lockf *lf; 533 struct lockf *lock; 534 int type; 535 struct lockf ***prev; 536 struct lockf **overlap; 537{ 538 off_t start, end; 539 540 *overlap = lf; 541 if (lf == NOLOCKF) 542 return (0); 543#ifdef LOCKF_DEBUG 544 if (lockf_debug & 2) 545 lf_print("lf_findoverlap: looking for overlap in", lock); 546#endif /* LOCKF_DEBUG */ 547 start = lock->lf_start; 548 end = lock->lf_end; 549 while (lf != NOLOCKF) { 550 if (((type & SELF) && lf->lf_id != lock->lf_id) || 551 ((type & OTHERS) && lf->lf_id == lock->lf_id)) { 552 *prev = &lf->lf_next; 553 *overlap = lf = lf->lf_next; 554 continue; 555 } 556#ifdef LOCKF_DEBUG 557 if (lockf_debug & 2) 558 lf_print("\tchecking", lf); 559#endif /* LOCKF_DEBUG */ 560 /* 561 * OK, check for overlap 562 * 563 * Six cases: 564 * 0) no overlap 565 * 1) overlap == lock 566 * 2) overlap contains lock 567 * 3) lock contains overlap 568 * 4) overlap starts before lock 569 * 5) overlap ends after lock 570 */ 571 if ((lf->lf_end != -1 && start > lf->lf_end) || 572 (end != -1 && lf->lf_start > end)) { 573 /* Case 0 */ 574#ifdef LOCKF_DEBUG 575 if (lockf_debug & 2) 576 printf("no overlap\n"); 577#endif /* LOCKF_DEBUG */ 578 if ((type & SELF) && end != -1 && lf->lf_start > end) 579 return (0); 580 *prev = &lf->lf_next; 581 *overlap = lf = lf->lf_next; 582 continue; 583 } 584 if ((lf->lf_start == start) && (lf->lf_end == end)) { 585 /* Case 1 */ 586#ifdef LOCKF_DEBUG 587 if (lockf_debug & 2) 588 printf("overlap == lock\n"); 589#endif /* LOCKF_DEBUG */ 590 return (1); 591 } 592 if ((lf->lf_start <= start) && 593 (end != -1) && 594 ((lf->lf_end >= end) || (lf->lf_end == -1))) { 595 /* Case 2 */ 596#ifdef LOCKF_DEBUG 597 if (lockf_debug & 2) 598 printf("overlap contains lock\n"); 599#endif /* LOCKF_DEBUG */ 600 return (2); 601 } 602 if (start <= lf->lf_start && 603 (end == -1 || 604 (lf->lf_end != -1 && end >= lf->lf_end))) { 605 /* Case 3 */ 606#ifdef LOCKF_DEBUG 607 if (lockf_debug & 2) 608 printf("lock contains overlap\n"); 609#endif /* LOCKF_DEBUG */ 610 return (3); 611 } 612 if ((lf->lf_start < start) && 613 ((lf->lf_end >= start) || (lf->lf_end == -1))) { 614 /* Case 4 */ 615#ifdef LOCKF_DEBUG 616 if (lockf_debug & 2) 617 printf("overlap starts before lock\n"); 618#endif /* LOCKF_DEBUG */ 619 return (4); 620 } 621 if ((lf->lf_start > start) && 622 (end != -1) && 623 ((lf->lf_end > end) || (lf->lf_end == -1))) { 624 /* Case 5 */ 625#ifdef LOCKF_DEBUG 626 if (lockf_debug & 2) 627 printf("overlap ends after lock\n"); 628#endif /* LOCKF_DEBUG */ 629 return (5); 630 } 631 panic("lf_findoverlap: default"); 632 } 633 return (0); 634} 635 636/* 637 * Add a lock to the end of the blocked list. 638 */ 639void 640lf_addblock(lock, blocked) 641 struct lockf *lock; 642 struct lockf *blocked; 643{ 644 register struct lockf *lf; 645 646 if (blocked == NOLOCKF) 647 return; 648#ifdef LOCKF_DEBUG 649 if (lockf_debug & 2) { 650 lf_print("addblock: adding", blocked); 651 lf_print("to blocked list of", lock); 652 } 653#endif /* LOCKF_DEBUG */ 654 if ((lf = lock->lf_block) == NOLOCKF) { 655 lock->lf_block = blocked; 656 return; 657 } 658 while (lf->lf_block != NOLOCKF) 659 lf = lf->lf_block; 660 lf->lf_block = blocked; 661 return; 662} 663 664/* 665 * Split a lock and a contained region into 666 * two or three locks as necessary. 667 */ 668void 669lf_split(lock1, lock2) 670 register struct lockf *lock1; 671 register struct lockf *lock2; 672{ 673 register struct lockf *splitlock; 674 675#ifdef LOCKF_DEBUG 676 if (lockf_debug & 2) { 677 lf_print("lf_split", lock1); 678 lf_print("splitting from", lock2); 679 } 680#endif /* LOCKF_DEBUG */ 681 /* 682 * Check to see if spliting into only two pieces. 683 */ 684 if (lock1->lf_start == lock2->lf_start) { 685 lock1->lf_start = lock2->lf_end + 1; 686 lock2->lf_next = lock1; 687 return; 688 } 689 if (lock1->lf_end == lock2->lf_end) { 690 lock1->lf_end = lock2->lf_start - 1; 691 lock2->lf_next = lock1->lf_next; 692 lock1->lf_next = lock2; 693 return; 694 } 695 /* 696 * Make a new lock consisting of the last part of 697 * the encompassing lock 698 */ 699 MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK); 700 bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock); 701 splitlock->lf_start = lock2->lf_end + 1; 702 splitlock->lf_block = NOLOCKF; 703 lock1->lf_end = lock2->lf_start - 1; 704 /* 705 * OK, now link it in 706 */ 707 splitlock->lf_next = lock1->lf_next; 708 lock2->lf_next = splitlock; 709 lock1->lf_next = lock2; 710} 711 712/* 713 * Wakeup a blocklist 714 */ 715void 716lf_wakelock(listhead) 717 struct lockf *listhead; 718{ 719 register struct lockf *blocklist, *wakelock; 720 721 blocklist = listhead->lf_block; 722 listhead->lf_block = NOLOCKF; 723 while (blocklist != NOLOCKF) { 724 wakelock = blocklist; 725 blocklist = blocklist->lf_block; 726 wakelock->lf_block = NOLOCKF; 727 wakelock->lf_next = NOLOCKF; 728#ifdef LOCKF_DEBUG 729 if (lockf_debug & 2) 730 lf_print("lf_wakelock: awakening", wakelock); 731#endif /* LOCKF_DEBUG */ 732 wakeup((caddr_t)wakelock); 733 } 734} 735 736#ifdef LOCKF_DEBUG 737/* 738 * Print out a lock. 739 */ 740void 741lf_print(tag, lock) 742 char *tag; 743 register struct lockf *lock; 744{ 745 746 printf("%s: lock 0x%lx for ", tag, lock); 747 if (lock->lf_flags & F_POSIX) 748 printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid); 749 else 750 printf("id 0x%x", lock->lf_id); 751 printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d", 752 lock->lf_inode->i_number, 753 major(lock->lf_inode->i_dev), 754 minor(lock->lf_inode->i_dev), 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 (lock->lf_block) 760 printf(" block 0x%x\n", lock->lf_block); 761 else 762 printf("\n"); 763} 764 765void 766lf_printlist(tag, lock) 767 char *tag; 768 struct lockf *lock; 769{ 770 register struct lockf *lf; 771 772 printf("%s: Lock list for ino %d on dev <%d, %d>:\n", 773 tag, lock->lf_inode->i_number, 774 major(lock->lf_inode->i_dev), 775 minor(lock->lf_inode->i_dev)); 776 for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) { 777 printf("\tlock 0x%lx for ", lf); 778 if (lf->lf_flags & F_POSIX) 779 printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid); 780 else 781 printf("id 0x%x", lf->lf_id); 782 printf(", %s, start %d, end %d", 783 lf->lf_type == F_RDLCK ? "shared" : 784 lf->lf_type == F_WRLCK ? "exclusive" : 785 lf->lf_type == F_UNLCK ? "unlock" : 786 "unknown", lf->lf_start, lf->lf_end); 787 if (lf->lf_block) 788 printf(" block 0x%x\n", lf->lf_block); 789 else 790 printf("\n"); 791 } 792} 793#endif /* LOCKF_DEBUG */ 794