summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2002-01-12 20:57:36 +0000
committermckusick <mckusick@FreeBSD.org>2002-01-12 20:57:36 +0000
commitc6e526cffc373bd730b48c61cb3e36af675ee7ae (patch)
tree48f788593ada3fbbe36cc6b9836d6182002f5d25 /sys/ufs
parent08d40edb03cc948c5f3c599c70ad2ed8ee42db56 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c114
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);
OpenPOWER on IntegriCloud