From: Dmitry Safonov <dima@arista.com>
To: linux-kernel@vger.kernel.org
Cc: 0x7f454c46@gmail.com, Dmitry Safonov <dima@arista.com>,
kernel test robot <rong.a.chen@intel.com>,
Andrew Morton <akpm@linux-foundation.org>,
Ingo Molnar <mingo@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>,
Thomas Gleixner <tglx@linutronix.de>,
Waiman Long <longman@redhat.com>
Subject: [PATCH 2/2] debugobjects: Print warnings outside bucket lock
Date: Thu, 13 Dec 2018 04:34:47 +0000 [thread overview]
Message-ID: <20181213043447.23006-2-dima@arista.com> (raw)
In-Reply-To: <20181213043447.23006-1-dima@arista.com>
Whenever debugobjects finds invalid pattern during life time of a kernel
object such as:
- Activation of uninitialized objects
- Initialization of active objects
- Usage of freed/destroyed objects
it prints a warning and tries to make fixup over an object.
Unfortunately, it becomes error-prone to use WARN() or printing under
debugobjects bucket lock: printk() may defer work to workqueue, and
realization of workqueues uses debugobjects. Further, console drivers
use page allocator, potentially vmalloc() or slub/slab. Which reasonably
makes lockdep to go nuts as there are debug_check_no_obj_freed() checks
in allocators.
Move printings out of debugobjets bucket lock to address the potential
lockups.
Link: lkml.kernel.org/r/20181211091154.GL23332@shao2-debian
Reported-by: kernel test robot <rong.a.chen@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Waiman Long <longman@redhat.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
---
lib/debugobjects.c | 89 ++++++++++++++++++++++++----------------------
1 file changed, 47 insertions(+), 42 deletions(-)
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 98968219405b..0c92e46cb588 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -313,7 +313,7 @@ static struct debug_bucket *get_bucket(unsigned long addr)
return &obj_hash[hash];
}
-static void debug_print_object(struct debug_obj *obj, char *msg)
+static void __debug_print_object(struct debug_obj *obj, char *msg)
{
struct debug_obj_descr *descr = obj->descr;
static int limit;
@@ -330,6 +330,14 @@ static void debug_print_object(struct debug_obj *obj, char *msg)
debug_objects_warnings++;
}
+#define debug_print_object(obj, msg, lock, flags) \
+ do { \
+ struct debug_obj tmp = *obj; \
+ \
+ raw_spin_unlock_irqrestore(lock, flags); \
+ __debug_print_object(&tmp, msg); \
+ } while(0)
+
/*
* Try to repair the damage, so we have a better chance to get useful
* debug output.
@@ -403,15 +411,14 @@ __debug_object_init(void *addr, struct debug_obj_descr *descr)
break;
case ODEBUG_STATE_ACTIVE:
- debug_print_object(obj, "init");
state = obj->state;
- raw_spin_unlock_irqrestore(&db->lock, flags);
+ debug_print_object(obj, "init", &db->lock, flags);
debug_object_fixup(descr->fixup_init, addr, state);
return allocated;
case ODEBUG_STATE_DESTROYED:
- debug_print_object(obj, "init");
- break;
+ debug_print_object(obj, "init", &db->lock, flags);
+ return allocated;
default:
break;
}
@@ -485,16 +492,14 @@ int debug_object_activate(void *addr, struct debug_obj_descr *descr)
break;
case ODEBUG_STATE_ACTIVE:
- debug_print_object(obj, "activate");
state = obj->state;
- raw_spin_unlock_irqrestore(&db->lock, flags);
+ debug_print_object(obj, "activate", &db->lock, flags);
ret = debug_object_fixup(descr->fixup_activate, addr, state);
return ret ? 0 : -EINVAL;
case ODEBUG_STATE_DESTROYED:
- debug_print_object(obj, "activate");
- ret = -EINVAL;
- break;
+ debug_print_object(obj, "activate", &db->lock, flags);
+ return -EINVAL;
default:
ret = 0;
break;
@@ -516,7 +521,7 @@ int debug_object_activate(void *addr, struct debug_obj_descr *descr)
debug_object_init(addr, descr);
debug_object_activate(addr, descr);
} else {
- debug_print_object(&o, "activate");
+ __debug_print_object(&o, "activate");
ret = debug_object_fixup(descr->fixup_activate, addr,
ODEBUG_STATE_NOTAVAILABLE);
return ret ? 0 : -EINVAL;
@@ -549,27 +554,27 @@ void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
case ODEBUG_STATE_INIT:
case ODEBUG_STATE_INACTIVE:
case ODEBUG_STATE_ACTIVE:
- if (!obj->astate)
+ if (!obj->astate) {
obj->state = ODEBUG_STATE_INACTIVE;
- else
- debug_print_object(obj, "deactivate");
- break;
-
+ break;
+ }
+ /* fallthrough */
case ODEBUG_STATE_DESTROYED:
- debug_print_object(obj, "deactivate");
- break;
+ debug_print_object(obj, "deactivate", &db->lock, flags);
+ return;
default:
break;
}
- } else {
+ }
+ raw_spin_unlock_irqrestore(&db->lock, flags);
+
+ if (!obj) {
struct debug_obj o = { .object = addr,
.state = ODEBUG_STATE_NOTAVAILABLE,
.descr = descr };
- debug_print_object(&o, "deactivate");
+ __debug_print_object(&o, "deactivate");
}
-
- raw_spin_unlock_irqrestore(&db->lock, flags);
}
EXPORT_SYMBOL_GPL(debug_object_deactivate);
@@ -603,15 +608,14 @@ void debug_object_destroy(void *addr, struct debug_obj_descr *descr)
obj->state = ODEBUG_STATE_DESTROYED;
break;
case ODEBUG_STATE_ACTIVE:
- debug_print_object(obj, "destroy");
state = obj->state;
- raw_spin_unlock_irqrestore(&db->lock, flags);
+ debug_print_object(obj, "destroy", &db->lock, flags);
debug_object_fixup(descr->fixup_destroy, addr, state);
return;
case ODEBUG_STATE_DESTROYED:
- debug_print_object(obj, "destroy");
- break;
+ debug_print_object(obj, "destroy", &db->lock, flags);
+ return;
default:
break;
}
@@ -645,9 +649,8 @@ void debug_object_free(void *addr, struct debug_obj_descr *descr)
switch (obj->state) {
case ODEBUG_STATE_ACTIVE:
- debug_print_object(obj, "free");
state = obj->state;
- raw_spin_unlock_irqrestore(&db->lock, flags);
+ debug_print_object(obj, "free", &db->lock, flags);
debug_object_fixup(descr->fixup_free, addr, state);
return;
default:
@@ -695,7 +698,7 @@ void debug_object_assert_init(void *addr, struct debug_obj_descr *descr)
/* Track this static object */
debug_object_init(addr, descr);
} else {
- debug_print_object(&o, "assert_init");
+ __debug_print_object(&o, "assert_init");
debug_object_fixup(descr->fixup_assert_init, addr,
ODEBUG_STATE_NOTAVAILABLE);
}
@@ -732,25 +735,27 @@ debug_object_active_state(void *addr, struct debug_obj_descr *descr,
if (obj) {
switch (obj->state) {
case ODEBUG_STATE_ACTIVE:
- if (obj->astate == expect)
+ if (obj->astate == expect) {
obj->astate = next;
- else
- debug_print_object(obj, "active_state");
- break;
-
+ raw_spin_unlock_irqrestore(&db->lock, flags);
+ return;
+ }
+ /* fallthrough */
default:
- debug_print_object(obj, "active_state");
- break;
+ debug_print_object(obj, "active_state",
+ &db->lock, flags);
+ return;
}
- } else {
+ }
+ raw_spin_unlock_irqrestore(&db->lock, flags);
+
+ if (!obj) {
struct debug_obj o = { .object = addr,
.state = ODEBUG_STATE_NOTAVAILABLE,
.descr = descr };
- debug_print_object(&o, "active_state");
+ __debug_print_object(&o, "active_state");
}
-
- raw_spin_unlock_irqrestore(&db->lock, flags);
}
EXPORT_SYMBOL_GPL(debug_object_active_state);
@@ -786,10 +791,10 @@ static void __debug_check_no_obj_freed(const void *address, unsigned long size)
switch (obj->state) {
case ODEBUG_STATE_ACTIVE:
- debug_print_object(obj, "free");
descr = obj->descr;
state = obj->state;
- raw_spin_unlock_irqrestore(&db->lock, flags);
+ debug_print_object(obj, "free",
+ &db->lock, flags);
debug_object_fixup(descr->fixup_free,
(void *) oaddr, state);
goto repeat;
--
2.20.0
next prev parent reply other threads:[~2018-12-13 4:35 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-13 4:34 [PATCH 1/2] debugobjects: Warn wrong annotation outside bucket lock Dmitry Safonov
2018-12-13 4:34 ` Dmitry Safonov [this message]
2018-12-13 22:04 ` [PATCH 2/2] debugobjects: Print warnings " Waiman Long
2018-12-13 9:28 ` [PATCH 1/2] debugobjects: Warn wrong annotation " Sergey Senozhatsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181213043447.23006-2-dima@arista.com \
--to=dima@arista.com \
--cc=0x7f454c46@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=longman@redhat.com \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=rong.a.chen@intel.com \
--cc=sergey.senozhatsky.work@gmail.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.