diff options
author | mckusick <mckusick@FreeBSD.org> | 2002-01-12 20:57:36 +0000 |
---|---|---|
committer | mckusick <mckusick@FreeBSD.org> | 2002-01-12 20:57:36 +0000 |
commit | c6e526cffc373bd730b48c61cb3e36af675ee7ae (patch) | |
tree | 48f788593ada3fbbe36cc6b9836d6182002f5d25 /sys/ufs/ffs/ffs_softdep.c | |
parent | 08d40edb03cc948c5f3c599c70ad2ed8ee42db56 (diff) | |
download | FreeBSD-src-c6e526cffc373bd730b48c61cb3e36af675ee7ae.zip FreeBSD-src-c6e526cffc373bd730b48c61cb3e36af675ee7ae.tar.gz |
When going to sleep, we must save our SPL so that it does not get
lost if some other process uses the lock while we are sleeping. We
restore it after we have slept. This functionality is provided by
a new routine interlocked_sleep() that wraps the interlocking with
functions that sleep. This function is then used in place of the
old ACQUIRE_LOCK_INTERLOCKED() and FREE_LOCK_INTERLOCKED() macros.
Submitted by: Debbie Chu <dchu@juniper.net>
Diffstat (limited to 'sys/ufs/ffs/ffs_softdep.c')
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 114 |
1 files changed, 76 insertions, 38 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index c2126c8..8316254 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -227,8 +227,6 @@ static struct lockit { } lk = { 0 }; #define ACQUIRE_LOCK(lk) (lk)->lkt_spl = splbio() #define FREE_LOCK(lk) splx((lk)->lkt_spl) -#define ACQUIRE_LOCK_INTERLOCKED(lk) -#define FREE_LOCK_INTERLOCKED(lk) #else /* DEBUG */ #define NOHOLDER ((struct thread *)-1) @@ -241,13 +239,10 @@ static int lockcnt; static void acquire_lock __P((struct lockit *)); static void free_lock __P((struct lockit *)); -static void acquire_lock_interlocked __P((struct lockit *)); -static void free_lock_interlocked __P((struct lockit *)); +void softdep_panic __P((char *)); #define ACQUIRE_LOCK(lk) acquire_lock(lk) #define FREE_LOCK(lk) free_lock(lk) -#define ACQUIRE_LOCK_INTERLOCKED(lk) acquire_lock_interlocked(lk) -#define FREE_LOCK_INTERLOCKED(lk) free_lock_interlocked(lk) static void acquire_lock(lk) @@ -279,36 +274,78 @@ free_lock(lk) splx(lk->lkt_spl); } -static void -acquire_lock_interlocked(lk) +/* + * Function to release soft updates lock and panic. + */ +void +softdep_panic(msg) + char *msg; +{ + + if (lk.lkt_held != NOHOLDER) + FREE_LOCK(&lk); + panic(msg); +} +#endif /* DEBUG */ + +static int interlocked_sleep __P((struct lockit *, int, void *, int, + const char *, int)); + +/* + * When going to sleep, we must save our SPL so that it does + * not get lost if some other process uses the lock while we + * are sleeping. We restore it after we have slept. This routine + * wraps the interlocking with functions that sleep. The list + * below enumerates the available set of operations. + */ +#define UNKNOWN 0 +#define SLEEP 1 +#define LOCKBUF 2 + +static int +interlocked_sleep(lk, op, ident, flags, wmesg, timo) struct lockit *lk; + int op; + void *ident; + int flags; + const char *wmesg; + int timo; { struct thread *holder; + int s, retval; + s = lk->lkt_spl; +# ifdef DEBUG + if (lk->lkt_held == NOHOLDER) + panic("interlocked_sleep: lock not held"); + lk->lkt_held = NOHOLDER; +# endif /* DEBUG */ + switch (op) { + case SLEEP: + retval = tsleep(ident, flags, wmesg, timo); + break; + case LOCKBUF: + retval = BUF_LOCK((struct buf *)ident, flags); + break; + default: + panic("interlocked_sleep: unknown operation"); + } +# ifdef DEBUG if (lk->lkt_held != NOHOLDER) { holder = lk->lkt_held; FREE_LOCK(lk); if (holder == curthread) - panic("softdep_lock_interlocked: locking against self"); + panic("interlocked_sleep: locking against self"); else - panic("softdep_lock_interlocked: lock held by %p", - holder); + panic("interlocked_sleep: lock held by %p", holder); } lk->lkt_held = curthread; lockcnt++; +# endif /* DEBUG */ + lk->lkt_spl = s; + return (retval); } -static void -free_lock_interlocked(lk) - struct lockit *lk; -{ - - if (lk->lkt_held == NOHOLDER) - panic("softdep_unlock_interlocked: lock not held"); - lk->lkt_held = NOHOLDER; -} -#endif /* DEBUG */ - /* * Place holder for real semaphores. */ @@ -344,12 +381,13 @@ sema_get(semap, interlock) { if (semap->value++ > 0) { - if (interlock != NULL) - FREE_LOCK_INTERLOCKED(interlock); - tsleep((caddr_t)semap, semap->prio, semap->name, semap->timo); if (interlock != NULL) { - ACQUIRE_LOCK_INTERLOCKED(interlock); + interlocked_sleep(interlock, SLEEP, (caddr_t)semap, + semap->prio, semap->name, semap->timo); FREE_LOCK(interlock); + } else { + tsleep((caddr_t)semap, semap->prio, semap->name, + semap->timo); } return (0); } @@ -4863,9 +4901,8 @@ request_cleanup(resource, islocked) proc_waiting += 1; if (handle.callout == NULL) handle = timeout(pause_timer, 0, tickdelay > 2 ? tickdelay : 2); - FREE_LOCK_INTERLOCKED(&lk); - (void) tsleep((caddr_t)&proc_waiting, PPAUSE, "softupdate", 0); - ACQUIRE_LOCK_INTERLOCKED(&lk); + interlocked_sleep(&lk, SLEEP, (caddr_t)&proc_waiting, PPAUSE, + "softupdate", 0); proc_waiting -= 1; if (islocked == 0) FREE_LOCK(&lk); @@ -5104,6 +5141,7 @@ getdirtybuf(bpp, waitfor) int waitfor; { struct buf *bp; + int error; for (;;) { if ((bp = *bpp) == NULL) @@ -5115,17 +5153,18 @@ getdirtybuf(bpp, waitfor) if (waitfor != MNT_WAIT) return (0); bp->b_xflags |= BX_BKGRDWAIT; - FREE_LOCK_INTERLOCKED(&lk); - tsleep(&bp->b_xflags, PRIBIO, "getbuf", 0); - ACQUIRE_LOCK_INTERLOCKED(&lk); + interlocked_sleep(&lk, SLEEP, &bp->b_xflags, PRIBIO, + "getbuf", 0); continue; } if (waitfor != MNT_WAIT) return (0); - FREE_LOCK_INTERLOCKED(&lk); - if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL) != ENOLCK) + error = interlocked_sleep(&lk, LOCKBUF, bp, + LK_EXCLUSIVE | LK_SLEEPFAIL, 0, 0); + if (error != ENOLCK) { + FREE_LOCK(&lk); panic("getdirtybuf: inconsistent lock"); - ACQUIRE_LOCK_INTERLOCKED(&lk); + } } if ((bp->b_flags & B_DELWRI) == 0) { BUF_UNLOCK(bp); @@ -5149,9 +5188,8 @@ drain_output(vp, islocked) ACQUIRE_LOCK(&lk); while (vp->v_numoutput) { vp->v_flag |= VBWAIT; - FREE_LOCK_INTERLOCKED(&lk); - tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "drainvp", 0); - ACQUIRE_LOCK_INTERLOCKED(&lk); + interlocked_sleep(&lk, SLEEP, (caddr_t)&vp->v_numoutput, + PRIBIO + 1, "drainvp", 0); } if (!islocked) FREE_LOCK(&lk); |