home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / ufs / ufs_lockf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-02  |  16.8 KB  |  681 lines

  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 */
  681.