diff options
Diffstat (limited to 'sys/kern/kern_lockf.c')
-rw-r--r-- | sys/kern/kern_lockf.c | 123 |
1 files changed, 54 insertions, 69 deletions
diff --git a/sys/kern/kern_lockf.c b/sys/kern/kern_lockf.c index aea3976..3491e63 100644 --- a/sys/kern/kern_lockf.c +++ b/sys/kern/kern_lockf.c @@ -52,16 +52,18 @@ * This variable controls the maximum number of processes that will * be checked in doing deadlock detection. */ -int maxlockdepth = MAXDEPTH; +static int maxlockdepth = MAXDEPTH; #ifdef LOCKF_DEBUG +#include <vm/vm.h> +#include <sys/sysctl.h> int lockf_debug = 0; +SYSCTL_INT(_debug, 4, lockf_debug, CTLFLAG_RW, &lockf_debug, 0, ""); #endif #define NOLOCKF (struct lockf *)0 #define SELF 0x1 #define OTHERS 0x2 -static void lf_addblock __P((struct lockf *, struct lockf *)); static int lf_clearlock __P((struct lockf *)); static int lf_findoverlap __P((struct lockf *, struct lockf *, int, struct lockf ***, struct lockf **)); @@ -138,10 +140,11 @@ lf_advlock(ap, head, size) lock->lf_start = start; lock->lf_end = end; lock->lf_id = ap->a_id; - lock->lf_head = head; +/* lock->lf_inode = ip; */ /* XXX JH */ lock->lf_type = fl->l_type; + lock->lf_head = head; lock->lf_next = (struct lockf *)0; - lock->lf_block = (struct lockf *)0; + TAILQ_INIT(&lock->lf_blkhd); lock->lf_flags = ap->a_flags; /* * Do the requested operation. @@ -252,7 +255,7 @@ lf_setlock(lock) * Remember who blocked us (for deadlock detection). */ lock->lf_next = block; - lf_addblock(block, lock); + TAILQ_INSERT_TAIL(&block->lf_blkhd, lock, lf_block); #ifdef LOCKF_DEBUG if (lockf_debug & 1) { lf_print("lf_setlock: blocking on", block); @@ -260,19 +263,19 @@ lf_setlock(lock) } #endif /* LOCKF_DEBUG */ if ((error = tsleep((caddr_t)lock, priority, lockstr, 0))) { - /* - * Delete ourselves from the waiting to lock list. - */ - for (block = lock->lf_next; - block != NOLOCKF; - block = block->lf_block) { - if (block->lf_block != lock) - continue; - block->lf_block = block->lf_block->lf_block; - break; - } - free(lock, M_LOCKF); - return (error); + /* + * We may have been awakened by a signal (in + * which case we must remove ourselves from the + * blocked list) and/or by another process + * releasing a lock (in which case we have already + * been removed from the blocked list and our + * lf_next field set to NOLOCKF). + */ + if (lock->lf_next) + TAILQ_REMOVE(&lock->lf_next->lf_blkhd, lock, + lf_block); + free(lock, M_LOCKF); + return (error); } } /* @@ -347,9 +350,12 @@ lf_setlock(lock) overlap->lf_type == F_WRLCK) { lf_wakelock(overlap); } else { - ltmp = lock->lf_block; - lock->lf_block = overlap->lf_block; - lf_addblock(lock, ltmp); + while (ltmp = overlap->lf_blkhd.tqh_first) { + TAILQ_REMOVE(&overlap->lf_blkhd, ltmp, + lf_block); + TAILQ_INSERT_TAIL(&lock->lf_blkhd, + ltmp, lf_block); + } } /* * Add the new lock if necessary and delete the overlap. @@ -645,34 +651,6 @@ lf_findoverlap(lf, lock, type, prev, overlap) } /* - * Add a lock to the end of the blocked list. - */ -static void -lf_addblock(blocklist, lock) - struct lockf *blocklist; - struct lockf *lock; -{ - register struct lockf *lf; - - if (lock == NOLOCKF) - return; -#ifdef LOCKF_DEBUG - if (lockf_debug & 2) { - lf_print("addblock: adding", lock); - lf_print("to blocked list of", blocklist); - } -#endif /* LOCKF_DEBUG */ - if ((lf = blocklist->lf_block) == NOLOCKF) { - blocklist->lf_block = lock; - return; - } - while (lf->lf_block != NOLOCKF) - lf = lf->lf_block; - lf->lf_block = lock; - return; -} - -/* * Split a lock and a contained region into * two or three locks as necessary. */ @@ -710,7 +688,7 @@ lf_split(lock1, lock2) MALLOC(splitlock, struct lockf *, sizeof *splitlock, M_LOCKF, M_WAITOK); bcopy((caddr_t)lock1, (caddr_t)splitlock, sizeof *splitlock); splitlock->lf_start = lock2->lf_end + 1; - splitlock->lf_block = NOLOCKF; + TAILQ_INIT(&splitlock->lf_blkhd); lock1->lf_end = lock2->lf_start - 1; /* * OK, now link it in @@ -727,28 +705,23 @@ static void lf_wakelock(listhead) struct lockf *listhead; { - register struct lockf *blocklist, *wakelock; - - blocklist = listhead->lf_block; - listhead->lf_block = NOLOCKF; - while (blocklist != NOLOCKF) { - wakelock = blocklist; - blocklist = blocklist->lf_block; - wakelock->lf_block = NOLOCKF; + register struct lockf *wakelock; + + while (wakelock = listhead->lf_blkhd.tqh_first) { + TAILQ_REMOVE(&listhead->lf_blkhd, wakelock, lf_block); wakelock->lf_next = NOLOCKF; #ifdef LOCKF_DEBUG if (lockf_debug & 2) lf_print("lf_wakelock: awakening", wakelock); #endif /* LOCKF_DEBUG */ - wakeup((caddr_t)wakelock); - } + wakeup((caddr_t)wakelock); + } } #ifdef LOCKF_DEBUG /* * Print out a lock. */ -void lf_print(tag, lock) char *tag; register struct lockf *lock; @@ -767,18 +740,17 @@ lf_print(tag, lock) lock->lf_type == F_WRLCK ? "exclusive" : lock->lf_type == F_UNLCK ? "unlock" : "unknown", lock->lf_start, lock->lf_end); - if (lock->lf_block) - printf(" block 0x%x\n", lock->lf_block); + if (lock->lf_blkhd.tqh_first) + printf(" block 0x%x\n", lock->lf_blkhd.tqh_first); else printf("\n"); } -void lf_printlist(tag, lock) char *tag; struct lockf *lock; { - register struct lockf *lf; + register struct lockf *lf, *blk; printf("%s: Lock list for ino %d on dev <%d, %d>:\n", tag, lock->lf_inode->i_number, @@ -795,10 +767,23 @@ lf_printlist(tag, lock) lf->lf_type == F_WRLCK ? "exclusive" : lf->lf_type == F_UNLCK ? "unlock" : "unknown", lf->lf_start, lf->lf_end); - if (lf->lf_block) - printf(" block 0x%x\n", lf->lf_block); - else - printf("\n"); + for (blk = lf->lf_blkhd.tqh_first; blk; + blk = blk->lf_block.tqe_next) { + printf("\n\t\tlock request 0x%lx for ", blk); + if (blk->lf_flags & F_POSIX) + printf("proc %d", + ((struct proc *)(blk->lf_id))->p_pid); + else + printf("id 0x%x", blk->lf_id); + printf(", %s, start %d, end %d", + blk->lf_type == F_RDLCK ? "shared" : + blk->lf_type == F_WRLCK ? "exclusive" : + blk->lf_type == F_UNLCK ? "unlock" : + "unknown", blk->lf_start, blk->lf_end); + if (blk->lf_blkhd.tqh_first) + panic("lf_printlist: bad list"); + } + printf("\n"); } } #endif /* LOCKF_DEBUG */ |