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