kern_lockf.c revision 177371
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 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)ufs_lockf.c 8.3 (Berkeley) 1/6/94 33 */ 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD: head/sys/kern/kern_lockf.c 177371 2008-03-19 07:13:24Z jeff $"); 37 38#include "opt_debug_lockf.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/kernel.h> 43#include <sys/limits.h> 44#include <sys/lock.h> 45#include <sys/mount.h> 46#include <sys/mutex.h> 47#include <sys/proc.h> 48#include <sys/unistd.h> 49#include <sys/vnode.h> 50#include <sys/malloc.h> 51#include <sys/fcntl.h> 52#include <sys/lockf.h> 53 54/* 55 * This variable controls the maximum number of processes that will 56 * be checked in doing deadlock detection. 57 */ 58static int maxlockdepth = MAXDEPTH; 59 60#ifdef LOCKF_DEBUG 61#include <sys/sysctl.h> 62 63#include <ufs/ufs/quota.h> 64#include <ufs/ufs/inode.h> 65 66 67static int lockf_debug = 0; 68SYSCTL_INT(_debug, OID_AUTO, lockf_debug, CTLFLAG_RW, &lockf_debug, 0, ""); 69#endif 70 71MALLOC_DEFINE(M_LOCKF, "lockf", "Byte-range locking structures"); 72 73#define NOLOCKF (struct lockf *)0 74#define SELF 0x1 75#define OTHERS 0x2 76static int lf_clearlock(struct lockf *, struct lockf **); 77static int lf_findoverlap(struct lockf *, 78 struct lockf *, int, struct lockf ***, struct lockf **); 79static struct lockf * 80 lf_getblock(struct lockf *); 81static int lf_getlock(struct lockf *, struct flock *); 82static int lf_setlock(struct lockf *, struct vnode *, struct lockf **); 83static void lf_split(struct lockf *, struct lockf *, struct lockf **); 84static void lf_wakelock(struct lockf *); 85#ifdef LOCKF_DEBUG 86static void lf_print(char *, struct lockf *); 87static void lf_printlist(char *, struct lockf *); 88#endif 89 90/* 91 * Advisory record locking support 92 */ 93int 94lf_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 struct flock *fl = ap->a_fl; 106 struct lockf *lock; 107 struct vnode *vp = ap->a_vp; 108 off_t start, end, oadd; 109 struct lockf *clean, *n; 110 int error; 111 112 /* 113 * Convert the flock structure into a start and end. 114 */ 115 switch (fl->l_whence) { 116 117 case SEEK_SET: 118 case SEEK_CUR: 119 /* 120 * Caller is responsible for adding any necessary offset 121 * when SEEK_CUR is used. 122 */ 123 start = fl->l_start; 124 break; 125 126 case SEEK_END: 127 if (size > OFF_MAX || 128 (fl->l_start > 0 && size > OFF_MAX - fl->l_start)) 129 return (EOVERFLOW); 130 start = size + fl->l_start; 131 break; 132 133 default: 134 return (EINVAL); 135 } 136 if (start < 0) 137 return (EINVAL); 138 if (fl->l_len < 0) { 139 if (start == 0) 140 return (EINVAL); 141 end = start - 1; 142 start += fl->l_len; 143 if (start < 0) 144 return (EINVAL); 145 } else if (fl->l_len == 0) 146 end = -1; 147 else { 148 oadd = fl->l_len - 1; 149 if (oadd > OFF_MAX - start) 150 return (EOVERFLOW); 151 end = start + oadd; 152 } 153 /* 154 * Avoid the common case of unlocking when inode has no locks. 155 */ 156 if (*head == (struct lockf *)0) { 157 if (ap->a_op != F_SETLK) { 158 fl->l_type = F_UNLCK; 159 return (0); 160 } 161 } 162 /* 163 * Allocate a spare structure in case we have to split. 164 */ 165 clean = NULL; 166 if (ap->a_op == F_SETLK || ap->a_op == F_UNLCK) { 167 MALLOC(clean, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK); 168 clean->lf_next = NULL; 169 } 170 /* 171 * Create the lockf structure 172 */ 173 MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK); 174 lock->lf_start = start; 175 lock->lf_end = end; 176 lock->lf_id = ap->a_id; 177 /* 178 * XXX The problem is that VTOI is ufs specific, so it will 179 * break LOCKF_DEBUG for all other FS's other than UFS because 180 * it casts the vnode->data ptr to struct inode *. 181 */ 182/* lock->lf_inode = VTOI(ap->a_vp); */ 183 lock->lf_inode = (struct inode *)0; 184 lock->lf_type = fl->l_type; 185 lock->lf_head = head; 186 lock->lf_next = (struct lockf *)0; 187 TAILQ_INIT(&lock->lf_blkhd); 188 lock->lf_flags = ap->a_flags; 189 /* 190 * Do the requested operation. 191 */ 192 VI_LOCK(vp); 193 switch(ap->a_op) { 194 case F_SETLK: 195 error = lf_setlock(lock, vp, &clean); 196 break; 197 198 case F_UNLCK: 199 error = lf_clearlock(lock, &clean); 200 lock->lf_next = clean; 201 clean = lock; 202 break; 203 204 case F_GETLK: 205 error = lf_getlock(lock, fl); 206 lock->lf_next = clean; 207 clean = lock; 208 break; 209 210 default: 211 lock->lf_next = clean; 212 clean = lock; 213 error = EINVAL; 214 break; 215 } 216 VI_UNLOCK(vp); 217 for (lock = clean; lock != NULL; ) { 218 n = lock->lf_next; 219 free(lock, M_LOCKF); 220 lock = n; 221 } 222 return (error); 223} 224 225/* 226 * Set a byte-range lock. 227 */ 228static int 229lf_setlock(lock, vp, clean) 230 struct lockf *lock; 231 struct vnode *vp; 232 struct lockf **clean; 233{ 234 struct lockf *block; 235 struct lockf **head = lock->lf_head; 236 struct lockf **prev, *overlap, *ltmp; 237 static char lockstr[] = "lockf"; 238 int ovcase, priority, needtolink, error; 239 240#ifdef LOCKF_DEBUG 241 if (lockf_debug & 1) 242 lf_print("lf_setlock", lock); 243#endif /* LOCKF_DEBUG */ 244 245 /* 246 * Set the priority 247 */ 248 priority = PLOCK; 249 if (lock->lf_type == F_WRLCK) 250 priority += 4; 251 priority |= PCATCH; 252 /* 253 * Scan lock list for this file looking for locks that would block us. 254 */ 255 while ((block = lf_getblock(lock))) { 256 /* 257 * Free the structure and return if nonblocking. 258 */ 259 if ((lock->lf_flags & F_WAIT) == 0) { 260 lock->lf_next = *clean; 261 *clean = lock; 262 return (EAGAIN); 263 } 264 /* 265 * We are blocked. Since flock style locks cover 266 * the whole file, there is no chance for deadlock. 267 * For byte-range locks we must check for deadlock. 268 * 269 * Deadlock detection is done by looking through the 270 * wait channels to see if there are any cycles that 271 * involve us. MAXDEPTH is set just to make sure we 272 * do not go off into neverland. 273 */ 274 if ((lock->lf_flags & F_POSIX) && 275 (block->lf_flags & F_POSIX)) { 276 struct proc *wproc; 277 struct proc *nproc; 278 struct thread *td; 279 struct lockf *waitblock; 280 int i = 0; 281 282 /* The block is waiting on something */ 283 wproc = (struct proc *)block->lf_id; 284restart: 285 nproc = NULL; 286 PROC_LOCK(wproc); 287 FOREACH_THREAD_IN_PROC(wproc, td) { 288 thread_lock(td); 289 for (;;) { 290 if (!TD_ON_SLEEPQ(td) || 291 td->td_wmesg != lockstr) 292 break; 293 waitblock = (struct lockf *)td->td_wchan; 294 /* Get the owner of the blocking lock */ 295 if (waitblock->lf_next == NULL) 296 break; 297 waitblock = waitblock->lf_next; 298 if ((waitblock->lf_flags & F_POSIX) == 0) 299 break; 300 if (waitblock->lf_id == lock->lf_id) { 301 thread_unlock(td); 302 PROC_UNLOCK(wproc); 303 lock->lf_next = *clean; 304 *clean = lock; 305 return (EDEADLK); 306 } 307 nproc = (struct proc *)waitblock->lf_id; 308 break; 309 } 310 thread_unlock(td); 311 if (nproc) 312 break; 313 } 314 PROC_UNLOCK(wproc); 315 wproc = nproc; 316 if (++i < maxlockdepth && wproc) 317 goto restart; 318 } 319 /* 320 * For flock type locks, we must first remove 321 * any shared locks that we hold before we sleep 322 * waiting for an exclusive lock. 323 */ 324 if ((lock->lf_flags & F_FLOCK) && 325 lock->lf_type == F_WRLCK) { 326 lock->lf_type = F_UNLCK; 327 (void) lf_clearlock(lock, clean); 328 lock->lf_type = F_WRLCK; 329 } 330 /* 331 * Add our lock to the blocked list and sleep until we're free. 332 * Remember who blocked us (for deadlock detection). 333 */ 334 lock->lf_next = block; 335 TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block); 336#ifdef LOCKF_DEBUG 337 if (lockf_debug & 1) { 338 lf_print("lf_setlock: blocking on", block); 339 lf_printlist("lf_setlock", block); 340 } 341#endif /* LOCKF_DEBUG */ 342 error = msleep(lock, VI_MTX(vp), priority, lockstr, 0); 343 /* 344 * We may have been awakened by a signal and/or by a 345 * debugger continuing us (in which cases we must remove 346 * ourselves from the blocked list) and/or by another 347 * process releasing a lock (in which case we have 348 * already been removed from the blocked list and our 349 * lf_next field set to NOLOCKF). 350 */ 351 if (lock->lf_next) { 352 TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, lf_block); 353 lock->lf_next = NOLOCKF; 354 } 355 if (error) { 356 lock->lf_next = *clean; 357 *clean = lock; 358 return (error); 359 } 360 } 361 /* 362 * No blocks!! Add the lock. Note that we will 363 * downgrade or upgrade any overlapping locks this 364 * process already owns. 365 * 366 * Skip over locks owned by other processes. 367 * Handle any locks that overlap and are owned by ourselves. 368 */ 369 prev = head; 370 block = *head; 371 needtolink = 1; 372 for (;;) { 373 ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap); 374 if (ovcase) 375 block = overlap->lf_next; 376 /* 377 * Six cases: 378 * 0) no overlap 379 * 1) overlap == lock 380 * 2) overlap contains lock 381 * 3) lock contains overlap 382 * 4) overlap starts before lock 383 * 5) overlap ends after lock 384 */ 385 switch (ovcase) { 386 case 0: /* no overlap */ 387 if (needtolink) { 388 *prev = lock; 389 lock->lf_next = overlap; 390 } 391 break; 392 393 case 1: /* overlap == lock */ 394 /* 395 * If downgrading lock, others may be 396 * able to acquire it. 397 */ 398 if (lock->lf_type == F_RDLCK && 399 overlap->lf_type == F_WRLCK) 400 lf_wakelock(overlap); 401 overlap->lf_type = lock->lf_type; 402 lock->lf_next = *clean; 403 *clean = lock; 404 lock = overlap; /* for debug output below */ 405 break; 406 407 case 2: /* overlap contains lock */ 408 /* 409 * Check for common starting point and different types. 410 */ 411 if (overlap->lf_type == lock->lf_type) { 412 lock->lf_next = *clean; 413 *clean = lock; 414 lock = overlap; /* for debug output below */ 415 break; 416 } 417 if (overlap->lf_start == lock->lf_start) { 418 *prev = lock; 419 lock->lf_next = overlap; 420 overlap->lf_start = lock->lf_end + 1; 421 } else 422 lf_split(overlap, lock, clean); 423 lf_wakelock(overlap); 424 break; 425 426 case 3: /* lock contains overlap */ 427 /* 428 * If downgrading lock, others may be able to 429 * acquire it, otherwise take the list. 430 */ 431 if (lock->lf_type == F_RDLCK && 432 overlap->lf_type == F_WRLCK) { 433 lf_wakelock(overlap); 434 } else { 435 while (!TAILQ_EMPTY(&overlap->lf_blkhd)) { 436 ltmp = TAILQ_FIRST(&overlap->lf_blkhd); 437 TAILQ_REMOVE(&overlap->lf_blkhd, ltmp, 438 lf_block); 439 TAILQ_INSERT_TAIL(&lock->lf_blkhd, 440 ltmp, lf_block); 441 ltmp->lf_next = lock; 442 } 443 } 444 /* 445 * Add the new lock if necessary and delete the overlap. 446 */ 447 if (needtolink) { 448 *prev = lock; 449 lock->lf_next = overlap->lf_next; 450 prev = &lock->lf_next; 451 needtolink = 0; 452 } else 453 *prev = overlap->lf_next; 454 overlap->lf_next = *clean; 455 *clean = 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 */ 499static int 500lf_clearlock(unlock, clean) 501 struct lockf *unlock; 502 struct lockf **clean; 503{ 504 struct lockf **head = unlock->lf_head; 505 register 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, &prev, &overlap))) { 519 /* 520 * Wakeup the list of locks to be retried. 521 */ 522 lf_wakelock(overlap); 523 524 switch (ovcase) { 525 526 case 1: /* overlap == lock */ 527 *prev = overlap->lf_next; 528 overlap->lf_next = *clean; 529 *clean = overlap; 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, clean); 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 overlap->lf_next = *clean; 545 *clean = overlap; 546 continue; 547 548 case 4: /* overlap starts before lock */ 549 overlap->lf_end = unlock->lf_start - 1; 550 prev = &overlap->lf_next; 551 lf = overlap->lf_next; 552 continue; 553 554 case 5: /* overlap ends after lock */ 555 overlap->lf_start = unlock->lf_end + 1; 556 break; 557 } 558 break; 559 } 560#ifdef LOCKF_DEBUG 561 if (lockf_debug & 1) 562 lf_printlist("lf_clearlock", unlock); 563#endif /* LOCKF_DEBUG */ 564 return (0); 565} 566 567/* 568 * Check whether there is a blocking lock, 569 * and if so return its process identifier. 570 */ 571static int 572lf_getlock(lock, fl) 573 register struct lockf *lock; 574 register struct flock *fl; 575{ 576 register struct lockf *block; 577 578#ifdef LOCKF_DEBUG 579 if (lockf_debug & 1) 580 lf_print("lf_getlock", lock); 581#endif /* LOCKF_DEBUG */ 582 583 if ((block = lf_getblock(lock))) { 584 fl->l_type = block->lf_type; 585 fl->l_whence = SEEK_SET; 586 fl->l_start = block->lf_start; 587 if (block->lf_end == -1) 588 fl->l_len = 0; 589 else 590 fl->l_len = block->lf_end - block->lf_start + 1; 591 if (block->lf_flags & F_POSIX) 592 fl->l_pid = ((struct proc *)(block->lf_id))->p_pid; 593 else 594 fl->l_pid = -1; 595 } else { 596 fl->l_type = F_UNLCK; 597 } 598 return (0); 599} 600 601/* 602 * Walk the list of locks for an inode and 603 * return the first blocking lock. 604 */ 605static struct lockf * 606lf_getblock(lock) 607 register struct lockf *lock; 608{ 609 struct lockf **prev, *overlap, *lf = *(lock->lf_head); 610 int ovcase; 611 612 prev = lock->lf_head; 613 while ((ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap))) { 614 /* 615 * We've found an overlap, see if it blocks us 616 */ 617 if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) 618 return (overlap); 619 /* 620 * Nope, point to the next one on the list and 621 * see if it blocks us 622 */ 623 lf = overlap->lf_next; 624 } 625 return (NOLOCKF); 626} 627 628/* 629 * Walk the list of locks for an inode to 630 * find an overlapping lock (if any). 631 * 632 * NOTE: this returns only the FIRST overlapping lock. There 633 * may be more than one. 634 */ 635static int 636lf_findoverlap(lf, lock, type, prev, overlap) 637 register struct lockf *lf; 638 struct lockf *lock; 639 int type; 640 struct lockf ***prev; 641 struct lockf **overlap; 642{ 643 off_t start, end; 644 645 *overlap = lf; 646 if (lf == NOLOCKF) 647 return (0); 648#ifdef LOCKF_DEBUG 649 if (lockf_debug & 2) 650 lf_print("lf_findoverlap: looking for overlap in", lock); 651#endif /* LOCKF_DEBUG */ 652 start = lock->lf_start; 653 end = lock->lf_end; 654 while (lf != NOLOCKF) { 655 if (((type & SELF) && lf->lf_id != lock->lf_id) || 656 ((type & OTHERS) && lf->lf_id == lock->lf_id)) { 657 *prev = &lf->lf_next; 658 *overlap = lf = lf->lf_next; 659 continue; 660 } 661#ifdef LOCKF_DEBUG 662 if (lockf_debug & 2) 663 lf_print("\tchecking", lf); 664#endif /* LOCKF_DEBUG */ 665 /* 666 * OK, check for overlap 667 * 668 * Six cases: 669 * 0) no overlap 670 * 1) overlap == lock 671 * 2) overlap contains lock 672 * 3) lock contains overlap 673 * 4) overlap starts before lock 674 * 5) overlap ends after lock 675 */ 676 if ((lf->lf_end != -1 && start > lf->lf_end) || 677 (end != -1 && lf->lf_start > end)) { 678 /* Case 0 */ 679#ifdef LOCKF_DEBUG 680 if (lockf_debug & 2) 681 printf("no overlap\n"); 682#endif /* LOCKF_DEBUG */ 683 if ((type & SELF) && end != -1 && lf->lf_start > end) 684 return (0); 685 *prev = &lf->lf_next; 686 *overlap = lf = lf->lf_next; 687 continue; 688 } 689 if ((lf->lf_start == start) && (lf->lf_end == end)) { 690 /* Case 1 */ 691#ifdef LOCKF_DEBUG 692 if (lockf_debug & 2) 693 printf("overlap == lock\n"); 694#endif /* LOCKF_DEBUG */ 695 return (1); 696 } 697 if ((lf->lf_start <= start) && 698 (end != -1) && 699 ((lf->lf_end >= end) || (lf->lf_end == -1))) { 700 /* Case 2 */ 701#ifdef LOCKF_DEBUG 702 if (lockf_debug & 2) 703 printf("overlap contains lock\n"); 704#endif /* LOCKF_DEBUG */ 705 return (2); 706 } 707 if (start <= lf->lf_start && 708 (end == -1 || 709 (lf->lf_end != -1 && end >= lf->lf_end))) { 710 /* Case 3 */ 711#ifdef LOCKF_DEBUG 712 if (lockf_debug & 2) 713 printf("lock contains overlap\n"); 714#endif /* LOCKF_DEBUG */ 715 return (3); 716 } 717 if ((lf->lf_start < start) && 718 ((lf->lf_end >= start) || (lf->lf_end == -1))) { 719 /* Case 4 */ 720#ifdef LOCKF_DEBUG 721 if (lockf_debug & 2) 722 printf("overlap starts before lock\n"); 723#endif /* LOCKF_DEBUG */ 724 return (4); 725 } 726 if ((lf->lf_start > start) && 727 (end != -1) && 728 ((lf->lf_end > end) || (lf->lf_end == -1))) { 729 /* Case 5 */ 730#ifdef LOCKF_DEBUG 731 if (lockf_debug & 2) 732 printf("overlap ends after lock\n"); 733#endif /* LOCKF_DEBUG */ 734 return (5); 735 } 736 panic("lf_findoverlap: default"); 737 } 738 return (0); 739} 740 741/* 742 * Split a lock and a contained region into 743 * two or three locks as necessary. 744 */ 745static void 746lf_split(lock1, lock2, split) 747 struct lockf *lock1; 748 struct lockf *lock2; 749 struct lockf **split; 750{ 751 struct lockf *splitlock; 752 753#ifdef LOCKF_DEBUG 754 if (lockf_debug & 2) { 755 lf_print("lf_split", lock1); 756 lf_print("splitting from", lock2); 757 } 758#endif /* LOCKF_DEBUG */ 759 /* 760 * Check to see if spliting into only two pieces. 761 */ 762 if (lock1->lf_start == lock2->lf_start) { 763 lock1->lf_start = lock2->lf_end + 1; 764 lock2->lf_next = lock1; 765 return; 766 } 767 if (lock1->lf_end == lock2->lf_end) { 768 lock1->lf_end = lock2->lf_start - 1; 769 lock2->lf_next = lock1->lf_next; 770 lock1->lf_next = lock2; 771 return; 772 } 773 /* 774 * Make a new lock consisting of the last part of 775 * the encompassing lock. We use the preallocated 776 * splitlock so we don't have to block. 777 */ 778 splitlock = *split; 779 KASSERT(splitlock != NULL, ("no split")); 780 *split = splitlock->lf_next; 781 bcopy(lock1, splitlock, sizeof *splitlock); 782 splitlock->lf_start = lock2->lf_end + 1; 783 TAILQ_INIT(&splitlock->lf_blkhd); 784 lock1->lf_end = lock2->lf_start - 1; 785 /* 786 * OK, now link it in 787 */ 788 splitlock->lf_next = lock1->lf_next; 789 lock2->lf_next = splitlock; 790 lock1->lf_next = lock2; 791} 792 793/* 794 * Wakeup a blocklist 795 */ 796static void 797lf_wakelock(listhead) 798 struct lockf *listhead; 799{ 800 register struct lockf *wakelock; 801 802 while (!TAILQ_EMPTY(&listhead->lf_blkhd)) { 803 wakelock = TAILQ_FIRST(&listhead->lf_blkhd); 804 TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block); 805 wakelock->lf_next = NOLOCKF; 806#ifdef LOCKF_DEBUG 807 if (lockf_debug & 2) 808 lf_print("lf_wakelock: awakening", wakelock); 809#endif /* LOCKF_DEBUG */ 810 wakeup(wakelock); 811 } 812} 813 814#ifdef LOCKF_DEBUG 815/* 816 * Print out a lock. 817 */ 818static void 819lf_print(tag, lock) 820 char *tag; 821 register struct lockf *lock; 822{ 823 824 printf("%s: lock %p for ", tag, (void *)lock); 825 if (lock->lf_flags & F_POSIX) 826 printf("proc %ld", (long)((struct proc *)lock->lf_id)->p_pid); 827 else 828 printf("id %p", (void *)lock->lf_id); 829 if (lock->lf_inode != (struct inode *)0) 830 printf(" in ino %ju on dev <%s>, %s, start %jd, end %jd", 831 (uintmax_t)lock->lf_inode->i_number, 832 devtoname(lock->lf_inode->i_dev), 833 lock->lf_type == F_RDLCK ? "shared" : 834 lock->lf_type == F_WRLCK ? "exclusive" : 835 lock->lf_type == F_UNLCK ? "unlock" : "unknown", 836 (intmax_t)lock->lf_start, (intmax_t)lock->lf_end); 837 else 838 printf(" %s, start %jd, end %jd", 839 lock->lf_type == F_RDLCK ? "shared" : 840 lock->lf_type == F_WRLCK ? "exclusive" : 841 lock->lf_type == F_UNLCK ? "unlock" : "unknown", 842 (intmax_t)lock->lf_start, (intmax_t)lock->lf_end); 843 if (!TAILQ_EMPTY(&lock->lf_blkhd)) 844 printf(" block %p\n", (void *)TAILQ_FIRST(&lock->lf_blkhd)); 845 else 846 printf("\n"); 847} 848 849static void 850lf_printlist(tag, lock) 851 char *tag; 852 struct lockf *lock; 853{ 854 register struct lockf *lf, *blk; 855 856 if (lock->lf_inode == (struct inode *)0) 857 return; 858 859 printf("%s: Lock list for ino %ju on dev <%s>:\n", 860 tag, (uintmax_t)lock->lf_inode->i_number, 861 devtoname(lock->lf_inode->i_dev)); 862 for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) { 863 printf("\tlock %p for ",(void *)lf); 864 if (lf->lf_flags & F_POSIX) 865 printf("proc %ld", 866 (long)((struct proc *)lf->lf_id)->p_pid); 867 else 868 printf("id %p", (void *)lf->lf_id); 869 printf(", %s, start %jd, end %jd", 870 lf->lf_type == F_RDLCK ? "shared" : 871 lf->lf_type == F_WRLCK ? "exclusive" : 872 lf->lf_type == F_UNLCK ? "unlock" : 873 "unknown", (intmax_t)lf->lf_start, (intmax_t)lf->lf_end); 874 TAILQ_FOREACH(blk, &lf->lf_blkhd, lf_block) { 875 printf("\n\t\tlock request %p for ", (void *)blk); 876 if (blk->lf_flags & F_POSIX) 877 printf("proc %ld", 878 (long)((struct proc *)blk->lf_id)->p_pid); 879 else 880 printf("id %p", (void *)blk->lf_id); 881 printf(", %s, start %jd, end %jd", 882 blk->lf_type == F_RDLCK ? "shared" : 883 blk->lf_type == F_WRLCK ? "exclusive" : 884 blk->lf_type == F_UNLCK ? "unlock" : 885 "unknown", (intmax_t)blk->lf_start, 886 (intmax_t)blk->lf_end); 887 if (!TAILQ_EMPTY(&blk->lf_blkhd)) 888 panic("lf_printlist: bad list"); 889 } 890 printf("\n"); 891 } 892} 893#endif /* LOCKF_DEBUG */ 894