From: Rafael Aquini <aquini@redhat.com>
To: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org, akpm@linux-foundation.org,
iamjoonsoo.kim@lge.com, rientjes@google.com, penberg@kernel.org,
cl@linux.com
Subject: [PATCH] mm: slub: add panic_on_error to the debug facilities
Date: Fri, 1 May 2020 17:15:40 -0400 [thread overview]
Message-ID: <20200501211540.71216-1-aquini@redhat.com> (raw)
Sometimes it is desirable to override SLUB's debug facilities
default behavior upon stumbling on a cache or object error
and just stop the execution in order to grab a coredump, at
the error-spotting time, instead of trying to fix the issue
and report in an attempt to keep the system rolling.
This patch introduces a new debug flag SLAB_PANIC_ON_ERROR,
along with its related SLUB-machinery, in order to extend
current slub_debug facilites and provide the aforementioned
behavior override.
Signed-off-by: Rafael Aquini <aquini@redhat.com>
---
Documentation/vm/slub.rst | 2 ++
include/linux/slab.h | 2 ++
mm/slab.h | 3 ++-
mm/slub.c | 44 ++++++++++++++++++++++++++++++---------
4 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/Documentation/vm/slub.rst b/Documentation/vm/slub.rst
index 933ada4368ff..51b18c28ec78 100644
--- a/Documentation/vm/slub.rst
+++ b/Documentation/vm/slub.rst
@@ -54,6 +54,8 @@ Possible debug options are::
caused higher minimum slab orders
- Switch all debugging off (useful if the kernel is
configured with CONFIG_SLUB_DEBUG_ON)
+ C Toggle panic on error (crash) to allow for post-mortem
+ analysis of a coredump taken at the error-spotting time
F.e. in order to boot just with sanity checks and red zoning one would specify::
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 6d454886bcaf..e3496ad7859f 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -25,6 +25,8 @@
*/
/* DEBUG: Perform (expensive) checks on alloc/free */
#define SLAB_CONSISTENCY_CHECKS ((slab_flags_t __force)0x00000100U)
+/* DEBUG: panic on error (forced crash) */
+#define SLAB_PANIC_ON_ERROR ((slab_flags_t __force)0x00000200U)
/* DEBUG: Red zone objs in a cache */
#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400U)
/* DEBUG: Poison objects */
diff --git a/mm/slab.h b/mm/slab.h
index 207c83ef6e06..27116f8683a1 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -198,7 +198,8 @@ static inline slab_flags_t kmem_cache_flags(unsigned int object_size,
#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER)
#elif defined(CONFIG_SLUB_DEBUG)
#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
- SLAB_TRACE | SLAB_CONSISTENCY_CHECKS)
+ SLAB_TRACE | SLAB_CONSISTENCY_CHECKS | \
+ SLAB_PANIC_ON_ERROR)
#else
#define SLAB_DEBUG_FLAGS (0)
#endif
diff --git a/mm/slub.c b/mm/slub.c
index 9bf44955c4f1..8b4fc002b865 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -700,8 +700,6 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
/* Beginning of the filler is the free pointer */
print_section(KERN_ERR, "Padding ", p + off,
size_from_object(s) - off);
-
- dump_stack();
}
void object_err(struct kmem_cache *s, struct page *page,
@@ -709,6 +707,9 @@ void object_err(struct kmem_cache *s, struct page *page,
{
slab_bug(s, "%s", reason);
print_trailer(s, page, object);
+ if (unlikely(s->flags & SLAB_PANIC_ON_ERROR))
+ panic("BUG: %s: %s", s->name, reason);
+ dump_stack();
}
static __printf(3, 4) void slab_err(struct kmem_cache *s, struct page *page,
@@ -722,6 +723,8 @@ static __printf(3, 4) void slab_err(struct kmem_cache *s, struct page *page,
va_end(args);
slab_bug(s, "%s", buf);
print_page_info(page);
+ if (unlikely(s->flags & SLAB_PANIC_ON_ERROR))
+ panic("BUG: %s: %s", s->name, buf);
dump_stack();
}
@@ -771,7 +774,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
fault, end - 1, fault - addr,
fault[0], value);
print_trailer(s, page, object);
-
+ dump_stack();
restore_bytes(s, what, value, fault, end);
return 0;
}
@@ -1173,13 +1176,14 @@ static inline int free_consistency_checks(struct kmem_cache *s,
if (!PageSlab(page)) {
slab_err(s, page, "Attempt to free object(0x%p) outside of slab",
object);
- } else if (!page->slab_cache) {
- pr_err("SLUB <none>: no slab for object 0x%p.\n",
- object);
- dump_stack();
- } else
- object_err(s, page, object,
- "page slab pointer corrupt.");
+ } else {
+ char reason[80];
+
+ snprintf(reason, sizeof(reason),
+ "page slab pointer corruption: 0x%p (0x%p expected)",
+ page->slab_cache, s);
+ object_err(s, page, object, reason);
+ }
return 0;
}
return 1;
@@ -1291,6 +1295,9 @@ static int __init setup_slub_debug(char *str)
*/
disable_higher_order_debug = 1;
break;
+ case 'c':
+ slub_debug |= SLAB_PANIC_ON_ERROR;
+ break;
default:
pr_err("slub_debug option '%c' unknown. skipped\n",
*str);
@@ -5312,6 +5319,22 @@ static ssize_t free_calls_show(struct kmem_cache *s, char *buf)
return list_locations(s, buf, TRACK_FREE);
}
SLAB_ATTR_RO(free_calls);
+
+static ssize_t
+panic_on_error_show(struct kmem_cache *s, char *buf)
+{
+ return sprintf(buf, "%d\n", !!(s->flags & SLAB_PANIC_ON_ERROR));
+}
+
+static ssize_t
+panic_on_error_store(struct kmem_cache *s, const char *buf, size_t length)
+{
+ s->flags &= ~SLAB_PANIC_ON_ERROR;
+ if (buf[0] == '1')
+ s->flags |= SLAB_PANIC_ON_ERROR;
+ return length;
+}
+SLAB_ATTR(panic_on_error);
#endif /* CONFIG_SLUB_DEBUG */
#ifdef CONFIG_FAILSLAB
@@ -5486,6 +5509,7 @@ static struct attribute *slab_attrs[] = {
&validate_attr.attr,
&alloc_calls_attr.attr,
&free_calls_attr.attr,
+ &panic_on_error_attr.attr,
#endif
#ifdef CONFIG_ZONE_DMA
&cache_dma_attr.attr,
--
2.25.4
next reply other threads:[~2020-05-01 21:15 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-01 21:15 Rafael Aquini [this message]
2020-05-01 21:29 ` [PATCH] mm: slub: add panic_on_error to the debug facilities Qian Cai
2020-05-01 21:54 ` Rafael Aquini
2020-05-01 22:00 ` Qian Cai
2020-05-01 23:17 ` Qian Cai
2020-05-04 2:36 ` Rafael Aquini
2020-05-01 21:37 ` Andrew Morton
2020-05-01 21:41 ` Rafael Aquini
2020-05-02 23:16 ` Christopher Lameter
2020-05-04 2:51 ` Rafael Aquini
2020-05-08 3:06 ` Christopher Lameter
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=20200501211540.71216-1-aquini@redhat.com \
--to=aquini@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=cl@linux.com \
--cc=iamjoonsoo.kim@lge.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=penberg@kernel.org \
--cc=rientjes@google.com \
/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.