summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrog <grog@FreeBSD.org>2001-05-22 02:34:30 +0000
committergrog <grog@FreeBSD.org>2001-05-22 02:34:30 +0000
commit436eef361cf46e88b3652cdbfc56d6bb3a8aec06 (patch)
treec3fa8fa9110dd6ca94db33965aac80df7e3902cc
parent86233b07badbdc56a1a571faeb4d3ec94a227f81 (diff)
downloadFreeBSD-src-436eef361cf46e88b3652cdbfc56d6bb3a8aec06.zip
FreeBSD-src-436eef361cf46e88b3652cdbfc56d6bb3a8aec06.tar.gz
Add a new debug flag, DEBUG_LOCKREQS, which logs only lock requests.
Use this instead of DEBUG_LASTREQS to decide whether to log lock requests. MFS: vinumlock: Catch a potential race condition where one process is waiting for a lock, and between the time it is woken and it retries the lock, another process gets it and places it in the first entry in the table. This problem has not been observed, but it's possible, and it's easy enough to fix. Submitted by: tegge vinumunlock: Catch a real bug capable of hanging a system. When releasing a lock, vinumunlock() called wakeup_one. This caused wakeups to sometimes get lost. After due consideration, we think that this is due to the fact that you can't guarantee that some other process is also waiting on the same address. This makes wakeup_one a very dangerous function to use.
-rw-r--r--sys/dev/vinum/vinumlock.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/sys/dev/vinum/vinumlock.c b/sys/dev/vinum/vinumlock.c
index 801f13f..f7d3f78 100644
--- a/sys/dev/vinum/vinumlock.c
+++ b/sys/dev/vinum/vinumlock.c
@@ -154,17 +154,18 @@ lockrange(daddr_t stripe, struct buf *bp, struct plex *plex)
if ((lock->stripe == stripe) /* it's our stripe */
&&(lock->bp != bp)) { /* but not our request */
#ifdef VINUMDEBUG
- if (debug & DEBUG_LASTREQS) {
- struct rangelock info;
+ if (debug & DEBUG_LOCKREQS) {
+ struct rangelockinfo lockinfo;
- info.stripe = stripe;
- info.bp = bp;
- logrq(loginfo_lockwait, (union rqinfou) &info, bp);
+ lockinfo.stripe = stripe;
+ lockinfo.bp = bp;
+ lockinfo.plexno = plex->plexno;
+ logrq(loginfo_lockwait, (union rqinfou) &lockinfo, bp);
}
#endif
plex->lockwaits++; /* waited one more time */
msleep(lock, &plex->lockmtx, PRIBIO, "vrlock", 0);
- lock = plex->lock; /* start again */
+ lock = &plex->lock[-1]; /* start again */
foundlocks = 0;
pos = NULL;
}
@@ -189,8 +190,14 @@ lockrange(daddr_t stripe, struct buf *bp, struct plex *plex)
plex->usedlocks++; /* one more lock */
mtx_unlock(&plex->lockmtx);
#ifdef VINUMDEBUG
- if (debug & DEBUG_LASTREQS)
- logrq(loginfo_lock, (union rqinfou) pos, bp);
+ if (debug & DEBUG_LOCKREQS) {
+ struct rangelockinfo lockinfo;
+
+ lockinfo.stripe = stripe;
+ lockinfo.bp = bp;
+ lockinfo.plexno = plex->plexno;
+ logrq(loginfo_lock, (union rqinfou) &lockinfo, bp);
+ }
#endif
return pos;
}
@@ -211,14 +218,20 @@ unlockrange(int plexno, struct rangelock *lock)
&plex->lock[PLEX_LOCKS]);
#endif
#ifdef VINUMDEBUG
- if (debug & DEBUG_LASTREQS)
- logrq(loginfo_unlock, (union rqinfou) lock, lock->bp);
+ if (debug & DEBUG_LOCKREQS) {
+ struct rangelockinfo lockinfo;
+
+ lockinfo.stripe = lock->stripe;
+ lockinfo.bp = lock->bp;
+ lockinfo.plexno = plex->plexno;
+ logrq(loginfo_lockwait, (union rqinfou) &lockinfo, lock->bp);
+ }
#endif
lock->stripe = 0; /* no longer used */
plex->usedlocks--; /* one less lock */
if (plex->usedlocks == PLEX_LOCKS - 1) /* we were full, */
- wakeup_one(&plex->usedlocks); /* get a waiter if one's there */
- wakeup_one((void *) lock);
+ wakeup(&plex->usedlocks); /* get a waiter if one's there */
+ wakeup((void *) lock);
}
/* Get a lock for the global config, wait if it's not available */
OpenPOWER on IntegriCloud