|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California. ! 3: * 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 7.7 (Berkeley) 7/2/91 ! 37: */ ! 38: ! 39: #include "param.h" ! 40: #include "systm.h" ! 41: #include "kernel.h" ! 42: #include "file.h" ! 43: #include "proc.h" ! 44: #include "vnode.h" ! 45: #include "malloc.h" ! 46: #include "fcntl.h" ! 47: ! 48: #include "lockf.h" ! 49: #include "quota.h" ! 50: #include "inode.h" ! 51: ! 52: /* ! 53: * This variable controls the maximum number of processes that will ! 54: * be checked in doing deadlock detection. ! 55: */ ! 56: int maxlockdepth = MAXDEPTH; ! 57: ! 58: #ifdef LOCKF_DEBUG ! 59: int lockf_debug = 0; ! 60: #endif /* LOCKF_DEBUG */ ! 61: ! 62: #define NOLOCKF (struct lockf *)0 ! 63: #define SELF 0x1 ! 64: #define OTHERS 0x2 ! 65: ! 66: /* ! 67: * Set a byte-range lock. ! 68: */ ! 69: lf_setlock(lock) ! 70: register struct lockf *lock; ! 71: { ! 72: register struct lockf *block; ! 73: struct inode *ip = lock->lf_inode; ! 74: struct lockf **prev, *overlap, *ltmp; ! 75: static char lockstr[] = "lockf"; ! 76: int ovcase, priority, needtolink, error; ! 77: ! 78: #ifdef LOCKF_DEBUG ! 79: if (lockf_debug & 1) ! 80: lf_print("lf_setlock", lock); ! 81: #endif /* LOCKF_DEBUG */ ! 82: ! 83: /* ! 84: * Set the priority ! 85: */ ! 86: priority = PLOCK; ! 87: if (lock->lf_type == F_WRLCK) ! 88: priority += 4; ! 89: priority |= PCATCH; ! 90: /* ! 91: * Scan lock list for this file looking for locks that would block us. ! 92: */ ! 93: while (block = lf_getblock(lock)) { ! 94: /* ! 95: * Free the structure and return if nonblocking. ! 96: */ ! 97: if ((lock->lf_flags & F_WAIT) == 0) { ! 98: FREE(lock, M_LOCKF); ! 99: return (EAGAIN); ! 100: } ! 101: /* ! 102: * We are blocked. Since flock style locks cover ! 103: * the whole file, there is no chance for deadlock. ! 104: * For byte-range locks we must check for deadlock. ! 105: * ! 106: * Deadlock detection is done by looking through the ! 107: * wait channels to see if there are any cycles that ! 108: * involve us. MAXDEPTH is set just to make sure we ! 109: * do not go off into neverland. ! 110: */ ! 111: if ((lock->lf_flags & F_POSIX) && ! 112: (block->lf_flags & F_POSIX)) { ! 113: register struct proc *wproc; ! 114: register struct lockf *waitblock; ! 115: int i = 0; ! 116: ! 117: /* The block is waiting on something */ ! 118: wproc = (struct proc *)block->lf_id; ! 119: while (wproc->p_wchan && ! 120: (wproc->p_wmesg == lockstr) && ! 121: (i++ < maxlockdepth)) { ! 122: waitblock = (struct lockf *)wproc->p_wchan; ! 123: /* Get the owner of the blocking lock */ ! 124: waitblock = waitblock->lf_next; ! 125: if ((waitblock->lf_flags & F_POSIX) == 0) ! 126: break; ! 127: wproc = (struct proc *)waitblock->lf_id; ! 128: if (wproc == (struct proc *)lock->lf_id) { ! 129: free(lock, M_LOCKF); ! 130: return (EDEADLK); ! 131: } ! 132: } ! 133: } ! 134: /* ! 135: * For flock type locks, we must first remove ! 136: * any shared locks that we hold before we sleep ! 137: * waiting for an exclusive lock. ! 138: */ ! 139: if ((lock->lf_flags & F_FLOCK) && ! 140: lock->lf_type == F_WRLCK) { ! 141: lock->lf_type = F_UNLCK; ! 142: (void) lf_clearlock(lock); ! 143: lock->lf_type = F_WRLCK; ! 144: } ! 145: /* ! 146: * Add our lock to the blocked list and sleep until we're free. ! 147: * Remember who blocked us (for deadlock detection). ! 148: */ ! 149: lock->lf_next = block; ! 150: lf_addblock(block, lock); ! 151: #ifdef LOCKF_DEBUG ! 152: if (lockf_debug & 1) { ! 153: lf_print("lf_setlock: blocking on", block); ! 154: lf_printlist("lf_setlock", block); ! 155: } ! 156: #endif /* LOCKF_DEBUG */ ! 157: if (error = tsleep((caddr_t)lock, priority, lockstr, 0)) { ! 158: free(lock, M_LOCKF); ! 159: return (error); ! 160: } ! 161: } ! 162: /* ! 163: * No blocks!! Add the lock. Note that we will ! 164: * downgrade or upgrade any overlapping locks this ! 165: * process already owns. ! 166: * ! 167: * Skip over locks owned by other processes. ! 168: * Handle any locks that overlap and are owned by ourselves. ! 169: */ ! 170: prev = &ip->i_lockf; ! 171: block = ip->i_lockf; ! 172: needtolink = 1; ! 173: for (;;) { ! 174: if (ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap)) ! 175: block = overlap->lf_next; ! 176: /* ! 177: * Six cases: ! 178: * 0) no overlap ! 179: * 1) overlap == lock ! 180: * 2) overlap contains lock ! 181: * 3) lock contains overlap ! 182: * 4) overlap starts before lock ! 183: * 5) overlap ends after lock ! 184: */ ! 185: switch (ovcase) { ! 186: case 0: /* no overlap */ ! 187: if (needtolink) { ! 188: *prev = lock; ! 189: lock->lf_next = overlap; ! 190: } ! 191: break; ! 192: ! 193: case 1: /* overlap == lock */ ! 194: /* ! 195: * If downgrading lock, others may be ! 196: * able to acquire it. ! 197: */ ! 198: if (lock->lf_type == F_RDLCK && ! 199: overlap->lf_type == F_WRLCK) ! 200: lf_wakelock(overlap); ! 201: overlap->lf_type = lock->lf_type; ! 202: FREE(lock, M_LOCKF); ! 203: lock = overlap; /* for debug output below */ ! 204: break; ! 205: ! 206: case 2: /* overlap contains lock */ ! 207: /* ! 208: * Check for common starting point and different types. ! 209: */ ! 210: if (overlap->lf_type == lock->lf_type) { ! 211: free(lock, M_LOCKF); ! 212: lock = overlap; /* for debug output below */ ! 213: break; ! 214: } ! 215: if (overlap->lf_start == lock->lf_start) { ! 216: *prev = lock; ! 217: lock->lf_next = overlap; ! 218: overlap->lf_start = lock->lf_end + 1; ! 219: } else ! 220: lf_split(overlap, lock); ! 221: lf_wakelock(overlap); ! 222: break; ! 223: ! 224: case 3: /* lock contains overlap */ ! 225: /* ! 226: * If downgrading lock, others may be able to ! 227: * acquire it, otherwise take the list. ! 228: */ ! 229: if (lock->lf_type == F_RDLCK && ! 230: overlap->lf_type == F_WRLCK) { ! 231: lf_wakelock(overlap); ! 232: } else { ! 233: ltmp = lock->lf_block; ! 234: lock->lf_block = overlap->lf_block; ! 235: lf_addblock(lock, ltmp); ! 236: } ! 237: /* ! 238: * Add the new lock if necessary and delete the overlap. ! 239: */ ! 240: if (needtolink) { ! 241: *prev = lock; ! 242: lock->lf_next = overlap->lf_next; ! 243: prev = &lock->lf_next; ! 244: needtolink = 0; ! 245: } else ! 246: *prev = overlap->lf_next; ! 247: free(overlap, M_LOCKF); ! 248: continue; ! 249: ! 250: case 4: /* overlap starts before lock */ ! 251: /* ! 252: * Add lock after overlap on the list. ! 253: */ ! 254: lock->lf_next = overlap->lf_next; ! 255: overlap->lf_next = lock; ! 256: overlap->lf_end = lock->lf_start - 1; ! 257: prev = &lock->lf_next; ! 258: lf_wakelock(overlap); ! 259: needtolink = 0; ! 260: continue; ! 261: ! 262: case 5: /* overlap ends after lock */ ! 263: /* ! 264: * Add the new lock before overlap. ! 265: */ ! 266: if (needtolink) { ! 267: *prev = lock; ! 268: lock->lf_next = overlap; ! 269: } ! 270: overlap->lf_start = lock->lf_end + 1; ! 271: lf_wakelock(overlap); ! 272: break; ! 273: } ! 274: break; ! 275: } ! 276: #ifdef LOCKF_DEBUG ! 277: if (lockf_debug & 1) { ! 278: lf_print("lf_setlock: got the lock", lock); ! 279: lf_printlist("lf_setlock", lock); ! 280: } ! 281: #endif /* LOCKF_DEBUG */ ! 282: return (0); ! 283: } ! 284: ! 285: /* ! 286: * Remove a byte-range lock on an inode. ! 287: * ! 288: * Generally, find the lock (or an overlap to that lock) ! 289: * and remove it (or shrink it), then wakeup anyone we can. ! 290: */ ! 291: lf_clearlock(unlock) ! 292: register struct lockf *unlock; ! 293: { ! 294: struct inode *ip = unlock->lf_inode; ! 295: register struct lockf *lf = ip->i_lockf; ! 296: struct lockf *overlap, **prev; ! 297: int ovcase; ! 298: ! 299: if (lf == NOLOCKF) ! 300: return (0); ! 301: #ifdef LOCKF_DEBUG ! 302: if (unlock->lf_type != F_UNLCK) ! 303: panic("lf_clearlock: bad type"); ! 304: if (lockf_debug & 1) ! 305: lf_print("lf_clearlock", unlock); ! 306: #endif /* LOCKF_DEBUG */ ! 307: prev = &ip->i_lockf; ! 308: while (ovcase = lf_findoverlap(lf, unlock, SELF, &prev, &overlap)) { ! 309: /* ! 310: * Wakeup the list of locks to be retried. ! 311: */ ! 312: lf_wakelock(overlap); ! 313: ! 314: switch (ovcase) { ! 315: ! 316: case 1: /* overlap == lock */ ! 317: *prev = overlap->lf_next; ! 318: FREE(overlap, M_LOCKF); ! 319: break; ! 320: ! 321: case 2: /* overlap contains lock: split it */ ! 322: if (overlap->lf_start == unlock->lf_start) { ! 323: overlap->lf_start = unlock->lf_end + 1; ! 324: break; ! 325: } ! 326: lf_split(overlap, unlock); ! 327: overlap->lf_next = unlock->lf_next; ! 328: break; ! 329: ! 330: case 3: /* lock contains overlap */ ! 331: *prev = overlap->lf_next; ! 332: lf = overlap->lf_next; ! 333: free(overlap, M_LOCKF); ! 334: continue; ! 335: ! 336: case 4: /* overlap starts before lock */ ! 337: overlap->lf_end = unlock->lf_start - 1; ! 338: prev = &overlap->lf_next; ! 339: lf = overlap->lf_next; ! 340: continue; ! 341: ! 342: case 5: /* overlap ends after lock */ ! 343: overlap->lf_start = unlock->lf_end + 1; ! 344: break; ! 345: } ! 346: break; ! 347: } ! 348: #ifdef LOCKF_DEBUG ! 349: if (lockf_debug & 1) ! 350: lf_printlist("lf_clearlock", unlock); ! 351: #endif /* LOCKF_DEBUG */ ! 352: return (0); ! 353: } ! 354: ! 355: /* ! 356: * Check whether there is a blocking lock, ! 357: * and if so return its process identifier. ! 358: */ ! 359: lf_getlock(lock, fl) ! 360: register struct lockf *lock; ! 361: register struct flock *fl; ! 362: { ! 363: register struct lockf *block; ! 364: off_t start, end; ! 365: ! 366: #ifdef LOCKF_DEBUG ! 367: if (lockf_debug & 1) ! 368: lf_print("lf_getlock", lock); ! 369: #endif /* LOCKF_DEBUG */ ! 370: ! 371: if (block = lf_getblock(lock)) { ! 372: fl->l_type = block->lf_type; ! 373: fl->l_whence = SEEK_SET; ! 374: fl->l_start = block->lf_start; ! 375: if (block->lf_end == -1) ! 376: fl->l_len = 0; ! 377: else ! 378: fl->l_len = block->lf_end - block->lf_start + 1; ! 379: if (block->lf_flags & F_POSIX) ! 380: fl->l_pid = ((struct proc *)(block->lf_id))->p_pid; ! 381: else ! 382: fl->l_pid = -1; ! 383: } else { ! 384: fl->l_type = F_UNLCK; ! 385: } ! 386: return (0); ! 387: } ! 388: ! 389: /* ! 390: * Walk the list of locks for an inode and ! 391: * return the first blocking lock. ! 392: */ ! 393: struct lockf * ! 394: lf_getblock(lock) ! 395: register struct lockf *lock; ! 396: { ! 397: struct lockf **prev, *overlap, *lf = lock->lf_inode->i_lockf; ! 398: int ovcase; ! 399: ! 400: prev = &lock->lf_inode->i_lockf; ! 401: while (ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap)) { ! 402: /* ! 403: * We've found an overlap, see if it blocks us ! 404: */ ! 405: if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) ! 406: return (overlap); ! 407: /* ! 408: * Nope, point to the next one on the list and ! 409: * see if it blocks us ! 410: */ ! 411: lf = overlap->lf_next; ! 412: } ! 413: return (NOLOCKF); ! 414: } ! 415: ! 416: /* ! 417: * Walk the list of locks for an inode to ! 418: * find an overlapping lock (if any). ! 419: * ! 420: * NOTE: this returns only the FIRST overlapping lock. There ! 421: * may be more than one. ! 422: */ ! 423: lf_findoverlap(lf, lock, type, prev, overlap) ! 424: register struct lockf *lf; ! 425: struct lockf *lock; ! 426: int type; ! 427: struct lockf ***prev; ! 428: struct lockf **overlap; ! 429: { ! 430: off_t start, end; ! 431: ! 432: *overlap = lf; ! 433: if (lf == NOLOCKF) ! 434: return (0); ! 435: #ifdef LOCKF_DEBUG ! 436: if (lockf_debug & 2) ! 437: lf_print("lf_findoverlap: looking for overlap in", lock); ! 438: #endif /* LOCKF_DEBUG */ ! 439: start = lock->lf_start; ! 440: end = lock->lf_end; ! 441: while (lf != NOLOCKF) { ! 442: if (((type & SELF) && lf->lf_id != lock->lf_id) || ! 443: ((type & OTHERS) && lf->lf_id == lock->lf_id)) { ! 444: *prev = &lf->lf_next; ! 445: *overlap = lf = lf->lf_next; ! 446: continue; ! 447: } ! 448: #ifdef LOCKF_DEBUG ! 449: if (lockf_debug & 2) ! 450: lf_print("\tchecking", lf); ! 451: #endif /* LOCKF_DEBUG */ ! 452: /* ! 453: * OK, check for overlap ! 454: * ! 455: * Six cases: ! 456: * 0) no overlap ! 457: * 1) overlap == lock ! 458: * 2) overlap contains lock ! 459: * 3) lock contains overlap ! 460: * 4) overlap starts before lock ! 461: * 5) overlap ends after lock ! 462: */ ! 463: if ((lf->lf_end != -1 && start > lf->lf_end) || ! 464: (end != -1 && lf->lf_start > end)) { ! 465: /* Case 0 */ ! 466: #ifdef LOCKF_DEBUG ! 467: if (lockf_debug & 2) ! 468: printf("no overlap\n"); ! 469: #endif /* LOCKF_DEBUG */ ! 470: if ((type & SELF) && end != -1 && lf->lf_start > end) ! 471: return (0); ! 472: *prev = &lf->lf_next; ! 473: *overlap = lf = lf->lf_next; ! 474: continue; ! 475: } ! 476: if ((lf->lf_start == start) && (lf->lf_end == end)) { ! 477: /* Case 1 */ ! 478: #ifdef LOCKF_DEBUG ! 479: if (lockf_debug & 2) ! 480: printf("overlap == lock\n"); ! 481: #endif /* LOCKF_DEBUG */ ! 482: return (1); ! 483: } ! 484: if ((lf->lf_start <= start) && ! 485: (end != -1) && ! 486: ((lf->lf_end >= end) || (lf->lf_end == -1))) { ! 487: /* Case 2 */ ! 488: #ifdef LOCKF_DEBUG ! 489: if (lockf_debug & 2) ! 490: printf("overlap contains lock\n"); ! 491: #endif /* LOCKF_DEBUG */ ! 492: return (2); ! 493: } ! 494: if (start <= lf->lf_start && ! 495: (end == -1 || ! 496: (lf->lf_end != -1 && end >= lf->lf_end))) { ! 497: /* Case 3 */ ! 498: #ifdef LOCKF_DEBUG ! 499: if (lockf_debug & 2) ! 500: printf("lock contains overlap\n"); ! 501: #endif /* LOCKF_DEBUG */ ! 502: return (3); ! 503: } ! 504: if ((lf->lf_start < start) && ! 505: ((lf->lf_end >= start) || (lf->lf_end == -1))) { ! 506: /* Case 4 */ ! 507: #ifdef LOCKF_DEBUG ! 508: if (lockf_debug & 2) ! 509: printf("overlap starts before lock\n"); ! 510: #endif /* LOCKF_DEBUG */ ! 511: return (4); ! 512: } ! 513: if ((lf->lf_start > start) && ! 514: (end != -1) && ! 515: ((lf->lf_end > end) || (lf->lf_end == -1))) { ! 516: /* Case 5 */ ! 517: #ifdef LOCKF_DEBUG ! 518: if (lockf_debug & 2) ! 519: printf("overlap ends after lock\n"); ! 520: #endif /* LOCKF_DEBUG */ ! 521: return (5); ! 522: } ! 523: panic("lf_findoverlap: default"); ! 524: } ! 525: return (0); ! 526: } ! 527: ! 528: /* ! 529: * Add a lock to the end of the blocked list. ! 530: */ ! 531: lf_addblock(lock, blocked) ! 532: struct lockf *lock; ! 533: struct lockf *blocked; ! 534: { ! 535: register struct lockf *lf; ! 536: ! 537: if (blocked == NOLOCKF) ! 538: return; ! 539: #ifdef LOCKF_DEBUG ! 540: if (lockf_debug & 2) { ! 541: lf_print("addblock: adding", blocked); ! 542: lf_print("to blocked list of", lock); ! 543: } ! 544: #endif /* LOCKF_DEBUG */ ! 545: if ((lf = lock->lf_block) == NOLOCKF) { ! 546: lock->lf_block = blocked; ! 547: return; ! 548: } ! 549: while (lf->lf_block != NOLOCKF) ! 550: lf = lf->lf_block; ! 551: lf->lf_block = blocked; ! 552: return; ! 553: } ! 554: ! 555: /* ! 556: * Split a lock and a contained region into ! 557: * two or three locks as necessary. ! 558: */ ! 559: lf_split(lock1, lock2) ! 560: register struct lockf *lock1; ! 561: register struct lockf *lock2; ! 562: { ! 563: register struct lockf *splitlock; ! 564: ! 565: #ifdef LOCKF_DEBUG ! 566: if (lockf_debug & 2) { ! 567: lf_print("lf_split", lock1); ! 568: lf_print("splitting from", lock2); ! 569: } ! 570: #endif /* LOCKF_DEBUG */ ! 571: /* ! 572: * Check to see if spliting into only two pieces. ! 573: */ ! 574: if (lock1->lf_start == lock2->lf_start) { ! 575: lock1->lf_start = lock2->lf_end + 1; ! 576: lock2->lf_next = lock1; ! 577: return; ! 578: } ! 579: if (lock1->lf_end == lock2->lf_end) { ! 580: lock1->lf_end = lock2->lf_start - 1; ! 581: lock2->lf_next = lock1->lf_next; ! 582: lock1->lf_next = lock2; ! 583: return; ! 584: } ! 585: /* ! 586: * Make a new lock consisting of the last part of ! 587: * the encompassing lock ! 588: */ ! 589: MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK); ! 590: bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock); ! 591: splitlock->lf_start = lock2->lf_end + 1; ! 592: splitlock->lf_block = NOLOCKF; ! 593: lock1->lf_end = lock2->lf_start - 1; ! 594: /* ! 595: * OK, now link it in ! 596: */ ! 597: splitlock->lf_next = lock1->lf_next; ! 598: lock2->lf_next = splitlock; ! 599: lock1->lf_next = lock2; ! 600: } ! 601: ! 602: /* ! 603: * Wakeup a blocklist ! 604: */ ! 605: lf_wakelock(listhead) ! 606: struct lockf *listhead; ! 607: { ! 608: register struct lockf *blocklist, *wakelock; ! 609: ! 610: blocklist = listhead->lf_block; ! 611: listhead->lf_block = NOLOCKF; ! 612: while (blocklist != NOLOCKF) { ! 613: wakelock = blocklist; ! 614: blocklist = blocklist->lf_block; ! 615: wakelock->lf_block = NOLOCKF; ! 616: wakelock->lf_next = NOLOCKF; ! 617: #ifdef LOCKF_DEBUG ! 618: if (lockf_debug & 2) ! 619: lf_print("lf_wakelock: awakening", wakelock); ! 620: #endif /* LOCKF_DEBUG */ ! 621: wakeup((caddr_t)wakelock); ! 622: } ! 623: } ! 624: ! 625: #ifdef LOCKF_DEBUG ! 626: /* ! 627: * Print out a lock. ! 628: */ ! 629: lf_print(tag, lock) ! 630: char *tag; ! 631: register struct lockf *lock; ! 632: { ! 633: ! 634: printf("%s: lock 0x%lx for ", tag, lock); ! 635: if (lock->lf_flags & F_POSIX) ! 636: printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid); ! 637: else ! 638: printf("id 0x%x", lock->lf_id); ! 639: printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d", ! 640: lock->lf_inode->i_number, ! 641: major(lock->lf_inode->i_dev), ! 642: minor(lock->lf_inode->i_dev), ! 643: lock->lf_type == F_RDLCK ? "shared" : ! 644: lock->lf_type == F_WRLCK ? "exclusive" : ! 645: lock->lf_type == F_UNLCK ? "unlock" : ! 646: "unknown", lock->lf_start, lock->lf_end); ! 647: if (lock->lf_block) ! 648: printf(" block 0x%x\n", lock->lf_block); ! 649: else ! 650: printf("\n"); ! 651: } ! 652: ! 653: lf_printlist(tag, lock) ! 654: char *tag; ! 655: struct lockf *lock; ! 656: { ! 657: register struct lockf *lf; ! 658: ! 659: printf("%s: Lock list for ino %d on dev <%d, %d>:\n", ! 660: tag, lock->lf_inode->i_number, ! 661: major(lock->lf_inode->i_dev), ! 662: minor(lock->lf_inode->i_dev)); ! 663: for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) { ! 664: printf("\tlock 0x%lx for ", lf); ! 665: if (lf->lf_flags & F_POSIX) ! 666: printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid); ! 667: else ! 668: printf("id 0x%x", lf->lf_id); ! 669: printf(", %s, start %d, end %d", ! 670: lf->lf_type == F_RDLCK ? "shared" : ! 671: lf->lf_type == F_WRLCK ? "exclusive" : ! 672: lf->lf_type == F_UNLCK ? "unlock" : ! 673: "unknown", lf->lf_start, lf->lf_end); ! 674: if (lf->lf_block) ! 675: printf(" block 0x%x\n", lf->lf_block); ! 676: else ! 677: printf("\n"); ! 678: } ! 679: } ! 680: #endif /* LOCKF_DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.