|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: ! 23: /* (c) 1997-1998 Apple Computer, Inc. All Rights Reserved */ ! 24: /* ! 25: * Copyright (c) 1982, 1986, 1989, 1993 ! 26: * The Regents of the University of California. All rights reserved. ! 27: * ! 28: * This code is derived from software contributed to Berkeley by ! 29: * Scooter Morris at Genentech Inc. ! 30: * ! 31: * Redistribution and use in source and binary forms, with or without ! 32: * modification, are permitted provided that the following conditions ! 33: * are met: ! 34: * 1. Redistributions of source code must retain the above copyright ! 35: * notice, this list of conditions and the following disclaimer. ! 36: * 2. Redistributions in binary form must reproduce the above copyright ! 37: * notice, this list of conditions and the following disclaimer in the ! 38: * documentation and/or other materials provided with the distribution. ! 39: * 3. All advertising materials mentioning features or use of this software ! 40: * must display the following acknowledgement: ! 41: * This product includes software developed by the University of ! 42: * California, Berkeley and its contributors. ! 43: * 4. Neither the name of the University nor the names of its contributors ! 44: * may be used to endorse or promote products derived from this software ! 45: * without specific prior written permission. ! 46: * ! 47: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 48: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 49: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 50: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 51: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 52: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 53: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 54: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 55: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 56: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 57: * SUCH DAMAGE. ! 58: * ! 59: * @(#)hfs_lockf.c 1.0 ! 60: * derived from @(#)ufs_lockf.c 8.4 (Berkeley) 10/26/94 ! 61: */ ! 62: ! 63: #include <sys/param.h> ! 64: #include <sys/systm.h> ! 65: #include <sys/kernel.h> ! 66: #include <sys/file.h> ! 67: #include <sys/proc.h> ! 68: #include <sys/vnode.h> ! 69: #include <sys/malloc.h> ! 70: #include <sys/fcntl.h> ! 71: ! 72: #include "hfs_lockf.h" ! 73: #include "hfs.h" ! 74: ! 75: /* ! 76: * This variable controls the maximum number of processes that will ! 77: * be checked in doing deadlock detection. ! 78: */ ! 79: int hfsmaxlockdepth = MAXDEPTH; ! 80: ! 81: #ifdef LOCKF_DEBUG ! 82: #include <vm/vm.h> ! 83: #include <sys/sysctl.h> ! 84: int lockf_debug = 0; ! 85: struct ctldebug debug4 = { "lockf_debug", &lockf_debug }; ! 86: #endif ! 87: ! 88: #define NOLOCKF (struct hfslockf *)0 ! 89: #define SELF 0x1 ! 90: #define OTHERS 0x2 ! 91: ! 92: /* ! 93: * Set a byte-range lock. ! 94: */ ! 95: int ! 96: hfs_setlock(lock) ! 97: register struct hfslockf *lock; ! 98: { ! 99: register struct hfslockf *block; ! 100: struct hfsnode *hp = lock->lf_hfsnode; ! 101: struct hfslockf **prev, *overlap, *ltmp; ! 102: static char lockstr[] = "hfslockf"; ! 103: int ovcase, priority, needtolink, error; ! 104: ! 105: #ifdef LOCKF_DEBUG ! 106: if (lockf_debug & 1) ! 107: hfs_lprint("hfs_setlock", lock); ! 108: #endif /* LOCKF_DEBUG */ ! 109: ! 110: /* ! 111: * Set the priority ! 112: */ ! 113: priority = PLOCK; ! 114: if (lock->lf_type == F_WRLCK) ! 115: priority += 4; ! 116: priority |= PCATCH; ! 117: /* ! 118: * Scan lock list for this file looking for locks that would block us. ! 119: */ ! 120: while ((block = hfs_getblock(lock))) { ! 121: /* ! 122: * Free the structure and return if nonblocking. ! 123: */ ! 124: if ((lock->lf_flags & F_WAIT) == 0) { ! 125: FREE(lock, M_LOCKF); ! 126: return (EAGAIN); ! 127: } ! 128: /* ! 129: * We are blocked. Since flock style locks cover ! 130: * the whole file, there is no chance for deadlock. ! 131: * For byte-range locks we must check for deadlock. ! 132: * ! 133: * Deadlock detection is done by looking through the ! 134: * wait channels to see if there are any cycles that ! 135: * involve us. MAXDEPTH is set just to make sure we ! 136: * do not go off into neverland. ! 137: */ ! 138: if ((lock->lf_flags & F_POSIX) && ! 139: (block->lf_flags & F_POSIX)) { ! 140: register struct proc *wproc; ! 141: register struct hfslockf *waitblock; ! 142: int i = 0; ! 143: ! 144: /* The block is waiting on something */ ! 145: wproc = (struct proc *)block->lf_id; ! 146: while (wproc->p_wchan && ! 147: (wproc->p_wmesg == lockstr) && ! 148: (i++ < hfsmaxlockdepth)) { ! 149: waitblock = (struct hfslockf *)wproc->p_wchan; ! 150: /* Get the owner of the blocking lock */ ! 151: waitblock = waitblock->lf_next; ! 152: if ((waitblock->lf_flags & F_POSIX) == 0) ! 153: break; ! 154: wproc = (struct proc *)waitblock->lf_id; ! 155: if (wproc == (struct proc *)lock->lf_id) { ! 156: _FREE(lock, M_LOCKF); ! 157: return (EDEADLK); ! 158: } ! 159: } ! 160: } ! 161: /* ! 162: * For flock type locks, we must first remove ! 163: * any shared locks that we hold before we sleep ! 164: * waiting for an exclusive lock. ! 165: */ ! 166: if ((lock->lf_flags & F_FLOCK) && ! 167: lock->lf_type == F_WRLCK) { ! 168: lock->lf_type = F_UNLCK; ! 169: (void) hfs_clearlock(lock); ! 170: lock->lf_type = F_WRLCK; ! 171: } ! 172: /* ! 173: * Add our lock to the blocked list and sleep until we're free. ! 174: * Remember who blocked us (for deadlock detection). ! 175: */ ! 176: lock->lf_next = block; ! 177: TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block); ! 178: #ifdef LOCKF_DEBUG ! 179: if (lockf_debug & 1) { ! 180: hfs_lprint("hfs_setlock: blocking on", block); ! 181: hfs_lprintlist("hfs_setlock", block); ! 182: } ! 183: #endif /* LOCKF_DEBUG */ ! 184: if ((error = tsleep((caddr_t)lock, priority, lockstr, 0))) { ! 185: /* ! 186: * We may have been awakened by a signal (in ! 187: * which case we must remove ourselves from the ! 188: * blocked list) and/or by another process ! 189: * releasing a lock (in which case we have already ! 190: * been removed from the blocked list and our ! 191: * lf_next field set to NOLOCKF). ! 192: */ ! 193: if (lock->lf_next) ! 194: TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, ! 195: lf_block); ! 196: _FREE(lock, M_LOCKF); ! 197: return (error); ! 198: } ! 199: } ! 200: /* ! 201: * No blocks!! Add the lock. Note that we will ! 202: * downgrade or upgrade any overlapping locks this ! 203: * process already owns. ! 204: * ! 205: * Skip over locks owned by other processes. ! 206: * Handle any locks that overlap and are owned by ourselves. ! 207: */ ! 208: prev = &hp->h_lockf; ! 209: block = hp->h_lockf; ! 210: needtolink = 1; ! 211: for (;;) { ! 212: if ((ovcase = hfs_findoverlap(block, lock, SELF, &prev, &overlap))) ! 213: block = overlap->lf_next; ! 214: /* ! 215: * Six cases: ! 216: * 0) no overlap ! 217: * 1) overlap == lock ! 218: * 2) overlap contains lock ! 219: * 3) lock contains overlap ! 220: * 4) overlap starts before lock ! 221: * 5) overlap ends after lock ! 222: */ ! 223: switch (ovcase) { ! 224: case 0: /* no overlap */ ! 225: if (needtolink) { ! 226: *prev = lock; ! 227: lock->lf_next = overlap; ! 228: } ! 229: break; ! 230: ! 231: case 1: /* overlap == lock */ ! 232: /* ! 233: * If downgrading lock, others may be ! 234: * able to acquire it. ! 235: */ ! 236: if (lock->lf_type == F_RDLCK && ! 237: overlap->lf_type == F_WRLCK) ! 238: hfs_wakelock(overlap); ! 239: overlap->lf_type = lock->lf_type; ! 240: FREE(lock, M_LOCKF); ! 241: lock = overlap; /* for debug output below */ ! 242: break; ! 243: ! 244: case 2: /* overlap contains lock */ ! 245: /* ! 246: * Check for common starting point and different types. ! 247: */ ! 248: if (overlap->lf_type == lock->lf_type) { ! 249: _FREE(lock, M_LOCKF); ! 250: lock = overlap; /* for debug output below */ ! 251: break; ! 252: } ! 253: if (overlap->lf_start == lock->lf_start) { ! 254: *prev = lock; ! 255: lock->lf_next = overlap; ! 256: overlap->lf_start = lock->lf_end + 1; ! 257: } else ! 258: hfs_split(overlap, lock); ! 259: hfs_wakelock(overlap); ! 260: break; ! 261: ! 262: case 3: /* lock contains overlap */ ! 263: /* ! 264: * If downgrading lock, others may be able to ! 265: * acquire it, otherwise take the list. ! 266: */ ! 267: if (lock->lf_type == F_RDLCK && ! 268: overlap->lf_type == F_WRLCK) { ! 269: hfs_wakelock(overlap); ! 270: } else { ! 271: while ((ltmp = overlap->lf_blkhd.tqh_first)) { ! 272: TAILQ_REMOVE(&overlap->lf_blkhd, ltmp, ! 273: lf_block); ! 274: TAILQ_INSERT_TAIL(&lock->lf_blkhd, ! 275: ltmp, lf_block); ! 276: } ! 277: } ! 278: /* ! 279: * Add the new lock if necessary and delete the overlap. ! 280: */ ! 281: if (needtolink) { ! 282: *prev = lock; ! 283: lock->lf_next = overlap->lf_next; ! 284: prev = &lock->lf_next; ! 285: needtolink = 0; ! 286: } else ! 287: *prev = overlap->lf_next; ! 288: _FREE(overlap, M_LOCKF); ! 289: continue; ! 290: ! 291: case 4: /* overlap starts before lock */ ! 292: /* ! 293: * Add lock after overlap on the list. ! 294: */ ! 295: lock->lf_next = overlap->lf_next; ! 296: overlap->lf_next = lock; ! 297: overlap->lf_end = lock->lf_start - 1; ! 298: prev = &lock->lf_next; ! 299: hfs_wakelock(overlap); ! 300: needtolink = 0; ! 301: continue; ! 302: ! 303: case 5: /* overlap ends after lock */ ! 304: /* ! 305: * Add the new lock before overlap. ! 306: */ ! 307: if (needtolink) { ! 308: *prev = lock; ! 309: lock->lf_next = overlap; ! 310: } ! 311: overlap->lf_start = lock->lf_end + 1; ! 312: hfs_wakelock(overlap); ! 313: break; ! 314: } ! 315: break; ! 316: } ! 317: #ifdef LOCKF_DEBUG ! 318: if (lockf_debug & 1) { ! 319: hfs_lprint("hfs_setlock: got the lock", lock); ! 320: hfs_lprintlist("hfs_setlock", lock); ! 321: } ! 322: #endif /* LOCKF_DEBUG */ ! 323: return (0); ! 324: } ! 325: ! 326: /* ! 327: * Remove a byte-range lock on an hfsnode. ! 328: * ! 329: * Generally, find the lock (or an overlap to that lock) ! 330: * and remove it (or shrink it), then wakeup anyone we can. ! 331: */ ! 332: int ! 333: hfs_clearlock(unlock) ! 334: register struct hfslockf *unlock; ! 335: { ! 336: struct hfsnode *hp = unlock->lf_hfsnode; ! 337: register struct hfslockf *lf = hp->h_lockf; ! 338: struct hfslockf *overlap, **prev; ! 339: int ovcase; ! 340: ! 341: if (lf == NOLOCKF) ! 342: return (0); ! 343: #ifdef LOCKF_DEBUG ! 344: if (unlock->lf_type != F_UNLCK) ! 345: panic("hfs_clearlock: bad type"); ! 346: if (lockf_debug & 1) ! 347: hfs_lprint("hfs_clearlock", unlock); ! 348: #endif /* LOCKF_DEBUG */ ! 349: prev = &hp->h_lockf; ! 350: while ((ovcase = hfs_findoverlap(lf, unlock, SELF, &prev, &overlap))) { ! 351: /* ! 352: * Wakeup the list of locks to be retried. ! 353: */ ! 354: hfs_wakelock(overlap); ! 355: ! 356: switch (ovcase) { ! 357: ! 358: case 1: /* overlap == lock */ ! 359: *prev = overlap->lf_next; ! 360: FREE(overlap, M_LOCKF); ! 361: break; ! 362: ! 363: case 2: /* overlap contains lock: split it */ ! 364: if (overlap->lf_start == unlock->lf_start) { ! 365: overlap->lf_start = unlock->lf_end + 1; ! 366: break; ! 367: } ! 368: hfs_split(overlap, unlock); ! 369: overlap->lf_next = unlock->lf_next; ! 370: break; ! 371: ! 372: case 3: /* lock contains overlap */ ! 373: *prev = overlap->lf_next; ! 374: lf = overlap->lf_next; ! 375: _FREE(overlap, M_LOCKF); ! 376: continue; ! 377: ! 378: case 4: /* overlap starts before lock */ ! 379: overlap->lf_end = unlock->lf_start - 1; ! 380: prev = &overlap->lf_next; ! 381: lf = overlap->lf_next; ! 382: continue; ! 383: ! 384: case 5: /* overlap ends after lock */ ! 385: overlap->lf_start = unlock->lf_end + 1; ! 386: break; ! 387: } ! 388: break; ! 389: } ! 390: #ifdef LOCKF_DEBUG ! 391: if (lockf_debug & 1) ! 392: hfs_lprintlist("hfs_clearlock", unlock); ! 393: #endif /* LOCKF_DEBUG */ ! 394: return (0); ! 395: } ! 396: ! 397: /* ! 398: * Check whether there is a blocking lock, ! 399: * and if so return its process identifier. ! 400: */ ! 401: int ! 402: hfs_getlock(lock, fl) ! 403: register struct hfslockf *lock; ! 404: register struct flock *fl; ! 405: { ! 406: register struct hfslockf *block; ! 407: ! 408: #ifdef LOCKF_DEBUG ! 409: if (lockf_debug & 1) ! 410: hfs_lprint("hfs_getlock", lock); ! 411: #endif /* LOCKF_DEBUG */ ! 412: ! 413: if ((block = hfs_getblock(lock))) { ! 414: fl->l_type = block->lf_type; ! 415: fl->l_whence = SEEK_SET; ! 416: fl->l_start = block->lf_start; ! 417: if (block->lf_end == -1) ! 418: fl->l_len = 0; ! 419: else ! 420: fl->l_len = block->lf_end - block->lf_start + 1; ! 421: if (block->lf_flags & F_POSIX) ! 422: fl->l_pid = ((struct proc *)(block->lf_id))->p_pid; ! 423: else ! 424: fl->l_pid = -1; ! 425: } else { ! 426: fl->l_type = F_UNLCK; ! 427: } ! 428: return (0); ! 429: } ! 430: ! 431: /* ! 432: * Walk the list of locks for an hfsnode and ! 433: * return the first blocking lock. ! 434: */ ! 435: struct hfslockf * ! 436: hfs_getblock(lock) ! 437: register struct hfslockf *lock; ! 438: { ! 439: struct hfslockf **prev, *overlap, *lf = lock->lf_hfsnode->h_lockf; ! 440: int ovcase; ! 441: ! 442: prev = &lock->lf_hfsnode->h_lockf; ! 443: while ((ovcase = hfs_findoverlap(lf, lock, OTHERS, &prev, &overlap))) { ! 444: /* ! 445: * We've found an overlap, see if it blocks us ! 446: */ ! 447: if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) ! 448: return (overlap); ! 449: /* ! 450: * Nope, point to the next one on the list and ! 451: * see if it blocks us ! 452: */ ! 453: lf = overlap->lf_next; ! 454: } ! 455: return (NOLOCKF); ! 456: } ! 457: ! 458: /* ! 459: * Walk the list of locks for an hfsnode to ! 460: * find an overlapping lock (if any). ! 461: * ! 462: * NOTE: this returns only the FIRST overlapping lock. There ! 463: * may be more than one. ! 464: */ ! 465: int ! 466: hfs_findoverlap(lf, lock, type, prev, overlap) ! 467: register struct hfslockf *lf; ! 468: struct hfslockf *lock; ! 469: int type; ! 470: struct hfslockf ***prev; ! 471: struct hfslockf **overlap; ! 472: { ! 473: off_t start, end; ! 474: ! 475: *overlap = lf; ! 476: if (lf == NOLOCKF) ! 477: return (0); ! 478: #ifdef LOCKF_DEBUG ! 479: if (lockf_debug & 2) ! 480: hfs_lprint("hfs_findoverlap: looking for overlap in", lock); ! 481: #endif /* LOCKF_DEBUG */ ! 482: start = lock->lf_start; ! 483: end = lock->lf_end; ! 484: while (lf != NOLOCKF) { ! 485: if (((type & SELF) && lf->lf_id != lock->lf_id) || ! 486: ((type & OTHERS) && lf->lf_id == lock->lf_id)) { ! 487: *prev = &lf->lf_next; ! 488: *overlap = lf = lf->lf_next; ! 489: continue; ! 490: } ! 491: #ifdef LOCKF_DEBUG ! 492: if (lockf_debug & 2) ! 493: hfs_lprint("\tchecking", lf); ! 494: #endif /* LOCKF_DEBUG */ ! 495: /* ! 496: * OK, check for overlap ! 497: * ! 498: * Six cases: ! 499: * 0) no overlap ! 500: * 1) overlap == lock ! 501: * 2) overlap contains lock ! 502: * 3) lock contains overlap ! 503: * 4) overlap starts before lock ! 504: * 5) overlap ends after lock ! 505: */ ! 506: if ((lf->lf_end != -1 && start > lf->lf_end) || ! 507: (end != -1 && lf->lf_start > end)) { ! 508: /* Case 0 */ ! 509: #ifdef LOCKF_DEBUG ! 510: if (lockf_debug & 2) ! 511: printf("no overlap\n"); ! 512: #endif /* LOCKF_DEBUG */ ! 513: if ((type & SELF) && end != -1 && lf->lf_start > end) ! 514: return (0); ! 515: *prev = &lf->lf_next; ! 516: *overlap = lf = lf->lf_next; ! 517: continue; ! 518: } ! 519: if ((lf->lf_start == start) && (lf->lf_end == end)) { ! 520: /* Case 1 */ ! 521: #ifdef LOCKF_DEBUG ! 522: if (lockf_debug & 2) ! 523: printf("overlap == lock\n"); ! 524: #endif /* LOCKF_DEBUG */ ! 525: return (1); ! 526: } ! 527: if ((lf->lf_start <= start) && ! 528: (end != -1) && ! 529: ((lf->lf_end >= end) || (lf->lf_end == -1))) { ! 530: /* Case 2 */ ! 531: #ifdef LOCKF_DEBUG ! 532: if (lockf_debug & 2) ! 533: printf("overlap contains lock\n"); ! 534: #endif /* LOCKF_DEBUG */ ! 535: return (2); ! 536: } ! 537: if (start <= lf->lf_start && ! 538: (end == -1 || ! 539: (lf->lf_end != -1 && end >= lf->lf_end))) { ! 540: /* Case 3 */ ! 541: #ifdef LOCKF_DEBUG ! 542: if (lockf_debug & 2) ! 543: printf("lock contains overlap\n"); ! 544: #endif /* LOCKF_DEBUG */ ! 545: return (3); ! 546: } ! 547: if ((lf->lf_start < start) && ! 548: ((lf->lf_end >= start) || (lf->lf_end == -1))) { ! 549: /* Case 4 */ ! 550: #ifdef LOCKF_DEBUG ! 551: if (lockf_debug & 2) ! 552: printf("overlap starts before lock\n"); ! 553: #endif /* LOCKF_DEBUG */ ! 554: return (4); ! 555: } ! 556: if ((lf->lf_start > start) && ! 557: (end != -1) && ! 558: ((lf->lf_end > end) || (lf->lf_end == -1))) { ! 559: /* Case 5 */ ! 560: #ifdef LOCKF_DEBUG ! 561: if (lockf_debug & 2) ! 562: printf("overlap ends after lock\n"); ! 563: #endif /* LOCKF_DEBUG */ ! 564: return (5); ! 565: } ! 566: panic("hfs_findoverlap: default"); ! 567: } ! 568: return (0); ! 569: } ! 570: ! 571: /* ! 572: * Split a lock and a contained region into ! 573: * two or three locks as necessary. ! 574: */ ! 575: void ! 576: hfs_split(lock1, lock2) ! 577: register struct hfslockf *lock1; ! 578: register struct hfslockf *lock2; ! 579: { ! 580: register struct hfslockf *splitlock; ! 581: ! 582: #ifdef LOCKF_DEBUG ! 583: if (lockf_debug & 2) { ! 584: hfs_lprint("hfs_split", lock1); ! 585: hfs_lprint("splitting from", lock2); ! 586: } ! 587: #endif /* LOCKF_DEBUG */ ! 588: /* ! 589: * Check to see if spliting into only two pieces. ! 590: */ ! 591: if (lock1->lf_start == lock2->lf_start) { ! 592: lock1->lf_start = lock2->lf_end + 1; ! 593: lock2->lf_next = lock1; ! 594: return; ! 595: } ! 596: if (lock1->lf_end == lock2->lf_end) { ! 597: lock1->lf_end = lock2->lf_start - 1; ! 598: lock2->lf_next = lock1->lf_next; ! 599: lock1->lf_next = lock2; ! 600: return; ! 601: } ! 602: /* ! 603: * Make a new lock consisting of the last part of ! 604: * the encompassing lock ! 605: */ ! 606: MALLOC(splitlock, struct hfslockf *, sizeof *splitlock, M_LOCKF, M_WAITOK); ! 607: bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock); ! 608: splitlock->lf_start = lock2->lf_end + 1; ! 609: TAILQ_INIT(&splitlock->lf_blkhd); ! 610: lock1->lf_end = lock2->lf_start - 1; ! 611: /* ! 612: * OK, now link it in ! 613: */ ! 614: splitlock->lf_next = lock1->lf_next; ! 615: lock2->lf_next = splitlock; ! 616: lock1->lf_next = lock2; ! 617: } ! 618: ! 619: /* ! 620: * Wakeup a blocklist ! 621: */ ! 622: void ! 623: hfs_wakelock(listhead) ! 624: struct hfslockf *listhead; ! 625: { ! 626: register struct hfslockf *wakelock; ! 627: ! 628: while ((wakelock = listhead->lf_blkhd.tqh_first)) { ! 629: TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block); ! 630: wakelock->lf_next = NOLOCKF; ! 631: #ifdef LOCKF_DEBUG ! 632: if (lockf_debug & 2) ! 633: hfs_lprint("hfs_wakelock: awakening", wakelock); ! 634: #endif /* LOCKF_DEBUG */ ! 635: wakeup((caddr_t)wakelock); ! 636: } ! 637: } ! 638: ! 639: #ifdef LOCKF_DEBUG ! 640: /* ! 641: * Print out a lock. ! 642: */ ! 643: hfs_lprint(tag, lock) ! 644: char *tag; ! 645: register struct hfslockf *lock; ! 646: { ! 647: ! 648: printf("%s: lock 0x%lx for ", tag, lock); ! 649: if (lock->lf_flags & F_POSIX) ! 650: printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid); ! 651: else ! 652: printf("id 0x%x", lock->lf_id); ! 653: printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d", ! 654: lock->lf_hfsnode->i_number, ! 655: major(lock->lf_hfsnode->h_dev), ! 656: minor(lock->lf_hfsnode->h_dev), ! 657: lock->lf_type == F_RDLCK ? "shared" : ! 658: lock->lf_type == F_WRLCK ? "exclusive" : ! 659: lock->lf_type == F_UNLCK ? "unlock" : ! 660: "unknown", lock->lf_start, lock->lf_end); ! 661: if (lock->lf_blkhd.tqh_first) ! 662: printf(" block 0x%x\n", lock->lf_blkhd.tqh_first); ! 663: else ! 664: printf("\n"); ! 665: } ! 666: ! 667: hfs_lprintlist(tag, lock) ! 668: char *tag; ! 669: struct hfslockf *lock; ! 670: { ! 671: register struct hfslockf *lf, *blk; ! 672: ! 673: printf("%s: Lock list for ino %d on dev <%d, %d>:\n", ! 674: tag, lock->lf_hfsnode->i_number, ! 675: major(lock->lf_hfsnode->h_dev), ! 676: minor(lock->lf_hfsnode->h_dev)); ! 677: for (lf = lock->lf_hfsnode->h_lockf; lf; lf = lf->lf_next) { ! 678: printf("\tlock 0x%lx for ", lf); ! 679: if (lf->lf_flags & F_POSIX) ! 680: printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid); ! 681: else ! 682: printf("id 0x%x", lf->lf_id); ! 683: printf(", %s, start %d, end %d", ! 684: lf->lf_type == F_RDLCK ? "shared" : ! 685: lf->lf_type == F_WRLCK ? "exclusive" : ! 686: lf->lf_type == F_UNLCK ? "unlock" : ! 687: "unknown", lf->lf_start, lf->lf_end); ! 688: for (blk = lf->lf_blkhd.tqh_first; blk; ! 689: blk = blk->lf_block.tqe_next) { ! 690: printf("\n\t\tlock request 0x%lx for ", blk); ! 691: if (blk->lf_flags & F_POSIX) ! 692: printf("proc %d", ! 693: ((struct proc *)(blk->lf_id))->p_pid); ! 694: else ! 695: printf("id 0x%x", blk->lf_id); ! 696: printf(", %s, start %d, end %d", ! 697: blk->lf_type == F_RDLCK ? "shared" : ! 698: blk->lf_type == F_WRLCK ? "exclusive" : ! 699: blk->lf_type == F_UNLCK ? "unlock" : ! 700: "unknown", blk->lf_start, blk->lf_end); ! 701: if (blk->lf_blkhd.tqh_first) ! 702: panic("hfs_lprintlist: bad list"); ! 703: } ! 704: printf("\n"); ! 705: } ! 706: } ! 707: #endif /* LOCKF_DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.