192dc7331SDavid Greenman /* 292dc7331SDavid Greenman * Copyright (c) 1982, 1986, 1989, 1993 392dc7331SDavid Greenman * The Regents of the University of California. All rights reserved. 492dc7331SDavid Greenman * 592dc7331SDavid Greenman * This code is derived from software contributed to Berkeley by 692dc7331SDavid Greenman * Scooter Morris at Genentech Inc. 792dc7331SDavid Greenman * 892dc7331SDavid Greenman * Redistribution and use in source and binary forms, with or without 992dc7331SDavid Greenman * modification, are permitted provided that the following conditions 1092dc7331SDavid Greenman * are met: 1192dc7331SDavid Greenman * 1. Redistributions of source code must retain the above copyright 1292dc7331SDavid Greenman * notice, this list of conditions and the following disclaimer. 1392dc7331SDavid Greenman * 2. Redistributions in binary form must reproduce the above copyright 1492dc7331SDavid Greenman * notice, this list of conditions and the following disclaimer in the 1592dc7331SDavid Greenman * documentation and/or other materials provided with the distribution. 1692dc7331SDavid Greenman * 3. All advertising materials mentioning features or use of this software 1792dc7331SDavid Greenman * must display the following acknowledgement: 1892dc7331SDavid Greenman * This product includes software developed by the University of 1992dc7331SDavid Greenman * California, Berkeley and its contributors. 2092dc7331SDavid Greenman * 4. Neither the name of the University nor the names of its contributors 2192dc7331SDavid Greenman * may be used to endorse or promote products derived from this software 2292dc7331SDavid Greenman * without specific prior written permission. 2392dc7331SDavid Greenman * 2492dc7331SDavid Greenman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2592dc7331SDavid Greenman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2692dc7331SDavid Greenman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2792dc7331SDavid Greenman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2892dc7331SDavid Greenman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2992dc7331SDavid Greenman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3092dc7331SDavid Greenman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3192dc7331SDavid Greenman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3292dc7331SDavid Greenman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3392dc7331SDavid Greenman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3492dc7331SDavid Greenman * SUCH DAMAGE. 3592dc7331SDavid Greenman * 3692dc7331SDavid Greenman * @(#)ufs_lockf.c 8.3 (Berkeley) 1/6/94 37b71fec07SBruce Evans * $Id: kern_lockf.c,v 1.5 1995/12/14 08:31:26 phk Exp $ 3892dc7331SDavid Greenman */ 3992dc7331SDavid Greenman 4092dc7331SDavid Greenman #include <sys/param.h> 4192dc7331SDavid Greenman #include <sys/systm.h> 4292dc7331SDavid Greenman #include <sys/kernel.h> 4392dc7331SDavid Greenman #include <sys/proc.h> 44b71fec07SBruce Evans #include <sys/unistd.h> 4592dc7331SDavid Greenman #include <sys/vnode.h> 4692dc7331SDavid Greenman #include <sys/malloc.h> 4792dc7331SDavid Greenman #include <sys/fcntl.h> 4892dc7331SDavid Greenman 4992dc7331SDavid Greenman #include <sys/lockf.h> 5092dc7331SDavid Greenman 5192dc7331SDavid Greenman /* 5292dc7331SDavid Greenman * This variable controls the maximum number of processes that will 5392dc7331SDavid Greenman * be checked in doing deadlock detection. 5492dc7331SDavid Greenman */ 5592dc7331SDavid Greenman int maxlockdepth = MAXDEPTH; 5692dc7331SDavid Greenman 5792dc7331SDavid Greenman #ifdef LOCKF_DEBUG 5892dc7331SDavid Greenman int lockf_debug = 0; 5992dc7331SDavid Greenman #endif 6092dc7331SDavid Greenman 6192dc7331SDavid Greenman #define NOLOCKF (struct lockf *)0 6292dc7331SDavid Greenman #define SELF 0x1 6392dc7331SDavid Greenman #define OTHERS 0x2 6487b6de2bSPoul-Henning Kamp static void lf_addblock __P((struct lockf *, struct lockf *)); 6587b6de2bSPoul-Henning Kamp static int lf_clearlock __P((struct lockf *)); 6687b6de2bSPoul-Henning Kamp static int lf_findoverlap __P((struct lockf *, 6787b6de2bSPoul-Henning Kamp struct lockf *, int, struct lockf ***, struct lockf **)); 6887b6de2bSPoul-Henning Kamp static struct lockf * 6987b6de2bSPoul-Henning Kamp lf_getblock __P((struct lockf *)); 7087b6de2bSPoul-Henning Kamp static int lf_getlock __P((struct lockf *, struct flock *)); 7187b6de2bSPoul-Henning Kamp static int lf_setlock __P((struct lockf *)); 7287b6de2bSPoul-Henning Kamp static void lf_split __P((struct lockf *, struct lockf *)); 7387b6de2bSPoul-Henning Kamp static void lf_wakelock __P((struct lockf *)); 7492dc7331SDavid Greenman 7592dc7331SDavid Greenman /* 7692dc7331SDavid Greenman * Advisory record locking support 7792dc7331SDavid Greenman */ 7892dc7331SDavid Greenman int 7992dc7331SDavid Greenman lf_advlock(ap, head, size) 8092dc7331SDavid Greenman struct vop_advlock_args /* { 8192dc7331SDavid Greenman struct vnode *a_vp; 8292dc7331SDavid Greenman caddr_t a_id; 8392dc7331SDavid Greenman int a_op; 8492dc7331SDavid Greenman struct flock *a_fl; 8592dc7331SDavid Greenman int a_flags; 8692dc7331SDavid Greenman } */ *ap; 8792dc7331SDavid Greenman struct lockf **head; 8892dc7331SDavid Greenman u_quad_t size; 8992dc7331SDavid Greenman { 9092dc7331SDavid Greenman register struct flock *fl = ap->a_fl; 9192dc7331SDavid Greenman register struct lockf *lock; 9292dc7331SDavid Greenman off_t start, end; 9392dc7331SDavid Greenman int error; 9492dc7331SDavid Greenman 9592dc7331SDavid Greenman /* 9692dc7331SDavid Greenman * Avoid the common case of unlocking when inode has no locks. 9792dc7331SDavid Greenman */ 9892dc7331SDavid Greenman if (*head == (struct lockf *)0) { 9992dc7331SDavid Greenman if (ap->a_op != F_SETLK) { 10092dc7331SDavid Greenman fl->l_type = F_UNLCK; 10192dc7331SDavid Greenman return (0); 10292dc7331SDavid Greenman } 10392dc7331SDavid Greenman } 10492dc7331SDavid Greenman /* 10592dc7331SDavid Greenman * Convert the flock structure into a start and end. 10692dc7331SDavid Greenman */ 10792dc7331SDavid Greenman switch (fl->l_whence) { 10892dc7331SDavid Greenman 10992dc7331SDavid Greenman case SEEK_SET: 11092dc7331SDavid Greenman case SEEK_CUR: 11192dc7331SDavid Greenman /* 11292dc7331SDavid Greenman * Caller is responsible for adding any necessary offset 11392dc7331SDavid Greenman * when SEEK_CUR is used. 11492dc7331SDavid Greenman */ 11592dc7331SDavid Greenman start = fl->l_start; 11692dc7331SDavid Greenman break; 11792dc7331SDavid Greenman 11892dc7331SDavid Greenman case SEEK_END: 11992dc7331SDavid Greenman start = size + fl->l_start; 12092dc7331SDavid Greenman break; 12192dc7331SDavid Greenman 12292dc7331SDavid Greenman default: 12392dc7331SDavid Greenman return (EINVAL); 12492dc7331SDavid Greenman } 12592dc7331SDavid Greenman if (start < 0) 12692dc7331SDavid Greenman return (EINVAL); 12792dc7331SDavid Greenman if (fl->l_len == 0) 12892dc7331SDavid Greenman end = -1; 12992dc7331SDavid Greenman else 13092dc7331SDavid Greenman end = start + fl->l_len - 1; 13192dc7331SDavid Greenman /* 13292dc7331SDavid Greenman * Create the lockf structure 13392dc7331SDavid Greenman */ 13492dc7331SDavid Greenman MALLOC(lock, struct lockf *, sizeof *lock, M_LOCKF, M_WAITOK); 13592dc7331SDavid Greenman lock->lf_start = start; 13692dc7331SDavid Greenman lock->lf_end = end; 13792dc7331SDavid Greenman lock->lf_id = ap->a_id; 13892dc7331SDavid Greenman lock->lf_head = head; 13992dc7331SDavid Greenman lock->lf_type = fl->l_type; 14092dc7331SDavid Greenman lock->lf_next = (struct lockf *)0; 14192dc7331SDavid Greenman lock->lf_block = (struct lockf *)0; 14292dc7331SDavid Greenman lock->lf_flags = ap->a_flags; 14392dc7331SDavid Greenman /* 14492dc7331SDavid Greenman * Do the requested operation. 14592dc7331SDavid Greenman */ 14692dc7331SDavid Greenman switch(ap->a_op) { 14792dc7331SDavid Greenman case F_SETLK: 14892dc7331SDavid Greenman return (lf_setlock(lock)); 14992dc7331SDavid Greenman 15092dc7331SDavid Greenman case F_UNLCK: 15192dc7331SDavid Greenman error = lf_clearlock(lock); 15292dc7331SDavid Greenman FREE(lock, M_LOCKF); 15392dc7331SDavid Greenman return (error); 15492dc7331SDavid Greenman 15592dc7331SDavid Greenman case F_GETLK: 15692dc7331SDavid Greenman error = lf_getlock(lock, fl); 15792dc7331SDavid Greenman FREE(lock, M_LOCKF); 15892dc7331SDavid Greenman return (error); 15992dc7331SDavid Greenman 16092dc7331SDavid Greenman default: 16192dc7331SDavid Greenman free(lock, M_LOCKF); 16292dc7331SDavid Greenman return (EINVAL); 16392dc7331SDavid Greenman } 16492dc7331SDavid Greenman /* NOTREACHED */ 16592dc7331SDavid Greenman } 16692dc7331SDavid Greenman 16792dc7331SDavid Greenman /* 16892dc7331SDavid Greenman * Set a byte-range lock. 16992dc7331SDavid Greenman */ 17087b6de2bSPoul-Henning Kamp static int 17192dc7331SDavid Greenman lf_setlock(lock) 17292dc7331SDavid Greenman register struct lockf *lock; 17392dc7331SDavid Greenman { 17492dc7331SDavid Greenman register struct lockf *block; 17592dc7331SDavid Greenman struct lockf **head = lock->lf_head; 17692dc7331SDavid Greenman struct lockf **prev, *overlap, *ltmp; 17792dc7331SDavid Greenman static char lockstr[] = "lockf"; 17892dc7331SDavid Greenman int ovcase, priority, needtolink, error; 17992dc7331SDavid Greenman 18092dc7331SDavid Greenman #ifdef LOCKF_DEBUG 18192dc7331SDavid Greenman if (lockf_debug & 1) 18292dc7331SDavid Greenman lf_print("lf_setlock", lock); 18392dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 18492dc7331SDavid Greenman 18592dc7331SDavid Greenman /* 18692dc7331SDavid Greenman * Set the priority 18792dc7331SDavid Greenman */ 18892dc7331SDavid Greenman priority = PLOCK; 18992dc7331SDavid Greenman if (lock->lf_type == F_WRLCK) 19092dc7331SDavid Greenman priority += 4; 19192dc7331SDavid Greenman priority |= PCATCH; 19292dc7331SDavid Greenman /* 19392dc7331SDavid Greenman * Scan lock list for this file looking for locks that would block us. 19492dc7331SDavid Greenman */ 195bb56ec4aSPoul-Henning Kamp while ((block = lf_getblock(lock))) { 19692dc7331SDavid Greenman /* 19792dc7331SDavid Greenman * Free the structure and return if nonblocking. 19892dc7331SDavid Greenman */ 19992dc7331SDavid Greenman if ((lock->lf_flags & F_WAIT) == 0) { 20092dc7331SDavid Greenman FREE(lock, M_LOCKF); 20192dc7331SDavid Greenman return (EAGAIN); 20292dc7331SDavid Greenman } 20392dc7331SDavid Greenman /* 20492dc7331SDavid Greenman * We are blocked. Since flock style locks cover 20592dc7331SDavid Greenman * the whole file, there is no chance for deadlock. 20692dc7331SDavid Greenman * For byte-range locks we must check for deadlock. 20792dc7331SDavid Greenman * 20892dc7331SDavid Greenman * Deadlock detection is done by looking through the 20992dc7331SDavid Greenman * wait channels to see if there are any cycles that 21092dc7331SDavid Greenman * involve us. MAXDEPTH is set just to make sure we 21192dc7331SDavid Greenman * do not go off into neverland. 21292dc7331SDavid Greenman */ 21392dc7331SDavid Greenman if ((lock->lf_flags & F_POSIX) && 21492dc7331SDavid Greenman (block->lf_flags & F_POSIX)) { 21592dc7331SDavid Greenman register struct proc *wproc; 21692dc7331SDavid Greenman register struct lockf *waitblock; 21792dc7331SDavid Greenman int i = 0; 21892dc7331SDavid Greenman 21992dc7331SDavid Greenman /* The block is waiting on something */ 22092dc7331SDavid Greenman wproc = (struct proc *)block->lf_id; 22192dc7331SDavid Greenman while (wproc->p_wchan && 22292dc7331SDavid Greenman (wproc->p_wmesg == lockstr) && 22392dc7331SDavid Greenman (i++ < maxlockdepth)) { 22492dc7331SDavid Greenman waitblock = (struct lockf *)wproc->p_wchan; 22592dc7331SDavid Greenman /* Get the owner of the blocking lock */ 22692dc7331SDavid Greenman waitblock = waitblock->lf_next; 22792dc7331SDavid Greenman if ((waitblock->lf_flags & F_POSIX) == 0) 22892dc7331SDavid Greenman break; 22992dc7331SDavid Greenman wproc = (struct proc *)waitblock->lf_id; 23092dc7331SDavid Greenman if (wproc == (struct proc *)lock->lf_id) { 23192dc7331SDavid Greenman free(lock, M_LOCKF); 23292dc7331SDavid Greenman return (EDEADLK); 23392dc7331SDavid Greenman } 23492dc7331SDavid Greenman } 23592dc7331SDavid Greenman } 23692dc7331SDavid Greenman /* 23792dc7331SDavid Greenman * For flock type locks, we must first remove 23892dc7331SDavid Greenman * any shared locks that we hold before we sleep 23992dc7331SDavid Greenman * waiting for an exclusive lock. 24092dc7331SDavid Greenman */ 24192dc7331SDavid Greenman if ((lock->lf_flags & F_FLOCK) && 24292dc7331SDavid Greenman lock->lf_type == F_WRLCK) { 24392dc7331SDavid Greenman lock->lf_type = F_UNLCK; 24492dc7331SDavid Greenman (void) lf_clearlock(lock); 24592dc7331SDavid Greenman lock->lf_type = F_WRLCK; 24692dc7331SDavid Greenman } 24792dc7331SDavid Greenman /* 24892dc7331SDavid Greenman * Add our lock to the blocked list and sleep until we're free. 24992dc7331SDavid Greenman * Remember who blocked us (for deadlock detection). 25092dc7331SDavid Greenman */ 25192dc7331SDavid Greenman lock->lf_next = block; 25292dc7331SDavid Greenman lf_addblock(block, lock); 25392dc7331SDavid Greenman #ifdef LOCKF_DEBUG 25492dc7331SDavid Greenman if (lockf_debug & 1) { 25592dc7331SDavid Greenman lf_print("lf_setlock: blocking on", block); 25692dc7331SDavid Greenman lf_printlist("lf_setlock", block); 25792dc7331SDavid Greenman } 25892dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 259bb56ec4aSPoul-Henning Kamp if ((error = tsleep((caddr_t)lock, priority, lockstr, 0))) { 26092dc7331SDavid Greenman /* 26192dc7331SDavid Greenman * Delete ourselves from the waiting to lock list. 26292dc7331SDavid Greenman */ 26392dc7331SDavid Greenman for (block = lock->lf_next; 26492dc7331SDavid Greenman block != NOLOCKF; 26592dc7331SDavid Greenman block = block->lf_block) { 26692dc7331SDavid Greenman if (block->lf_block != lock) 26792dc7331SDavid Greenman continue; 26892dc7331SDavid Greenman block->lf_block = block->lf_block->lf_block; 26992dc7331SDavid Greenman break; 27092dc7331SDavid Greenman } 27192dc7331SDavid Greenman /* 27292dc7331SDavid Greenman * If we did not find ourselves on the list, but 27392dc7331SDavid Greenman * are still linked onto a lock list, then something 27492dc7331SDavid Greenman * is very wrong. 27592dc7331SDavid Greenman */ 27692dc7331SDavid Greenman if (block == NOLOCKF && lock->lf_next != NOLOCKF) 27792dc7331SDavid Greenman panic("lf_setlock: lost lock"); 27892dc7331SDavid Greenman free(lock, M_LOCKF); 27992dc7331SDavid Greenman return (error); 28092dc7331SDavid Greenman } 28192dc7331SDavid Greenman } 28292dc7331SDavid Greenman /* 28392dc7331SDavid Greenman * No blocks!! Add the lock. Note that we will 28492dc7331SDavid Greenman * downgrade or upgrade any overlapping locks this 28592dc7331SDavid Greenman * process already owns. 28692dc7331SDavid Greenman * 28792dc7331SDavid Greenman * Skip over locks owned by other processes. 28892dc7331SDavid Greenman * Handle any locks that overlap and are owned by ourselves. 28992dc7331SDavid Greenman */ 29092dc7331SDavid Greenman prev = head; 29192dc7331SDavid Greenman block = *head; 29292dc7331SDavid Greenman needtolink = 1; 29392dc7331SDavid Greenman for (;;) { 294bb56ec4aSPoul-Henning Kamp ovcase = lf_findoverlap(block, lock, SELF, &prev, &overlap); 295bb56ec4aSPoul-Henning Kamp if (ovcase) 29692dc7331SDavid Greenman block = overlap->lf_next; 29792dc7331SDavid Greenman /* 29892dc7331SDavid Greenman * Six cases: 29992dc7331SDavid Greenman * 0) no overlap 30092dc7331SDavid Greenman * 1) overlap == lock 30192dc7331SDavid Greenman * 2) overlap contains lock 30292dc7331SDavid Greenman * 3) lock contains overlap 30392dc7331SDavid Greenman * 4) overlap starts before lock 30492dc7331SDavid Greenman * 5) overlap ends after lock 30592dc7331SDavid Greenman */ 30692dc7331SDavid Greenman switch (ovcase) { 30792dc7331SDavid Greenman case 0: /* no overlap */ 30892dc7331SDavid Greenman if (needtolink) { 30992dc7331SDavid Greenman *prev = lock; 31092dc7331SDavid Greenman lock->lf_next = overlap; 31192dc7331SDavid Greenman } 31292dc7331SDavid Greenman break; 31392dc7331SDavid Greenman 31492dc7331SDavid Greenman case 1: /* overlap == lock */ 31592dc7331SDavid Greenman /* 31692dc7331SDavid Greenman * If downgrading lock, others may be 31792dc7331SDavid Greenman * able to acquire it. 31892dc7331SDavid Greenman */ 31992dc7331SDavid Greenman if (lock->lf_type == F_RDLCK && 32092dc7331SDavid Greenman overlap->lf_type == F_WRLCK) 32192dc7331SDavid Greenman lf_wakelock(overlap); 32292dc7331SDavid Greenman overlap->lf_type = lock->lf_type; 32392dc7331SDavid Greenman FREE(lock, M_LOCKF); 32492dc7331SDavid Greenman lock = overlap; /* for debug output below */ 32592dc7331SDavid Greenman break; 32692dc7331SDavid Greenman 32792dc7331SDavid Greenman case 2: /* overlap contains lock */ 32892dc7331SDavid Greenman /* 32992dc7331SDavid Greenman * Check for common starting point and different types. 33092dc7331SDavid Greenman */ 33192dc7331SDavid Greenman if (overlap->lf_type == lock->lf_type) { 33292dc7331SDavid Greenman free(lock, M_LOCKF); 33392dc7331SDavid Greenman lock = overlap; /* for debug output below */ 33492dc7331SDavid Greenman break; 33592dc7331SDavid Greenman } 33692dc7331SDavid Greenman if (overlap->lf_start == lock->lf_start) { 33792dc7331SDavid Greenman *prev = lock; 33892dc7331SDavid Greenman lock->lf_next = overlap; 33992dc7331SDavid Greenman overlap->lf_start = lock->lf_end + 1; 34092dc7331SDavid Greenman } else 34192dc7331SDavid Greenman lf_split(overlap, lock); 34292dc7331SDavid Greenman lf_wakelock(overlap); 34392dc7331SDavid Greenman break; 34492dc7331SDavid Greenman 34592dc7331SDavid Greenman case 3: /* lock contains overlap */ 34692dc7331SDavid Greenman /* 34792dc7331SDavid Greenman * If downgrading lock, others may be able to 34892dc7331SDavid Greenman * acquire it, otherwise take the list. 34992dc7331SDavid Greenman */ 35092dc7331SDavid Greenman if (lock->lf_type == F_RDLCK && 35192dc7331SDavid Greenman overlap->lf_type == F_WRLCK) { 35292dc7331SDavid Greenman lf_wakelock(overlap); 35392dc7331SDavid Greenman } else { 35492dc7331SDavid Greenman ltmp = lock->lf_block; 35592dc7331SDavid Greenman lock->lf_block = overlap->lf_block; 35692dc7331SDavid Greenman lf_addblock(lock, ltmp); 35792dc7331SDavid Greenman } 35892dc7331SDavid Greenman /* 35992dc7331SDavid Greenman * Add the new lock if necessary and delete the overlap. 36092dc7331SDavid Greenman */ 36192dc7331SDavid Greenman if (needtolink) { 36292dc7331SDavid Greenman *prev = lock; 36392dc7331SDavid Greenman lock->lf_next = overlap->lf_next; 36492dc7331SDavid Greenman prev = &lock->lf_next; 36592dc7331SDavid Greenman needtolink = 0; 36692dc7331SDavid Greenman } else 36792dc7331SDavid Greenman *prev = overlap->lf_next; 36892dc7331SDavid Greenman free(overlap, M_LOCKF); 36992dc7331SDavid Greenman continue; 37092dc7331SDavid Greenman 37192dc7331SDavid Greenman case 4: /* overlap starts before lock */ 37292dc7331SDavid Greenman /* 37392dc7331SDavid Greenman * Add lock after overlap on the list. 37492dc7331SDavid Greenman */ 37592dc7331SDavid Greenman lock->lf_next = overlap->lf_next; 37692dc7331SDavid Greenman overlap->lf_next = lock; 37792dc7331SDavid Greenman overlap->lf_end = lock->lf_start - 1; 37892dc7331SDavid Greenman prev = &lock->lf_next; 37992dc7331SDavid Greenman lf_wakelock(overlap); 38092dc7331SDavid Greenman needtolink = 0; 38192dc7331SDavid Greenman continue; 38292dc7331SDavid Greenman 38392dc7331SDavid Greenman case 5: /* overlap ends after lock */ 38492dc7331SDavid Greenman /* 38592dc7331SDavid Greenman * Add the new lock before overlap. 38692dc7331SDavid Greenman */ 38792dc7331SDavid Greenman if (needtolink) { 38892dc7331SDavid Greenman *prev = lock; 38992dc7331SDavid Greenman lock->lf_next = overlap; 39092dc7331SDavid Greenman } 39192dc7331SDavid Greenman overlap->lf_start = lock->lf_end + 1; 39292dc7331SDavid Greenman lf_wakelock(overlap); 39392dc7331SDavid Greenman break; 39492dc7331SDavid Greenman } 39592dc7331SDavid Greenman break; 39692dc7331SDavid Greenman } 39792dc7331SDavid Greenman #ifdef LOCKF_DEBUG 39892dc7331SDavid Greenman if (lockf_debug & 1) { 39992dc7331SDavid Greenman lf_print("lf_setlock: got the lock", lock); 40092dc7331SDavid Greenman lf_printlist("lf_setlock", lock); 40192dc7331SDavid Greenman } 40292dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 40392dc7331SDavid Greenman return (0); 40492dc7331SDavid Greenman } 40592dc7331SDavid Greenman 40692dc7331SDavid Greenman /* 40792dc7331SDavid Greenman * Remove a byte-range lock on an inode. 40892dc7331SDavid Greenman * 40992dc7331SDavid Greenman * Generally, find the lock (or an overlap to that lock) 41092dc7331SDavid Greenman * and remove it (or shrink it), then wakeup anyone we can. 41192dc7331SDavid Greenman */ 41287b6de2bSPoul-Henning Kamp static int 41392dc7331SDavid Greenman lf_clearlock(unlock) 41492dc7331SDavid Greenman register struct lockf *unlock; 41592dc7331SDavid Greenman { 41692dc7331SDavid Greenman struct lockf **head = unlock->lf_head; 41792dc7331SDavid Greenman register struct lockf *lf = *head; 41892dc7331SDavid Greenman struct lockf *overlap, **prev; 41992dc7331SDavid Greenman int ovcase; 42092dc7331SDavid Greenman 42192dc7331SDavid Greenman if (lf == NOLOCKF) 42292dc7331SDavid Greenman return (0); 42392dc7331SDavid Greenman #ifdef LOCKF_DEBUG 42492dc7331SDavid Greenman if (unlock->lf_type != F_UNLCK) 42592dc7331SDavid Greenman panic("lf_clearlock: bad type"); 42692dc7331SDavid Greenman if (lockf_debug & 1) 42792dc7331SDavid Greenman lf_print("lf_clearlock", unlock); 42892dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 42992dc7331SDavid Greenman prev = head; 430bb56ec4aSPoul-Henning Kamp while ((ovcase = lf_findoverlap(lf, unlock, SELF, &prev, &overlap))) { 43192dc7331SDavid Greenman /* 43292dc7331SDavid Greenman * Wakeup the list of locks to be retried. 43392dc7331SDavid Greenman */ 43492dc7331SDavid Greenman lf_wakelock(overlap); 43592dc7331SDavid Greenman 43692dc7331SDavid Greenman switch (ovcase) { 43792dc7331SDavid Greenman 43892dc7331SDavid Greenman case 1: /* overlap == lock */ 43992dc7331SDavid Greenman *prev = overlap->lf_next; 44092dc7331SDavid Greenman FREE(overlap, M_LOCKF); 44192dc7331SDavid Greenman break; 44292dc7331SDavid Greenman 44392dc7331SDavid Greenman case 2: /* overlap contains lock: split it */ 44492dc7331SDavid Greenman if (overlap->lf_start == unlock->lf_start) { 44592dc7331SDavid Greenman overlap->lf_start = unlock->lf_end + 1; 44692dc7331SDavid Greenman break; 44792dc7331SDavid Greenman } 44892dc7331SDavid Greenman lf_split(overlap, unlock); 44992dc7331SDavid Greenman overlap->lf_next = unlock->lf_next; 45092dc7331SDavid Greenman break; 45192dc7331SDavid Greenman 45292dc7331SDavid Greenman case 3: /* lock contains overlap */ 45392dc7331SDavid Greenman *prev = overlap->lf_next; 45492dc7331SDavid Greenman lf = overlap->lf_next; 45592dc7331SDavid Greenman free(overlap, M_LOCKF); 45692dc7331SDavid Greenman continue; 45792dc7331SDavid Greenman 45892dc7331SDavid Greenman case 4: /* overlap starts before lock */ 45992dc7331SDavid Greenman overlap->lf_end = unlock->lf_start - 1; 46092dc7331SDavid Greenman prev = &overlap->lf_next; 46192dc7331SDavid Greenman lf = overlap->lf_next; 46292dc7331SDavid Greenman continue; 46392dc7331SDavid Greenman 46492dc7331SDavid Greenman case 5: /* overlap ends after lock */ 46592dc7331SDavid Greenman overlap->lf_start = unlock->lf_end + 1; 46692dc7331SDavid Greenman break; 46792dc7331SDavid Greenman } 46892dc7331SDavid Greenman break; 46992dc7331SDavid Greenman } 47092dc7331SDavid Greenman #ifdef LOCKF_DEBUG 47192dc7331SDavid Greenman if (lockf_debug & 1) 47292dc7331SDavid Greenman lf_printlist("lf_clearlock", unlock); 47392dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 47492dc7331SDavid Greenman return (0); 47592dc7331SDavid Greenman } 47692dc7331SDavid Greenman 47792dc7331SDavid Greenman /* 47892dc7331SDavid Greenman * Check whether there is a blocking lock, 47992dc7331SDavid Greenman * and if so return its process identifier. 48092dc7331SDavid Greenman */ 48187b6de2bSPoul-Henning Kamp static int 48292dc7331SDavid Greenman lf_getlock(lock, fl) 48392dc7331SDavid Greenman register struct lockf *lock; 48492dc7331SDavid Greenman register struct flock *fl; 48592dc7331SDavid Greenman { 48692dc7331SDavid Greenman register struct lockf *block; 48792dc7331SDavid Greenman 48892dc7331SDavid Greenman #ifdef LOCKF_DEBUG 48992dc7331SDavid Greenman if (lockf_debug & 1) 49092dc7331SDavid Greenman lf_print("lf_getlock", lock); 49192dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 49292dc7331SDavid Greenman 493bb56ec4aSPoul-Henning Kamp if ((block = lf_getblock(lock))) { 49492dc7331SDavid Greenman fl->l_type = block->lf_type; 49592dc7331SDavid Greenman fl->l_whence = SEEK_SET; 49692dc7331SDavid Greenman fl->l_start = block->lf_start; 49792dc7331SDavid Greenman if (block->lf_end == -1) 49892dc7331SDavid Greenman fl->l_len = 0; 49992dc7331SDavid Greenman else 50092dc7331SDavid Greenman fl->l_len = block->lf_end - block->lf_start + 1; 50192dc7331SDavid Greenman if (block->lf_flags & F_POSIX) 50292dc7331SDavid Greenman fl->l_pid = ((struct proc *)(block->lf_id))->p_pid; 50392dc7331SDavid Greenman else 50492dc7331SDavid Greenman fl->l_pid = -1; 50592dc7331SDavid Greenman } else { 50692dc7331SDavid Greenman fl->l_type = F_UNLCK; 50792dc7331SDavid Greenman } 50892dc7331SDavid Greenman return (0); 50992dc7331SDavid Greenman } 51092dc7331SDavid Greenman 51192dc7331SDavid Greenman /* 51292dc7331SDavid Greenman * Walk the list of locks for an inode and 51392dc7331SDavid Greenman * return the first blocking lock. 51492dc7331SDavid Greenman */ 51587b6de2bSPoul-Henning Kamp static struct lockf * 51692dc7331SDavid Greenman lf_getblock(lock) 51792dc7331SDavid Greenman register struct lockf *lock; 51892dc7331SDavid Greenman { 51992dc7331SDavid Greenman struct lockf **prev, *overlap, *lf = *(lock->lf_head); 52092dc7331SDavid Greenman int ovcase; 52192dc7331SDavid Greenman 52292dc7331SDavid Greenman prev = lock->lf_head; 523bb56ec4aSPoul-Henning Kamp while ((ovcase = lf_findoverlap(lf, lock, OTHERS, &prev, &overlap))) { 52492dc7331SDavid Greenman /* 52592dc7331SDavid Greenman * We've found an overlap, see if it blocks us 52692dc7331SDavid Greenman */ 52792dc7331SDavid Greenman if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK)) 52892dc7331SDavid Greenman return (overlap); 52992dc7331SDavid Greenman /* 53092dc7331SDavid Greenman * Nope, point to the next one on the list and 53192dc7331SDavid Greenman * see if it blocks us 53292dc7331SDavid Greenman */ 53392dc7331SDavid Greenman lf = overlap->lf_next; 53492dc7331SDavid Greenman } 53592dc7331SDavid Greenman return (NOLOCKF); 53692dc7331SDavid Greenman } 53792dc7331SDavid Greenman 53892dc7331SDavid Greenman /* 53992dc7331SDavid Greenman * Walk the list of locks for an inode to 54092dc7331SDavid Greenman * find an overlapping lock (if any). 54192dc7331SDavid Greenman * 54292dc7331SDavid Greenman * NOTE: this returns only the FIRST overlapping lock. There 54392dc7331SDavid Greenman * may be more than one. 54492dc7331SDavid Greenman */ 54587b6de2bSPoul-Henning Kamp static int 54692dc7331SDavid Greenman lf_findoverlap(lf, lock, type, prev, overlap) 54792dc7331SDavid Greenman register struct lockf *lf; 54892dc7331SDavid Greenman struct lockf *lock; 54992dc7331SDavid Greenman int type; 55092dc7331SDavid Greenman struct lockf ***prev; 55192dc7331SDavid Greenman struct lockf **overlap; 55292dc7331SDavid Greenman { 55392dc7331SDavid Greenman off_t start, end; 55492dc7331SDavid Greenman 55592dc7331SDavid Greenman *overlap = lf; 55692dc7331SDavid Greenman if (lf == NOLOCKF) 55792dc7331SDavid Greenman return (0); 55892dc7331SDavid Greenman #ifdef LOCKF_DEBUG 55992dc7331SDavid Greenman if (lockf_debug & 2) 56092dc7331SDavid Greenman lf_print("lf_findoverlap: looking for overlap in", lock); 56192dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 56292dc7331SDavid Greenman start = lock->lf_start; 56392dc7331SDavid Greenman end = lock->lf_end; 56492dc7331SDavid Greenman while (lf != NOLOCKF) { 56592dc7331SDavid Greenman if (((type & SELF) && lf->lf_id != lock->lf_id) || 56692dc7331SDavid Greenman ((type & OTHERS) && lf->lf_id == lock->lf_id)) { 56792dc7331SDavid Greenman *prev = &lf->lf_next; 56892dc7331SDavid Greenman *overlap = lf = lf->lf_next; 56992dc7331SDavid Greenman continue; 57092dc7331SDavid Greenman } 57192dc7331SDavid Greenman #ifdef LOCKF_DEBUG 57292dc7331SDavid Greenman if (lockf_debug & 2) 57392dc7331SDavid Greenman lf_print("\tchecking", lf); 57492dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 57592dc7331SDavid Greenman /* 57692dc7331SDavid Greenman * OK, check for overlap 57792dc7331SDavid Greenman * 57892dc7331SDavid Greenman * Six cases: 57992dc7331SDavid Greenman * 0) no overlap 58092dc7331SDavid Greenman * 1) overlap == lock 58192dc7331SDavid Greenman * 2) overlap contains lock 58292dc7331SDavid Greenman * 3) lock contains overlap 58392dc7331SDavid Greenman * 4) overlap starts before lock 58492dc7331SDavid Greenman * 5) overlap ends after lock 58592dc7331SDavid Greenman */ 58692dc7331SDavid Greenman if ((lf->lf_end != -1 && start > lf->lf_end) || 58792dc7331SDavid Greenman (end != -1 && lf->lf_start > end)) { 58892dc7331SDavid Greenman /* Case 0 */ 58992dc7331SDavid Greenman #ifdef LOCKF_DEBUG 59092dc7331SDavid Greenman if (lockf_debug & 2) 59192dc7331SDavid Greenman printf("no overlap\n"); 59292dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 59392dc7331SDavid Greenman if ((type & SELF) && end != -1 && lf->lf_start > end) 59492dc7331SDavid Greenman return (0); 59592dc7331SDavid Greenman *prev = &lf->lf_next; 59692dc7331SDavid Greenman *overlap = lf = lf->lf_next; 59792dc7331SDavid Greenman continue; 59892dc7331SDavid Greenman } 59992dc7331SDavid Greenman if ((lf->lf_start == start) && (lf->lf_end == end)) { 60092dc7331SDavid Greenman /* Case 1 */ 60192dc7331SDavid Greenman #ifdef LOCKF_DEBUG 60292dc7331SDavid Greenman if (lockf_debug & 2) 60392dc7331SDavid Greenman printf("overlap == lock\n"); 60492dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 60592dc7331SDavid Greenman return (1); 60692dc7331SDavid Greenman } 60792dc7331SDavid Greenman if ((lf->lf_start <= start) && 60892dc7331SDavid Greenman (end != -1) && 60992dc7331SDavid Greenman ((lf->lf_end >= end) || (lf->lf_end == -1))) { 61092dc7331SDavid Greenman /* Case 2 */ 61192dc7331SDavid Greenman #ifdef LOCKF_DEBUG 61292dc7331SDavid Greenman if (lockf_debug & 2) 61392dc7331SDavid Greenman printf("overlap contains lock\n"); 61492dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 61592dc7331SDavid Greenman return (2); 61692dc7331SDavid Greenman } 61792dc7331SDavid Greenman if (start <= lf->lf_start && 61892dc7331SDavid Greenman (end == -1 || 61992dc7331SDavid Greenman (lf->lf_end != -1 && end >= lf->lf_end))) { 62092dc7331SDavid Greenman /* Case 3 */ 62192dc7331SDavid Greenman #ifdef LOCKF_DEBUG 62292dc7331SDavid Greenman if (lockf_debug & 2) 62392dc7331SDavid Greenman printf("lock contains overlap\n"); 62492dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 62592dc7331SDavid Greenman return (3); 62692dc7331SDavid Greenman } 62792dc7331SDavid Greenman if ((lf->lf_start < start) && 62892dc7331SDavid Greenman ((lf->lf_end >= start) || (lf->lf_end == -1))) { 62992dc7331SDavid Greenman /* Case 4 */ 63092dc7331SDavid Greenman #ifdef LOCKF_DEBUG 63192dc7331SDavid Greenman if (lockf_debug & 2) 63292dc7331SDavid Greenman printf("overlap starts before lock\n"); 63392dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 63492dc7331SDavid Greenman return (4); 63592dc7331SDavid Greenman } 63692dc7331SDavid Greenman if ((lf->lf_start > start) && 63792dc7331SDavid Greenman (end != -1) && 63892dc7331SDavid Greenman ((lf->lf_end > end) || (lf->lf_end == -1))) { 63992dc7331SDavid Greenman /* Case 5 */ 64092dc7331SDavid Greenman #ifdef LOCKF_DEBUG 64192dc7331SDavid Greenman if (lockf_debug & 2) 64292dc7331SDavid Greenman printf("overlap ends after lock\n"); 64392dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 64492dc7331SDavid Greenman return (5); 64592dc7331SDavid Greenman } 64692dc7331SDavid Greenman panic("lf_findoverlap: default"); 64792dc7331SDavid Greenman } 64892dc7331SDavid Greenman return (0); 64992dc7331SDavid Greenman } 65092dc7331SDavid Greenman 65192dc7331SDavid Greenman /* 65292dc7331SDavid Greenman * Add a lock to the end of the blocked list. 65392dc7331SDavid Greenman */ 65487b6de2bSPoul-Henning Kamp static void 655f15b8850SDavid Greenman lf_addblock(blocklist, lock) 656f15b8850SDavid Greenman struct lockf *blocklist; 65792dc7331SDavid Greenman struct lockf *lock; 65892dc7331SDavid Greenman { 65992dc7331SDavid Greenman register struct lockf *lf; 66092dc7331SDavid Greenman 661f15b8850SDavid Greenman if (lock == NOLOCKF) 66292dc7331SDavid Greenman return; 66392dc7331SDavid Greenman #ifdef LOCKF_DEBUG 66492dc7331SDavid Greenman if (lockf_debug & 2) { 665f15b8850SDavid Greenman lf_print("addblock: adding", lock); 666f15b8850SDavid Greenman lf_print("to blocked list of", blocklist); 66792dc7331SDavid Greenman } 66892dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 669f15b8850SDavid Greenman if ((lf = blocklist->lf_block) == NOLOCKF) { 670f15b8850SDavid Greenman blocklist->lf_block = lock; 67192dc7331SDavid Greenman return; 67292dc7331SDavid Greenman } 67392dc7331SDavid Greenman while (lf->lf_block != NOLOCKF) 67492dc7331SDavid Greenman lf = lf->lf_block; 675f15b8850SDavid Greenman lf->lf_block = lock; 67692dc7331SDavid Greenman return; 67792dc7331SDavid Greenman } 67892dc7331SDavid Greenman 67992dc7331SDavid Greenman /* 68092dc7331SDavid Greenman * Split a lock and a contained region into 68192dc7331SDavid Greenman * two or three locks as necessary. 68292dc7331SDavid Greenman */ 68387b6de2bSPoul-Henning Kamp static void 68492dc7331SDavid Greenman lf_split(lock1, lock2) 68592dc7331SDavid Greenman register struct lockf *lock1; 68692dc7331SDavid Greenman register struct lockf *lock2; 68792dc7331SDavid Greenman { 68892dc7331SDavid Greenman register struct lockf *splitlock; 68992dc7331SDavid Greenman 69092dc7331SDavid Greenman #ifdef LOCKF_DEBUG 69192dc7331SDavid Greenman if (lockf_debug & 2) { 69292dc7331SDavid Greenman lf_print("lf_split", lock1); 69392dc7331SDavid Greenman lf_print("splitting from", lock2); 69492dc7331SDavid Greenman } 69592dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 69692dc7331SDavid Greenman /* 69792dc7331SDavid Greenman * Check to see if spliting into only two pieces. 69892dc7331SDavid Greenman */ 69992dc7331SDavid Greenman if (lock1->lf_start == lock2->lf_start) { 70092dc7331SDavid Greenman lock1->lf_start = lock2->lf_end + 1; 70192dc7331SDavid Greenman lock2->lf_next = lock1; 70292dc7331SDavid Greenman return; 70392dc7331SDavid Greenman } 70492dc7331SDavid Greenman if (lock1->lf_end == lock2->lf_end) { 70592dc7331SDavid Greenman lock1->lf_end = lock2->lf_start - 1; 70692dc7331SDavid Greenman lock2->lf_next = lock1->lf_next; 70792dc7331SDavid Greenman lock1->lf_next = lock2; 70892dc7331SDavid Greenman return; 70992dc7331SDavid Greenman } 71092dc7331SDavid Greenman /* 71192dc7331SDavid Greenman * Make a new lock consisting of the last part of 71292dc7331SDavid Greenman * the encompassing lock 71392dc7331SDavid Greenman */ 71492dc7331SDavid Greenman MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK); 71592dc7331SDavid Greenman bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock); 71692dc7331SDavid Greenman splitlock->lf_start = lock2->lf_end + 1; 71792dc7331SDavid Greenman splitlock->lf_block = NOLOCKF; 71892dc7331SDavid Greenman lock1->lf_end = lock2->lf_start - 1; 71992dc7331SDavid Greenman /* 72092dc7331SDavid Greenman * OK, now link it in 72192dc7331SDavid Greenman */ 72292dc7331SDavid Greenman splitlock->lf_next = lock1->lf_next; 72392dc7331SDavid Greenman lock2->lf_next = splitlock; 72492dc7331SDavid Greenman lock1->lf_next = lock2; 72592dc7331SDavid Greenman } 72692dc7331SDavid Greenman 72792dc7331SDavid Greenman /* 72892dc7331SDavid Greenman * Wakeup a blocklist 72992dc7331SDavid Greenman */ 73087b6de2bSPoul-Henning Kamp static void 73192dc7331SDavid Greenman lf_wakelock(listhead) 73292dc7331SDavid Greenman struct lockf *listhead; 73392dc7331SDavid Greenman { 73492dc7331SDavid Greenman register struct lockf *blocklist, *wakelock; 73592dc7331SDavid Greenman 73692dc7331SDavid Greenman blocklist = listhead->lf_block; 73792dc7331SDavid Greenman listhead->lf_block = NOLOCKF; 73892dc7331SDavid Greenman while (blocklist != NOLOCKF) { 73992dc7331SDavid Greenman wakelock = blocklist; 74092dc7331SDavid Greenman blocklist = blocklist->lf_block; 74192dc7331SDavid Greenman wakelock->lf_block = NOLOCKF; 74292dc7331SDavid Greenman wakelock->lf_next = NOLOCKF; 74392dc7331SDavid Greenman #ifdef LOCKF_DEBUG 74492dc7331SDavid Greenman if (lockf_debug & 2) 74592dc7331SDavid Greenman lf_print("lf_wakelock: awakening", wakelock); 74692dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 74792dc7331SDavid Greenman wakeup((caddr_t)wakelock); 74892dc7331SDavid Greenman } 74992dc7331SDavid Greenman } 75092dc7331SDavid Greenman 75192dc7331SDavid Greenman #ifdef LOCKF_DEBUG 75292dc7331SDavid Greenman /* 75392dc7331SDavid Greenman * Print out a lock. 75492dc7331SDavid Greenman */ 75592dc7331SDavid Greenman void 75692dc7331SDavid Greenman lf_print(tag, lock) 75792dc7331SDavid Greenman char *tag; 75892dc7331SDavid Greenman register struct lockf *lock; 75992dc7331SDavid Greenman { 76092dc7331SDavid Greenman 76192dc7331SDavid Greenman printf("%s: lock 0x%lx for ", tag, lock); 76292dc7331SDavid Greenman if (lock->lf_flags & F_POSIX) 76392dc7331SDavid Greenman printf("proc %d", ((struct proc *)(lock->lf_id))->p_pid); 76492dc7331SDavid Greenman else 76592dc7331SDavid Greenman printf("id 0x%x", lock->lf_id); 76692dc7331SDavid Greenman printf(" in ino %d on dev <%d, %d>, %s, start %d, end %d", 76792dc7331SDavid Greenman lock->lf_inode->i_number, 76892dc7331SDavid Greenman major(lock->lf_inode->i_dev), 76992dc7331SDavid Greenman minor(lock->lf_inode->i_dev), 77092dc7331SDavid Greenman lock->lf_type == F_RDLCK ? "shared" : 77192dc7331SDavid Greenman lock->lf_type == F_WRLCK ? "exclusive" : 77292dc7331SDavid Greenman lock->lf_type == F_UNLCK ? "unlock" : 77392dc7331SDavid Greenman "unknown", lock->lf_start, lock->lf_end); 77492dc7331SDavid Greenman if (lock->lf_block) 77592dc7331SDavid Greenman printf(" block 0x%x\n", lock->lf_block); 77692dc7331SDavid Greenman else 77792dc7331SDavid Greenman printf("\n"); 77892dc7331SDavid Greenman } 77992dc7331SDavid Greenman 78092dc7331SDavid Greenman void 78192dc7331SDavid Greenman lf_printlist(tag, lock) 78292dc7331SDavid Greenman char *tag; 78392dc7331SDavid Greenman struct lockf *lock; 78492dc7331SDavid Greenman { 78592dc7331SDavid Greenman register struct lockf *lf; 78692dc7331SDavid Greenman 78792dc7331SDavid Greenman printf("%s: Lock list for ino %d on dev <%d, %d>:\n", 78892dc7331SDavid Greenman tag, lock->lf_inode->i_number, 78992dc7331SDavid Greenman major(lock->lf_inode->i_dev), 79092dc7331SDavid Greenman minor(lock->lf_inode->i_dev)); 79192dc7331SDavid Greenman for (lf = lock->lf_inode->i_lockf; lf; lf = lf->lf_next) { 79292dc7331SDavid Greenman printf("\tlock 0x%lx for ", lf); 79392dc7331SDavid Greenman if (lf->lf_flags & F_POSIX) 79492dc7331SDavid Greenman printf("proc %d", ((struct proc *)(lf->lf_id))->p_pid); 79592dc7331SDavid Greenman else 79692dc7331SDavid Greenman printf("id 0x%x", lf->lf_id); 79792dc7331SDavid Greenman printf(", %s, start %d, end %d", 79892dc7331SDavid Greenman lf->lf_type == F_RDLCK ? "shared" : 79992dc7331SDavid Greenman lf->lf_type == F_WRLCK ? "exclusive" : 80092dc7331SDavid Greenman lf->lf_type == F_UNLCK ? "unlock" : 80192dc7331SDavid Greenman "unknown", lf->lf_start, lf->lf_end); 80292dc7331SDavid Greenman if (lf->lf_block) 80392dc7331SDavid Greenman printf(" block 0x%x\n", lf->lf_block); 80492dc7331SDavid Greenman else 80592dc7331SDavid Greenman printf("\n"); 80692dc7331SDavid Greenman } 80792dc7331SDavid Greenman } 80892dc7331SDavid Greenman #endif /* LOCKF_DEBUG */ 809