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