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