From patchwork Fri May 1 21:15:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Aquini X-Patchwork-Id: 11523285 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 33D5E17EF for ; Fri, 1 May 2020 21:15:59 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id EBFD82166E for ; Fri, 1 May 2020 21:15:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Y6yjYEmt" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EBFD82166E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 16A078E0006; Fri, 1 May 2020 17:15:58 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 11BEA8E0001; Fri, 1 May 2020 17:15:58 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 030B78E0006; Fri, 1 May 2020 17:15:57 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0038.hostedemail.com [216.40.44.38]) by kanga.kvack.org (Postfix) with ESMTP id DBFB18E0001 for ; Fri, 1 May 2020 17:15:57 -0400 (EDT) Received: from smtpin12.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id 9441B8249980 for ; Fri, 1 May 2020 21:15:57 +0000 (UTC) X-FDA: 76769407554.12.shame15_6e315c007135a X-Spam-Summary: 1,0,0,,d41d8cd98f00b204,aquini@redhat.com,,RULES_HIT:30029:30054:30062,0,RBL:205.139.110.120:@redhat.com:.lbl8.mailshell.net-62.18.0.100 66.10.201.10,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:ft,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:25,LUA_SUMMARY:none X-HE-Tag: shame15_6e315c007135a X-Filterd-Recvd-Size: 7602 Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by imf48.hostedemail.com (Postfix) with ESMTP for ; Fri, 1 May 2020 21:15:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1588367756; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=TwVeJRda5LXDJE4kjcBYfmqq13SV7B4dqiJ51LZW9+E=; b=Y6yjYEmtcMsHp578vcOYX3jHs/KBzbEbDyxtc3UCyjXpeMH5a7qa0QazyJaAz9hG3rqI6k kXWaXhAARLkt8bSCG6fjgEEPr3Xx5bH5xGbr5xIHWgewvXSqBhooNo8yGZ8fRg+HEQnOX/ MjA0QaTraZ6biy+9pycX6YzEAauVmHM= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-370-hRavvBV7MceEKvU9Y_G19A-1; Fri, 01 May 2020 17:15:54 -0400 X-MC-Unique: hRavvBV7MceEKvU9Y_G19A-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7011B100CCC0; Fri, 1 May 2020 21:15:53 +0000 (UTC) Received: from optiplex-lnx.redhat.com (unknown [10.3.128.26]) by smtp.corp.redhat.com (Postfix) with ESMTP id B966927072; Fri, 1 May 2020 21:15:50 +0000 (UTC) From: Rafael Aquini 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 Message-Id: <20200501211540.71216-1-aquini@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: 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 --- 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 : 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,