summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_witness.c
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2008-08-29 15:47:53 +0000
committerattilio <attilio@FreeBSD.org>2008-08-29 15:47:53 +0000
commit8f53106a9eee67edefaa2dba7492395b96accb2d (patch)
tree4e2e4d76fcf66627cdb9dc135f02f2772e0fa3ff /sys/kern/subr_witness.c
parenta6acab26981247d2e297ed3b67e69ef5257b6ef3 (diff)
downloadFreeBSD-src-8f53106a9eee67edefaa2dba7492395b96accb2d.zip
FreeBSD-src-8f53106a9eee67edefaa2dba7492395b96accb2d.tar.gz
- Make witness_watch a 3 state value.
1 means that witness is up and running. 0 means that witness is disabled but that it can be established later again in effective way. -1 means that witness is disabled permanently - Fix a bug causing kernel to panic on witness disabling through witness_watch. lock lists queues were still full of entries and this was causing throubles with debugging stubs (like witness_thread_exit()). Reported by: kris, yongari Sponsored by: Nokia
Diffstat (limited to 'sys/kern/subr_witness.c')
-rw-r--r--sys/kern/subr_witness.c77
1 files changed, 42 insertions, 35 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 61ce035..891d606 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -464,7 +464,7 @@ static struct witness_lock_order_data *w_lofree = NULL;
static struct witness_lock_order_hash w_lohash;
static int w_max_used_index = 0;
static unsigned int w_generation = 0;
-static const char *w_notrunning = "Witness not running, witness_watch == 0\n";
+static const char *w_notrunning = "Witness not running\n";
static const char *w_stillcold = "Witness is still cold\n";
@@ -801,7 +801,7 @@ witness_init(struct lock_object *lock, const char *type)
* it to the pending_locks list. If it is not too early, then enroll
* the lock now.
*/
- if (witness_watch == 0 || panicstr != NULL ||
+ if (witness_watch < 1 || panicstr != NULL ||
(lock->lo_flags & LO_WITNESS) == 0)
lock->lo_witness = NULL;
else if (witness_cold) {
@@ -980,7 +980,7 @@ int
witness_defineorder(struct lock_object *lock1, struct lock_object *lock2)
{
- if (witness_watch == 0 || panicstr != NULL)
+ if (witness_watch < 1 || panicstr != NULL)
return (0);
/* Require locks that witness knows about. */
@@ -1019,7 +1019,7 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
struct thread *td;
int i, j;
- if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL ||
+ if (witness_cold || witness_watch < 1 || lock->lo_witness == NULL ||
panicstr != NULL)
return;
@@ -1297,7 +1297,7 @@ witness_lock(struct lock_object *lock, int flags, const char *file, int line)
struct witness *w;
struct thread *td;
- if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL ||
+ if (witness_cold || witness_watch == -1 || lock->lo_witness == NULL ||
panicstr != NULL)
return;
w = lock->lo_witness;
@@ -1356,7 +1356,7 @@ witness_upgrade(struct lock_object *lock, int flags, const char *file, int line)
struct lock_class *class;
KASSERT(witness_cold == 0, ("%s: witness_cold", __func__));
- if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL)
+ if (lock->lo_witness == NULL || witness_watch < 1 || panicstr != NULL)
return;
class = LOCK_CLASS(lock);
file = fixup_filename(file);
@@ -1388,7 +1388,7 @@ witness_downgrade(struct lock_object *lock, int flags, const char *file,
struct lock_class *class;
KASSERT(witness_cold == 0, ("%s: witness_cold", __func__));
- if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL)
+ if (lock->lo_witness == NULL || witness_watch < 1 || panicstr != NULL)
return;
class = LOCK_CLASS(lock);
file = fixup_filename(file);
@@ -1422,8 +1422,7 @@ witness_unlock(struct lock_object *lock, int flags, const char *file, int line)
register_t s;
int i, j;
- if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL ||
- panicstr != NULL)
+ if (witness_cold || lock->lo_witness == NULL || panicstr != NULL)
return;
td = curthread;
class = LOCK_CLASS(lock);
@@ -1441,12 +1440,22 @@ witness_unlock(struct lock_object *lock, int flags, const char *file, int line)
if (instance->li_lock == lock)
goto found;
}
- panic("lock (%s) %s not locked @ %s:%d", class->lc_name, lock->lo_name,
- file, line);
+
+ /*
+ * When disabling WITNESS through witness_watch we could end up in
+ * having registered locks in the locks list queue.
+ * We have to make sure we flush these queues, so just search for
+ * eventual registered locks and remove them.
+ */
+ if (witness_watch > 0)
+ panic("lock (%s) %s not locked @ %s:%d", class->lc_name,
+ lock->lo_name, file, line);
+ else
+ return;
found:
/* First, check for shared/exclusive mismatches. */
- if ((instance->li_flags & LI_EXCLUSIVE) != 0 &&
+ if ((instance->li_flags & LI_EXCLUSIVE) != 0 && witness_watch > 0 &&
(flags & LOP_EXCLUSIVE) == 0) {
printf("shared unlock of (%s) %s @ %s:%d\n", class->lc_name,
lock->lo_name, file, line);
@@ -1454,7 +1463,7 @@ found:
instance->li_file, instance->li_line);
panic("excl->ushare");
}
- if ((instance->li_flags & LI_EXCLUSIVE) == 0 &&
+ if ((instance->li_flags & LI_EXCLUSIVE) == 0 && witness_watch > 0 &&
(flags & LOP_EXCLUSIVE) != 0) {
printf("exclusive unlock of (%s) %s @ %s:%d\n", class->lc_name,
lock->lo_name, file, line);
@@ -1535,7 +1544,7 @@ witness_warn(int flags, struct lock_object *lock, const char *fmt, ...)
va_list ap;
int i, n;
- if (witness_cold || witness_watch == 0 || panicstr != NULL)
+ if (witness_cold || witness_watch < 1 || panicstr != NULL)
return (0);
n = 0;
td = curthread;
@@ -1596,7 +1605,7 @@ witness_file(struct lock_object *lock)
{
struct witness *w;
- if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL)
+ if (witness_cold || witness_watch < 1 || lock->lo_witness == NULL)
return ("?");
w = lock->lo_witness;
return (w->w_file);
@@ -1607,7 +1616,7 @@ witness_line(struct lock_object *lock)
{
struct witness *w;
- if (witness_cold || witness_watch == 0 || lock->lo_witness == NULL)
+ if (witness_cold || witness_watch < 1 || lock->lo_witness == NULL)
return (0);
w = lock->lo_witness;
return (w->w_line);
@@ -1621,7 +1630,7 @@ enroll(const char *description, struct lock_class *lock_class)
MPASS(description != NULL);
- if (witness_watch == 0 || panicstr != NULL)
+ if (witness_watch < 1 || panicstr != NULL)
return (NULL);
if ((lock_class->lc_flags & LC_SPINLOCK)) {
if (witness_skipspin)
@@ -1770,7 +1779,7 @@ adopt(struct witness *parent, struct witness *child)
i, j, w_rmatrix[i][j]);
kdb_backtrace();
printf("Witness disabled.\n");
- witness_watch = 0;
+ witness_watch = -1;
}
if ((w_rmatrix[j][i] & WITNESS_ANCESTOR_MASK) &&
(w_rmatrix[j][i] & WITNESS_DESCENDANT_MASK)) {
@@ -1779,7 +1788,7 @@ adopt(struct witness *parent, struct witness *child)
j, i, w_rmatrix[j][i]);
kdb_backtrace();
printf("Witness disabled.\n");
- witness_watch = 0;
+ witness_watch = -1;
}
}
}
@@ -1831,7 +1840,7 @@ _isitmyx(struct witness *w1, struct witness *w2, int rmask, const char *fname)
i2, i1, r2);
kdb_backtrace();
printf("Witness disabled.\n");
- witness_watch = 0;
+ witness_watch = -1;
}
return (r1 & rmask);
}
@@ -1888,12 +1897,12 @@ witness_get(void)
if (witness_cold == 0)
mtx_assert(&w_mtx, MA_OWNED);
- if (witness_watch == 0) {
+ if (witness_watch < 1) {
mtx_unlock_spin(&w_mtx);
return (NULL);
}
if (STAILQ_EMPTY(&w_free)) {
- witness_watch = 0;
+ witness_watch = -1;
mtx_unlock_spin(&w_mtx);
printf("WITNESS: unable to allocate a new witness object\n");
return (NULL);
@@ -1924,12 +1933,12 @@ witness_lock_list_get(void)
{
struct lock_list_entry *lle;
- if (witness_watch == 0)
+ if (witness_watch == -1)
return (NULL);
mtx_lock_spin(&w_mtx);
lle = w_lock_list_free;
if (lle == NULL) {
- witness_watch = 0;
+ witness_watch = -1;
mtx_unlock_spin(&w_mtx);
printf("%s: witness exhausted\n", __func__);
return (NULL);
@@ -2046,7 +2055,7 @@ witness_save(struct lock_object *lock, const char **filep, int *linep)
struct lock_class *class;
KASSERT(witness_cold == 0, ("%s: witness_cold", __func__));
- if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL)
+ if (lock->lo_witness == NULL || witness_watch < 1 || panicstr != NULL)
return;
class = LOCK_CLASS(lock);
if (class->lc_flags & LC_SLEEPLOCK)
@@ -2072,7 +2081,7 @@ witness_restore(struct lock_object *lock, const char *file, int line)
struct lock_class *class;
KASSERT(witness_cold == 0, ("%s: witness_cold", __func__));
- if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL)
+ if (lock->lo_witness == NULL || witness_watch < 1 || panicstr != NULL)
return;
class = LOCK_CLASS(lock);
if (class->lc_flags & LC_SLEEPLOCK)
@@ -2099,7 +2108,7 @@ witness_assert(struct lock_object *lock, int flags, const char *file, int line)
struct lock_instance *instance;
struct lock_class *class;
- if (lock->lo_witness == NULL || witness_watch == 0 || panicstr != NULL)
+ if (lock->lo_witness == NULL || witness_watch < 1 || panicstr != NULL)
return;
class = LOCK_CLASS(lock);
if ((class->lc_flags & LC_SLEEPLOCK) != 0)
@@ -2163,7 +2172,7 @@ witness_ddb_list(struct thread *td)
KASSERT(witness_cold == 0, ("%s: witness_cold", __func__));
KASSERT(kdb_active, ("%s: not in the debugger", __func__));
- if (witness_watch == 0)
+ if (witness_watch < 1)
return;
witness_list_locks(&td->td_sleeplocks);
@@ -2239,7 +2248,7 @@ sysctl_debug_witness_badstacks(SYSCTL_HANDLER_ARGS)
tmp_data2 = NULL;
tmp_w1 = NULL;
tmp_w2 = NULL;
- if (witness_watch == 0) {
+ if (witness_watch < 1) {
error = SYSCTL_OUT(req, w_notrunning, sizeof(w_notrunning));
return (error);
}
@@ -2391,7 +2400,7 @@ sysctl_debug_witness_fullgraph(SYSCTL_HANDLER_ARGS)
struct sbuf *sb;
int error;
- if (witness_watch == 0) {
+ if (witness_watch < 1) {
error = SYSCTL_OUT(req, w_notrunning, sizeof(w_notrunning));
return (error);
}
@@ -2436,15 +2445,13 @@ sysctl_debug_witness_watch(SYSCTL_HANDLER_ARGS)
{
int error, value;
- value = witness_watch;
error = sysctl_handle_int(oidp, &value, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
- if (value == witness_watch)
- return (0);
- if (value != 0)
+ if (value > 1 || value < -1 ||
+ (witness_watch == -1 && value != witness_watch))
return (EINVAL);
- witness_watch = 0;
+ witness_watch = value;
return (0);
}
OpenPOWER on IntegriCloud