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