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