From patchwork Sun May 10 20:24:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287351 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=r+CmPx94; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Knmx1HZJ; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwXr5ZT0z9sSt for ; Mon, 11 May 2020 06:25:00 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=XUQY01ZiH4gJzLSY+DwvlRdEqTNKsop2eaE8g+nh1Ts=; b=r+CmPx947n6lg8 KX/5EDQ+8cuNYiF7C2pOXXHUDwxEKNFsYpUJ5i0QyX+dAWYzxR7RhFE5HcsJmi0ZdSn1FAQyYODjo 5iol5+pWoS4qEnWIDZzUg5toE6ek+0At4nwPv5qiWsfCamXhMo+Gx4AX9z7Rjvk268dvUx2TfBsU3 24ZDhmNKbxNB2S1Anoth3VnyOcitX6zuM2ys3P5JEYrC+0sJHvUMVfvgJMkis/pKosWuLJS+a31qX WsgimXehnMazH5DU11ilgka3uJxj/oCnNdxa2TaIXL708rbetgxHUvU/35X31fymSxtssOFdfafff Sh50O+MGmInoZfowPuiA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVD-0002Rt-3P; Sun, 10 May 2020 20:24:47 +0000 Received: from mail-pj1-x1041.google.com ([2607:f8b0:4864:20::1041]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsV9-0002QA-Uj for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:45 +0000 Received: by mail-pj1-x1041.google.com with SMTP id fu13so6723714pjb.5 for ; Sun, 10 May 2020 13:24:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=BH7oPYzXzVGddb2eusJn7dvCiiIlEUY0aB5rJA7D8Lo=; b=Knmx1HZJZicNN2kyPSHXezy3IlidaxBgWVCKCEjmfFjqIIogaiilJAI6UQevUw+SzJ uxC1dHSDC2qeSRqPIKDp1GL2b47FC87gSdWL1tQCvqNJT+ecQn4XXHgGL5d4Ik6FXWoG Joq2ga7Uv9c5LsCL30Z7U4ze5fpY94V4y9JSI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=BH7oPYzXzVGddb2eusJn7dvCiiIlEUY0aB5rJA7D8Lo=; b=klYshOefYKZWESMDrOJPqsHZlvC+vSfdUzpuF0hr1jlepBbBdYvMCRjdh/rg9b8n22 NKe/zr4JsGLXR/S6eI+6YTus4Y7h62+7Cp5y7vNLbRrD2BrMICxUqBY0j7F/zCoUTf1M JBmFuWQmuz6lcugEVGpsNgAeCkYLQH/1I3EGnEa+YH2p/LHO0yo9sqEWvPcIZjFd+PAt eRYyR/VaNaG4y2FHuhVuTRwjSLiadDi3+cKZQj7sewzziWovGqp3FklpkE8e9loLoVWQ f5kYl2tUTbeHe0vhDDD0hfYK9u9bj88mgXd8ZXjAN+enkkxYjy3p128Se0ZuwgIQgWFk qgfA== X-Gm-Message-State: AGi0PuZ3TXdCGjLz7DxQwUrjA2POVe5ggVNdFqgCHwc06u1ng4J7ZSGr Wm90MzH360Qebq2DNtYXnM+sRA== X-Google-Smtp-Source: APiQypLOl1TXjmfLr/xQcK1xr2OabtzKZy6naN7IKAuzLaAUHxg4zhucy0rFHWqKNS4VPSsObsMKkw== X-Received: by 2002:a17:902:c194:: with SMTP id d20mr12212723pld.256.1589142282837; Sun, 10 May 2020 13:24:42 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id h12sm6246248pgi.5.2020.05.10.13.24.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:41 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 01/18] pstore/ram: Move dump_oops to end of module_param list Date: Sun, 10 May 2020 13:24:19 -0700 Message-Id: <20200510202436.63222-2-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132444_017308_F74296A6 X-CRM114-Status: GOOD ( 11.62 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1041 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org When reading "modinfo" details, dump_oops was before max_reason, which seems odd given dump_oops is now considered deprecated. Move it to the very end instead. Signed-off-by: Kees Cook --- fs/pstore/ram.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 198d04cceb3e..7f956053f4e5 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -57,11 +57,6 @@ module_param(mem_type, uint, 0400); MODULE_PARM_DESC(mem_type, "set to 1 to try to use unbuffered memory (default 0)"); -static int ramoops_dump_oops = -1; -module_param_named(dump_oops, ramoops_dump_oops, int, 0400); -MODULE_PARM_DESC(dump_oops, - "set to 1 to dump oopses & panics, 0 to only dump panics (deprecated: use max_reason instead)"); - static int ramoops_max_reason = KMSG_DUMP_OOPS; module_param_named(max_reason, ramoops_max_reason, int, 0400); MODULE_PARM_DESC(max_reason, @@ -74,6 +69,11 @@ MODULE_PARM_DESC(ramoops_ecc, "ECC buffer size in bytes (1 is a special value, means 16 " "bytes ECC)"); +static int ramoops_dump_oops = -1; +module_param_named(dump_oops, ramoops_dump_oops, int, 0400); +MODULE_PARM_DESC(dump_oops, + "(deprecated: use max_reason instead) set to 1 to dump oopses & panics, 0 to only dump panics"); + struct ramoops_context { struct persistent_ram_zone **dprzs; /* Oops dump zones */ struct persistent_ram_zone *cprz; /* Console zone */ From patchwork Sun May 10 20:24:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287352 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=tVulOBYn; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Vu8u0y3g; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwY24rrgz9sSd for ; Mon, 11 May 2020 06:25:10 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=C3kiE2+4AVCOi3ZPLMTXEGnf9JMiNEWyv7VVqRQt8r0=; b=tVulOBYntXt0Ry ioTb+UYj7uhQPmwHUJ3aYlx55hIDvfgTZd714MHqW1OoZVf5HT6Al/k77lIlL+bb6o8eha7Qgbgdq ZPNoFZWE9seKZ7+zhyVxseDX0KL/W3I1WfS33uJF6NJw3MH4/wmnVsPO7+HtQqeiT49JDys86S63d UXLtIbBiAsyEVVBrhRz40WOv7fCrKOiCHyHDA5AXuHJqAxMZQEXqXLNPIRLVMUb1Vm/vZBZmTQlwC ZOsDjRpFx3I9JzyZrmLFD1CAjzv6bri7VoFHJ04sGIPacGfmFR5X93hK2HyHNspkIcWHMKCKSIGki i9WRV0L1STsgxx+0ypjw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVV-0002lG-Qz; Sun, 10 May 2020 20:25:05 +0000 Received: from mail-pl1-x643.google.com ([2607:f8b0:4864:20::643]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVA-0002QC-8c for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:45 +0000 Received: by mail-pl1-x643.google.com with SMTP id k19so3018955pll.9 for ; Sun, 10 May 2020 13:24:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=a6bXV7bt3FJwO+6h7hS9wdbWbj+cKT2R8klgQdvy5V4=; b=Vu8u0y3g/EsMOqGf92rFyvezCvoeKBq6M4OIMjHDXZQuVY5ATlo2kh28eB6tVdSW2u HeG9wciptveXO5MHRNtJSHj4Ogkp9s7OktTbZhn/Vvp42lUU1KrIa9rIQ0bGpNOCOKeO EC9TBt8Z9Lh9M/kLz05YI4DHvIcGjrjtQpGgY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=a6bXV7bt3FJwO+6h7hS9wdbWbj+cKT2R8klgQdvy5V4=; b=scamXIdJqtt2MMUTEwFItXLKmNn+h2LPPKO31mAp2LgbZwgDb33CUYpVR6IoXr1z/L apblwthpV3/O8+6aFGUw5sS84tzZWURGSKRuk1Nfdl4wQclh5t98V1+rli7htbn+NvRR M9kd/+e8Ups/mnCSwZDfZvKb8PLz34Lh51zUeUUqdzdHDZAYO58+FuxVjg9Yy3nLhXe7 uHVorAt2VHGw/LDYu40YNfYtm5GB1lgAS2RKXa1fMF/l6PsmtQuXg3yloT8bmGZGXPd2 j2XraNRQIyMC0GaSeOLqSFs42a9C6wTk3MusoPstoi8pVsYghW1kJ+K2T2dzsNoPUTtd 484A== X-Gm-Message-State: AGi0PubzktYvy6T8n5XMEhf1d4ImU+t98x87qf6EUzR4M6OaL976G0mL NT7IFlccXOUfUKoVIYQeFtk1/w== X-Google-Smtp-Source: APiQypL4ftL5PXuI6WbPG1D/aF+OyzdmBrwXgZqbvh107ELfxtW4oGZxzd33g34wmpY9M28zk4hvsQ== X-Received: by 2002:a17:90b:374e:: with SMTP id ne14mr17664828pjb.145.1589142283365; Sun, 10 May 2020 13:24:43 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id y6sm7866882pjw.15.2020.05.10.13.24.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:41 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 02/18] pstore/platform: Switch pstore_info::name to const Date: Sun, 10 May 2020 13:24:20 -0700 Message-Id: <20200510202436.63222-3-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132444_300778_35AC4606 X-CRM114-Status: GOOD ( 13.34 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:643 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org In order to more cleanly pass around backend names, make the "name" member const. This means the module param needs to be dynamic (technically, it was before, so this actually cleans up a minor memory leak if a backend was specified and then gets unloaded.) Signed-off-by: Kees Cook --- fs/pstore/platform.c | 3 ++- include/linux/pstore.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index b882919b8784..e7bf22f01928 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -626,7 +626,7 @@ int pstore_register(struct pstore_info *psi) * Update the module parameter backend, so it is visible * through /sys/module/pstore/parameters/backend */ - backend = psi->name; + backend = kstrdup(psi->name, GFP_KERNEL); pr_info("Registered %s as persistent store backend\n", psi->name); @@ -669,6 +669,7 @@ void pstore_unregister(struct pstore_info *psi) free_buf_for_compression(); psinfo = NULL; + kfree(backend); backend = NULL; mutex_unlock(&psinfo_lock); } diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 16a1fdafc167..eb93a54cff31 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -176,7 +176,7 @@ struct pstore_record { */ struct pstore_info { struct module *owner; - char *name; + const char *name; struct semaphore buf_lock; char *buf; From patchwork Sun May 10 20:24:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287353 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=PdkUdl8e; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=oUPw6/i/; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwYh6xVlz9sT0 for ; Mon, 11 May 2020 06:25:44 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=cvAeTaIsijMQHv0UqQ7Lua20/DPVKHklnMBgOzo2qaA=; b=PdkUdl8eEnbQqd vYQ+S05Q4fqbXGGAVDw2DKustNC4AtmzdxgvSZNSyIeVKDedwtRZYxXNl/Q5zYbMqFcryGZAc0AKm 5xefB9UZ6NNBdjdwLg4M5MYemKVzRtrQ6Gf8N+G9tf3/X4kUeBBeLxMx8dH4/pg9z7Qu74nUIWOkO Al3cMFmghwL4t+PmoiTVOO6/qLPZR4Hs2QgjIpX2qXIISE1GSZ9MFvrlpbAq/JmU7qe5eiUUSGxQH HDUYwlPhAlufU25H6NrZ+rP/y18qrVyhOpxgJn/RzB7DPBzyUZkA1hlb8f56N1mH7nVKPBqTlC1qg zNcvOuxf9qtrWUzH79rw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVt-0005NK-Jg; Sun, 10 May 2020 20:25:29 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVA-0002Qi-NA for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:46 +0000 Received: by mail-pl1-x644.google.com with SMTP id s20so3026570plp.6 for ; Sun, 10 May 2020 13:24:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vvhNGN1Tx7s0Ij5sTylqbBedyOwoifzYhuoj8ucg/Ng=; b=oUPw6/i/iSWSLQ8qEZxi/iwEj2X96+Bexnha6PPFG6//+4Z23RGHmmMvuexJ/VamdF F19pZKmlabTzyoj+NUGRdBPzFwPSXEqx8bNuJLoNAp7GF8uWqV30AiPPU5cGHI9R0Wqb Pny9vkYjK7rac58pWP4vQRqVTW6M4MKmJ4k2M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vvhNGN1Tx7s0Ij5sTylqbBedyOwoifzYhuoj8ucg/Ng=; b=jS0cP77Cu5ruhJSfYF8e6u0nmIzwQIgb7n7qdgv/zF/kJuGAqgFQ37kG1RTBYIgPb8 TBNJT1SHMJeb1d8eaXGy1rOld6GvPo1Mu8+gdas+qTQ/uzQtbdx+nN+aSwXAnIl9T0w8 cZBTFxuGXkKwBjjQb1nxWw9kMu/fwVeY5nDwxCxGHxWV06jfEY+m3QXRawvxqK1IzfCt Ibf/x+o924hUoZupruO5anOolr746bCnBlXShrN/HATOTYCtXFC1RvJRRAFNAZ5wprFt pcTBY0XWZ81DPXzv43N6LNPCSMH1UVpBqe1ZRjlomHeD4RRbK1X3UguLhoW/Sm3H4y4/ w6vw== X-Gm-Message-State: AGi0PuaoB4LymMWeOyy2kYklZmKl4b3O2xR4fdrEQn4D2vakHbTSsuq0 huMH2rkMA8BnoZ8VY0+uALQThA== X-Google-Smtp-Source: APiQypI0peMuCdpjAI6Jjbk4+g7PSZ9VEw2TUInRV5/MACLXB5MTMLkkWXhKvUdHeRCsFkKmImLJjQ== X-Received: by 2002:a17:90a:22e8:: with SMTP id s95mr18281973pjc.219.1589142284157; Sun, 10 May 2020 13:24:44 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id 128sm7284042pfy.5.2020.05.10.13.24.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:41 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 03/18] pstore/platform: Move module params after declarations Date: Sun, 10 May 2020 13:24:21 -0700 Message-Id: <20200510202436.63222-4-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132444_749744_EF9C6B42 X-CRM114-Status: UNSURE ( 9.59 ) X-CRM114-Notice: Please train this message. X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org It is easier to see how module params are used if they're near the variables they use. Signed-off-by: Kees Cook --- fs/pstore/platform.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index e7bf22f01928..bf7fa7b278bd 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -77,12 +77,17 @@ static DEFINE_MUTEX(psinfo_lock); struct pstore_info *psinfo; static char *backend; +module_param(backend, charp, 0444); +MODULE_PARM_DESC(backend, "specific backend to use"); + static char *compress = #ifdef CONFIG_PSTORE_COMPRESS_DEFAULT CONFIG_PSTORE_COMPRESS_DEFAULT; #else NULL; #endif +module_param(compress, charp, 0444); +MODULE_PARM_DESC(compress, "compression to use"); /* Compression parameters */ static struct crypto_comp *tfm; @@ -853,11 +858,5 @@ static void __exit pstore_exit(void) } module_exit(pstore_exit) -module_param(compress, charp, 0444); -MODULE_PARM_DESC(compress, "Pstore compression to use"); - -module_param(backend, charp, 0444); -MODULE_PARM_DESC(backend, "Pstore backend to use"); - MODULE_AUTHOR("Tony Luck "); MODULE_LICENSE("GPL"); From patchwork Sun May 10 20:24:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287354 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=IGYl6bI1; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=M/cJvL8h; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwYm5Mfbz9sSd for ; Mon, 11 May 2020 06:25:48 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=bsMgNoNHeAMTeAiVdEPBDhonMZ3xIiJojZ39UXQJPjs=; b=IGYl6bI1fSuE/V KwGyVps6AwsLLcEGzJbbJtNfSb6isq3coRnUZdqnWHXNHpMWU6F1kU2MrcJ/awQpG+Khj4jnwy3px k/kGD3g/YS9032u62x+hDml5yfLzB5uEbTODhRuh50h8LfUNlaor9OEzdzcg93BYalSi/Y0JCUX5x Bhtr9JP6kvIH1VvwwREHqwzN17UIcdb3q/rU/XV6L+UpMOyblW6U+TVVRUIY0t60cgpuMF3yEgVqe kMB4o1A0L/QPpkwydzHNz1PPKIdpCoACciBhQWO1OJg4YgeuWJhODuWQpVoynzyUrT6o7wOWUUMWB JNTGZeVT/wLy1r/40+bQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsW8-0005e0-AK; Sun, 10 May 2020 20:25:44 +0000 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVB-0002Qz-I4 for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:46 +0000 Received: by mail-pf1-x444.google.com with SMTP id d184so3764008pfd.4 for ; Sun, 10 May 2020 13:24:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5ftIoYymBGMn0ProUbxAIjGCP6irGe3xnecuHwaJ2BU=; b=M/cJvL8hlN3LxOR7YqQKrAGHR739tSJqQTIBdmpAhjDy0nybQzRtcOtAPrHiKVhUKj hsB2XqjX4rZjw8Kbgv6P7obB7m7yi8bCOQa2muYfgmO3VhYbWa1JIbtFntpsUdFnBvpg z2URti78Yz+e3DuPLhwr8YZHxwRBn4DNVm9MI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5ftIoYymBGMn0ProUbxAIjGCP6irGe3xnecuHwaJ2BU=; b=YVZVTXM3tge78zjTKGR9Y/zhB6xhxtiBrPzmu59+1U0BkH76Q/fmP7/apC+X4mcKNJ NBsMaBwd7PSflN2dDK/0Bg+Tl7zcZ8VcBGKIWJOPkFf14olnDw/NdgYcEf7zGcw6p9Cv iTIG/pq5NxYauIqg8uCU1+nUy2zko58Peh55VhbpBNhNmAbrASznzOXryP8UA9c4CC6C YPwamaZlCz5c0Df8ri+H6MxOwMx2RjcI+rUpvDg93BxTQzt8/xUQbaiHuyyx1gwV4XCc azXuZ5ndWHzz8l6uIGvaT5SHIALyLuxx65eNkD7qT1ZPczJtWAOCby3CfeDySCoZwUir FKww== X-Gm-Message-State: AGi0PuZzA3m0An5GBXXu0RYEKrN7ti2FgsaBDAwm9sMCRPP30rENQFC+ Sh1zyOBuwJbZ4pE29uh77dU+Rw== X-Google-Smtp-Source: APiQypKkKbidaXA2M8XJ6HvdzKsXRV/+gbI2nQYSE78Rxu8a98OLbZfjBGurl33BBe6rQc0sYAewRw== X-Received: by 2002:a62:2cd7:: with SMTP id s206mr12711308pfs.183.1589142284913; Sun, 10 May 2020 13:24:44 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id n9sm8014797pjt.29.2020.05.10.13.24.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:41 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 04/18] pstore/platform: Use backend name for console registration Date: Sun, 10 May 2020 13:24:22 -0700 Message-Id: <20200510202436.63222-5-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132445_607142_F911E2BD X-CRM114-Status: GOOD ( 11.42 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:444 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org If the pstore backend changes, there's no indication in the logs what the console is (it always says "pstore"). Instead, pass through the active backend's name. Signed-off-by: Kees Cook --- fs/pstore/platform.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index bf7fa7b278bd..90d146fbc7d2 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -519,13 +519,15 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) } static struct console pstore_console = { - .name = "pstore", .write = pstore_console_write, .index = -1, }; static void pstore_register_console(void) { + /* Show which backend is going to get console writes. */ + strscpy(pstore_console.name, psinfo->name, + sizeof(pstore_console.name)); /* * Always initialize flags here since prior unregister_console() * calls may have changed settings (specifically CON_ENABLED). From patchwork Sun May 10 20:24:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287356 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=oKCFbWbX; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=drD03wch; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwZb5SZGz9sNH for ; Mon, 11 May 2020 06:26:31 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=QZcMZ1W0XZ/uo0FV8DOLs9W+IU3t85JRpmj7+eO3QPU=; b=oKCFbWbXvR/kxy ifOq0efFmXguvWE3eoxArutUrewr/VGlHs9ynqFO1oZIFikxutE/apS9yyVEmviL2QlxvVibX6rXi dljiuWNM1asnSz4f3hcdUSTVmR4mbuX+ziP9kr3Ca44OLzDrQBPXVYy7QS8SCGaP6oKoNPjFE2vYG rOHTh+hj6TAQd3JX3b129gseF6ENkBrJVtOsvOj1ZoMZeEThxXs3IZEAQK2OYUSuKeC5tgDVGdw3W ZEbI1JlTAAhYs8vcRLoWdRsxNAVGV0Iyi4Rc9xHE6V837KF5wQ1AMBTZN8mdVDhsXIlezy4hv5jPI ucp4yH9XCF9JXYsdVCXQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsWh-0006A9-Og; Sun, 10 May 2020 20:26:19 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVD-0002SP-MR for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:49 +0000 Received: by mail-pl1-x644.google.com with SMTP id u10so3022875pls.8 for ; Sun, 10 May 2020 13:24:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9b96+3F3UdF82FBwaSU5JLnw5ZdkMBQ4NVk3N1vy02U=; b=drD03wchFJ8JSi6NQlZOTRxtpLpre/PHVvk/pEeOVs/q7ZaC4QUP/gCZnLxqf1X9sk ytvjnrKwpw83qgDcoxIjucYAFsZ9QFtqdYQPRbOC/ItUOPjzt9OX3OK8tDNL+7XUv22B hPRWWXJBNSFKLTXd/IMgvZws7SyBYTA1VDjBQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9b96+3F3UdF82FBwaSU5JLnw5ZdkMBQ4NVk3N1vy02U=; b=WJq42kgqlCNT535z+QXS4yyiPfRzprCkv4/dOQ/7jP7fLiRnnk6Gg6TiIE0MPZqLE6 nUMzDxTXUeD8Ns3iM1f1jO8i0tCT2wwu8TYwqxKiWm7UTQvYgxF4N1G9eQWgCbJdDUx6 udUNQNnMWtpB1C1QvWbsm/oeQExJYaUh0KpBvtK1voYLYJ/eCKzcQQKaetDEmG7ZFgzT qDrtW1MQPS4Ziv0m/HvmINwexYzBBbAORlKFGSmycSBn9HBHuQRc28MQwsoSnSCKS20T isWLbvavb2IH3XYfkm0CcAdeHg9AB0NHICDDnsk0PQnUgxX9EwozZ2ZDbe0VgR9fxTxB yMPw== X-Gm-Message-State: AGi0PuajBLcV50Ftaj4S2HGB4tN4X8p628M9ZHYfgKuhzJ309MXvIgcp D1R9Ua1ZUzl63li6ZtMeWUQkOQ== X-Google-Smtp-Source: APiQypK13VGjWO1X5uy4YJUs3elsqkv3kZFShDVm0qrPduOIuFGQ3nyFICLCIiUDGDPwI3WjCC6x/w== X-Received: by 2002:a17:90a:21ce:: with SMTP id q72mr18453170pjc.0.1589142287117; Sun, 10 May 2020 13:24:47 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id u5sm7508379pfu.198.2020.05.10.13.24.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:45 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 05/18] pstore/ram: Refactor ftrace buffer merging Date: Sun, 10 May 2020 13:24:23 -0700 Message-Id: <20200510202436.63222-6-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132447_745884_FE36DBA9 X-CRM114-Status: GOOD ( 12.38 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org This changes the ftrace record merging code to be agnostic of pstore/ram, as the first step to making it available as a generic routine for other backends to use, such as pstore/zone. Signed-off-by: Kees Cook --- fs/pstore/ram.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 7f956053f4e5..672ad80646c5 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -172,8 +172,9 @@ static bool prz_ok(struct persistent_ram_zone *prz) persistent_ram_ecc_string(prz, NULL, 0)); } -static ssize_t ftrace_log_combine(struct persistent_ram_zone *dest, - struct persistent_ram_zone *src) +static +ssize_t ftrace_log_combine(char **dest_log, size_t *dest_log_size, + const char *src_log, size_t src_log_size) { size_t dest_size, src_size, total, dest_off, src_off; size_t dest_idx = 0, src_idx = 0, merged_idx = 0; @@ -181,19 +182,19 @@ static ssize_t ftrace_log_combine(struct persistent_ram_zone *dest, struct pstore_ftrace_record *drec, *srec, *mrec; size_t record_size = sizeof(struct pstore_ftrace_record); - dest_off = dest->old_log_size % record_size; - dest_size = dest->old_log_size - dest_off; + dest_off = *dest_log_size % record_size; + dest_size = *dest_log_size - dest_off; - src_off = src->old_log_size % record_size; - src_size = src->old_log_size - src_off; + src_off = src_log_size % record_size; + src_size = src_log_size - src_off; total = dest_size + src_size; merged_buf = kmalloc(total, GFP_KERNEL); if (!merged_buf) return -ENOMEM; - drec = (struct pstore_ftrace_record *)(dest->old_log + dest_off); - srec = (struct pstore_ftrace_record *)(src->old_log + src_off); + drec = (struct pstore_ftrace_record *)(*dest_log + dest_off); + srec = (struct pstore_ftrace_record *)(src_log + src_off); mrec = (struct pstore_ftrace_record *)(merged_buf); while (dest_size > 0 && src_size > 0) { @@ -217,9 +218,9 @@ static ssize_t ftrace_log_combine(struct persistent_ram_zone *dest, src_size -= record_size; } - kfree(dest->old_log); - dest->old_log = merged_buf; - dest->old_log_size = total; + kfree(*dest_log); + *dest_log = merged_buf; + *dest_log_size = total; return 0; } @@ -295,7 +296,11 @@ static ssize_t ramoops_pstore_read(struct pstore_record *record) tmp_prz->corrected_bytes += prz_next->corrected_bytes; tmp_prz->bad_blocks += prz_next->bad_blocks; - size = ftrace_log_combine(tmp_prz, prz_next); + + size = ftrace_log_combine(&tmp_prz->old_log, + &tmp_prz->old_log_size, + prz_next->old_log, + prz_next->old_log_size); if (size) goto out; } From patchwork Sun May 10 20:24:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287357 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=TogZr5em; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Y/sBPsqX; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwZx07zWz9sNH for ; Mon, 11 May 2020 06:26:49 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=CAVYStSO/BMhuosF3VqRaHuix/oHeJ52HihBsAA0DF4=; b=TogZr5emIVUYF7 iTl8ZLT92Ot/67i2k+hh4Wi6RDa1p714C9iBKV6L8YrJOro6BqLK4k9R3wHyfRn8jfUDne4Ab99HD e+k51c14PGOZQV32ymSiasKC0jlxAc5mckrT8VDEwKTWjqTwQQ9Wqipdbad/DYRnZpEcpHxiLo4Tl rQjJf9pHt+qTjsRCSQCZuyKVQsyHir2Fa1MGCpalpLXg58+Tk3iPHc2TbnYCN9rIeNNlX2DbF24nb UDcG6AsCE6ccn0k9W1nH3Z7IPKZnwUVWixXoL3pY1Mtvck9oK0CYNTjiixHSCDkC2bG9JOxN9OkC9 7sAPBEze981ccYlou2bg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsWz-0006Pr-Fq; Sun, 10 May 2020 20:26:37 +0000 Received: from mail-pg1-x544.google.com ([2607:f8b0:4864:20::544]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVE-0002TG-HO for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:50 +0000 Received: by mail-pg1-x544.google.com with SMTP id n11so3542154pgl.9 for ; Sun, 10 May 2020 13:24:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ktEJvuLjRdGObd9XB4X6c1FTgen2GQ5GeA/f/mZmo1s=; b=Y/sBPsqX3MXZ9SIaNFNXmIdsJ3hVH9j0QIs/ZWile2giWgHsi0SikYyILcF9vk3GX2 ubDac1MgzJ2xuFzRSepzs0eQUPCFYIxpGN1trlcxmhG3QmQUnUEyRJVdGeFnc/kcCcS5 giZ9wkrUJX1JeOKrlBYauH00e0HPsaTkbRGDo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ktEJvuLjRdGObd9XB4X6c1FTgen2GQ5GeA/f/mZmo1s=; b=Gzc4I4PQOfALXJvdndtdTN3IujHakGVCesx7XPFvsxCLGHSK/xuKHFY8VGXkhFP574 tXSs8JeqXV+E71xtiyxohApRqEU9UA4cQ5PsZL8PJHJYqrP/h/mT2RFmf0BAbcQWVkJ6 CHz1j41oL7+Z28yFT1+WSqi7ReXTIk9drxHKuERphV04I9SjOBPpwAcVeZFvokXPf3S6 7WveKKJCwvubLdsXIh8gOUGqrbb+U9zzAMWgcryJfjVl7lfSUDvUTtEH2w8MS1HU9LKw 9XgMfFTYbVS2dk0d3b5YYaijB/f8SRao88384Mb0IxudbG6LK6HRSBcPUEt4OuSsIojG /sbA== X-Gm-Message-State: AGi0PuZTGwKGDoJvJ4Qww72IE0Rle01WUFdpgXUaHaIXRlq7ZV4xqCHc Lue8+svjADHEleMUhVYL40GPEA== X-Google-Smtp-Source: APiQypLp/RqzTPiImN8RnELw3dvc46eWFYba4R0+hMF6+nxXnghgmI0h46ibCRZWsSMjsf1wcUokbg== X-Received: by 2002:aa7:9546:: with SMTP id w6mr12944921pfq.114.1589142287716; Sun, 10 May 2020 13:24:47 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id q14sm6250746pgq.60.2020.05.10.13.24.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:45 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 06/18] pstore/ftrace: Provide ftrace log merging routine Date: Sun, 10 May 2020 13:24:24 -0700 Message-Id: <20200510202436.63222-7-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132448_597119_3FAE6F9C X-CRM114-Status: GOOD ( 14.64 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:544 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Move the ftrace log merging logic out of pstore/ram into pstore/ftrace so other backends can use it, like pstore/zone. Signed-off-by: Kees Cook --- fs/pstore/ftrace.c | 54 +++++++++++++++++++++++++++++++++++++++++ fs/pstore/internal.h | 9 +++++++ fs/pstore/ram.c | 57 +++----------------------------------------- 3 files changed, 66 insertions(+), 54 deletions(-) diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c index bfbfc2698070..5c0450701293 100644 --- a/fs/pstore/ftrace.c +++ b/fs/pstore/ftrace.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "internal.h" @@ -132,3 +133,56 @@ void pstore_unregister_ftrace(void) debugfs_remove_recursive(pstore_ftrace_dir); } + +ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size, + const char *src_log, size_t src_log_size) +{ + size_t dest_size, src_size, total, dest_off, src_off; + size_t dest_idx = 0, src_idx = 0, merged_idx = 0; + void *merged_buf; + struct pstore_ftrace_record *drec, *srec, *mrec; + size_t record_size = sizeof(struct pstore_ftrace_record); + + dest_off = *dest_log_size % record_size; + dest_size = *dest_log_size - dest_off; + + src_off = src_log_size % record_size; + src_size = src_log_size - src_off; + + total = dest_size + src_size; + merged_buf = kmalloc(total, GFP_KERNEL); + if (!merged_buf) + return -ENOMEM; + + drec = (struct pstore_ftrace_record *)(*dest_log + dest_off); + srec = (struct pstore_ftrace_record *)(src_log + src_off); + mrec = (struct pstore_ftrace_record *)(merged_buf); + + while (dest_size > 0 && src_size > 0) { + if (pstore_ftrace_read_timestamp(&drec[dest_idx]) < + pstore_ftrace_read_timestamp(&srec[src_idx])) { + mrec[merged_idx++] = drec[dest_idx++]; + dest_size -= record_size; + } else { + mrec[merged_idx++] = srec[src_idx++]; + src_size -= record_size; + } + } + + while (dest_size > 0) { + mrec[merged_idx++] = drec[dest_idx++]; + dest_size -= record_size; + } + + while (src_size > 0) { + mrec[merged_idx++] = srec[src_idx++]; + src_size -= record_size; + } + + kfree(*dest_log); + *dest_log = merged_buf; + *dest_log_size = total; + + return 0; +} +EXPORT_SYMBOL_GPL(pstore_ftrace_combine_log); diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index 8efd72d93b10..7fb219042f13 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -12,9 +12,18 @@ extern unsigned long kmsg_bytes; #ifdef CONFIG_PSTORE_FTRACE extern void pstore_register_ftrace(void); extern void pstore_unregister_ftrace(void); +ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size, + const char *src_log, size_t src_log_size); #else static inline void pstore_register_ftrace(void) {} static inline void pstore_unregister_ftrace(void) {} +static inline ssize_t +pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size, + const char *src_log, size_t src_log_size) +{ + *dest_log_size = 0; + return 0; +} #endif #ifdef CONFIG_PSTORE_PMSG diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 672ad80646c5..b7929fdc0c72 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -21,6 +21,7 @@ #include #include #include +#include "internal.h" #define RAMOOPS_KERNMSG_HDR "====" #define MIN_MEM_SIZE 4096UL @@ -172,59 +173,6 @@ static bool prz_ok(struct persistent_ram_zone *prz) persistent_ram_ecc_string(prz, NULL, 0)); } -static -ssize_t ftrace_log_combine(char **dest_log, size_t *dest_log_size, - const char *src_log, size_t src_log_size) -{ - size_t dest_size, src_size, total, dest_off, src_off; - size_t dest_idx = 0, src_idx = 0, merged_idx = 0; - void *merged_buf; - struct pstore_ftrace_record *drec, *srec, *mrec; - size_t record_size = sizeof(struct pstore_ftrace_record); - - dest_off = *dest_log_size % record_size; - dest_size = *dest_log_size - dest_off; - - src_off = src_log_size % record_size; - src_size = src_log_size - src_off; - - total = dest_size + src_size; - merged_buf = kmalloc(total, GFP_KERNEL); - if (!merged_buf) - return -ENOMEM; - - drec = (struct pstore_ftrace_record *)(*dest_log + dest_off); - srec = (struct pstore_ftrace_record *)(src_log + src_off); - mrec = (struct pstore_ftrace_record *)(merged_buf); - - while (dest_size > 0 && src_size > 0) { - if (pstore_ftrace_read_timestamp(&drec[dest_idx]) < - pstore_ftrace_read_timestamp(&srec[src_idx])) { - mrec[merged_idx++] = drec[dest_idx++]; - dest_size -= record_size; - } else { - mrec[merged_idx++] = srec[src_idx++]; - src_size -= record_size; - } - } - - while (dest_size > 0) { - mrec[merged_idx++] = drec[dest_idx++]; - dest_size -= record_size; - } - - while (src_size > 0) { - mrec[merged_idx++] = srec[src_idx++]; - src_size -= record_size; - } - - kfree(*dest_log); - *dest_log = merged_buf; - *dest_log_size = total; - - return 0; -} - static ssize_t ramoops_pstore_read(struct pstore_record *record) { ssize_t size = 0; @@ -297,7 +245,8 @@ static ssize_t ramoops_pstore_read(struct pstore_record *record) prz_next->corrected_bytes; tmp_prz->bad_blocks += prz_next->bad_blocks; - size = ftrace_log_combine(&tmp_prz->old_log, + size = pstore_ftrace_combine_log( + &tmp_prz->old_log, &tmp_prz->old_log_size, prz_next->old_log, prz_next->old_log_size); From patchwork Sun May 10 20:24:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287358 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=ATU9pfKK; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=SE/Lj2r/; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwbG0Jxtz9sNH for ; Mon, 11 May 2020 06:27:06 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=jQAtgS7xh6lVtFdebzXzcveUN48BMDAtfDn0z5SuKVM=; b=ATU9pfKK8Gc5GW z11AImWrH8Y8qvm+0ZwyTGGJSoCM2d/opiUYDmQum3OnZwgVs8hkHJy0/AhRA27K9+UKutE7sET8u nAw5BwScG9X9zNbZ0ZYmmHM8eI7fefARrjIupNxEJSFhbpuRQV39L3mnmQ6gNhFYh278IR8sC27qb yqxuq9g6Yi42ubwnweO+DudyoLuffeRem2pUA/GmXDA74cP3qa2bQVk0x/Jstd4TvVuq7YmBegc1m 9yH134sU+sG7gg7b6YjbLEfnyc29CS1BbV9QMRhK64BGcDv/JeLnaf1xh8gM5LRL/vkIbt4i9OOaf PfUCnmDmAifPqtJDGC3Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsXG-0006jQ-0L; Sun, 10 May 2020 20:26:54 +0000 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVF-0002UN-28 for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:50 +0000 Received: by mail-pg1-x541.google.com with SMTP id s11so57282pgv.13 for ; Sun, 10 May 2020 13:24:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=e8QxXpTtzEc0PFUpgGtgZUc+FvTwN2g4UuYupfacY68=; b=SE/Lj2r/qm5MRAqEmy91aIMpwxOMaSbPzJm9LffMRTM1bMYU65FQ1TKG3X0ZDbyYio 7B7iJyomdn5ZaPKTBC2NPCyLpN+6NjzvPW1RdCc5OrFF7OGirTC6irYkn7I1yMOmA0QU 6ab1OTO/QvQNAoQqtEtzq1eDx2y9kcPmeWYbw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=e8QxXpTtzEc0PFUpgGtgZUc+FvTwN2g4UuYupfacY68=; b=V/UqdEsXggNOnxCB0ZipYaKY1LFPLQKPM4PA+X2Lks3xi6R18CTKyjqaSHKDRVeklP 7SfhR86AuafT1DHIaKzyummRAJXEden0xXd2i3EZeYo3OBmP4fK2JyJVFZ84jjUnrhe1 S9lK7V7S7DcG5r5ahmmBnzF9w5vvf4rGbpvOh1sjkpo24psMiCIbM53jcMQTbJtzDuHE y0wg5CSTq0zMtxAFVz38ewqlrVd6c3pkC0sHogJvfHgSAzF5MpxeipSSEiKhISYfH/Tp HBD0zCB3F4J0/eIdJ2j6XDq6pbvtxdhM2US7h/ctKrGxc4E6w1WASbJOsbXXknjsSaus 50hA== X-Gm-Message-State: AGi0PuYwYV/rfZbWnL35UQV8hS5J6rI178JUx0ZE6TnKKdROD6G/AqLc 2igiWELiokCwJ1t0pdMcxG4msA== X-Google-Smtp-Source: APiQypJP9SdsFTI/n79iIdc/+hcTxLTAwENcl6uTzDuzTIjiRCcw0DdJASm1sZtZg0sIzx1RfipUbw== X-Received: by 2002:a63:a61:: with SMTP id z33mr11625145pgk.440.1589142288307; Sun, 10 May 2020 13:24:48 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id c10sm7271971pfm.50.2020.05.10.13.24.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:45 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 07/18] printk: Introduce kmsg_dump_reason_str() Date: Sun, 10 May 2020 13:24:25 -0700 Message-Id: <20200510202436.63222-8-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132449_127689_8CFBF014 X-CRM114-Status: GOOD ( 13.16 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:541 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org The pstore subsystem already had a private version of this function. With the coming addition of the pstore/zone driver, this needs to be shared. As it really should live with printk, move it there instead. Signed-off-by: Kees Cook Acked-by: Petr Mladek Acked-by: Sergey Senozhatsky --- fs/pstore/platform.c | 22 +--------------------- include/linux/kmsg_dump.h | 7 +++++++ kernel/printk/printk.c | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 90d146fbc7d2..a9e297eefdff 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -135,26 +135,6 @@ enum pstore_type_id pstore_name_to_type(const char *name) } EXPORT_SYMBOL_GPL(pstore_name_to_type); -static const char *get_reason_str(enum kmsg_dump_reason reason) -{ - switch (reason) { - case KMSG_DUMP_PANIC: - return "Panic"; - case KMSG_DUMP_OOPS: - return "Oops"; - case KMSG_DUMP_EMERG: - return "Emergency"; - case KMSG_DUMP_RESTART: - return "Restart"; - case KMSG_DUMP_HALT: - return "Halt"; - case KMSG_DUMP_POWEROFF: - return "Poweroff"; - default: - return "Unknown"; - } -} - static void pstore_timer_kick(void) { if (pstore_update_ms < 0) @@ -407,7 +387,7 @@ static void pstore_dump(struct kmsg_dumper *dumper, unsigned int part = 1; int ret; - why = get_reason_str(reason); + why = kmsg_dump_reason_str(reason); if (down_trylock(&psinfo->buf_lock)) { /* Failed to acquire lock: give up if we cannot wait. */ diff --git a/include/linux/kmsg_dump.h b/include/linux/kmsg_dump.h index cfc042066be7..b3ddb0b2ee40 100644 --- a/include/linux/kmsg_dump.h +++ b/include/linux/kmsg_dump.h @@ -72,6 +72,8 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper); int kmsg_dump_register(struct kmsg_dumper *dumper); int kmsg_dump_unregister(struct kmsg_dumper *dumper); + +const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason); #else static inline void kmsg_dump(enum kmsg_dump_reason reason) { @@ -113,6 +115,11 @@ static inline int kmsg_dump_unregister(struct kmsg_dumper *dumper) { return -EINVAL; } + +static inline const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason) +{ + return "Disabled"; +} #endif #endif /* _LINUX_KMSG_DUMP_H */ diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 1aab69a8a2bf..67a284830d74 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3144,6 +3144,27 @@ EXPORT_SYMBOL_GPL(kmsg_dump_unregister); static bool always_kmsg_dump; module_param_named(always_kmsg_dump, always_kmsg_dump, bool, S_IRUGO | S_IWUSR); +const char *kmsg_dump_reason_str(enum kmsg_dump_reason reason) +{ + switch (reason) { + case KMSG_DUMP_PANIC: + return "Panic"; + case KMSG_DUMP_OOPS: + return "Oops"; + case KMSG_DUMP_EMERG: + return "Emergency"; + case KMSG_DUMP_RESTART: + return "Restart"; + case KMSG_DUMP_HALT: + return "Halt"; + case KMSG_DUMP_POWEROFF: + return "Poweroff"; + default: + return "Unknown"; + } +} +EXPORT_SYMBOL_GPL(kmsg_dump_reason_str); + /** * kmsg_dump - dump kernel log to kernel message dumpers. * @reason: the reason (oops, panic etc) for dumping From patchwork Sun May 10 20:24:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287360 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=Au3fXSaQ; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=hRsMh77I; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Kwc52JK1z9sNH for ; Mon, 11 May 2020 06:27:49 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=+03xl3ikZseGJq7VJRNgUE01QeSn6Th3c1PZdwk9UO4=; b=Au3fXSaQXvUiSz ZKm3YwHgVKDxjOW5CjyUDCuI9j6F+LmkMV78StmVdE/ccogFpfzGS1PZp740O7GKnpgy+Z+mrwu06 yccYNkQUpvJNAqUrCzvpbX7XcruVKBHqetHdZWSpzc2a8CUOn77gmSOcS2Cicg3WZns8JLjkfev/t J8UzE7PlpDjbb3NzR51tpysU+bBe2J+3O7TOrR/RNpJJYby6hgBkT7XsbHsZqoFMfLBjOgW391eLu ZYhMuiRf591BTTmDbPxEepTW9GOiTE8AWOquc+jC7lBkba9AiLptUiPALI8fS/OIbpiDAfIyo4GBh YT1v5tQ46DDb4BxGPLhQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsXr-0007Uv-QR; Sun, 10 May 2020 20:27:31 +0000 Received: from mail-pj1-x1043.google.com ([2607:f8b0:4864:20::1043]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVH-0002Vw-4j for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:55 +0000 Received: by mail-pj1-x1043.google.com with SMTP id q24so6727960pjd.1 for ; Sun, 10 May 2020 13:24:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JanhkQPHoBeqN7+yenEXsezjmbrePIr/OPNe7mNQA0U=; b=hRsMh77I5OWjM1cxWjsTgotbGrAxde1q5mT1lA40Yh15JoXHdW32aNJdylX1/Whvrb o/CGuRJopLX47eDVKgZ8bD8XGjQi2Hfge9ssjy3l/NZf2SeSuw4s/k+fJo3jkdOej//D 4OnqfenIT2F1eKAngECSRd8c24Z4x8iJI45CY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JanhkQPHoBeqN7+yenEXsezjmbrePIr/OPNe7mNQA0U=; b=UcA2TfWGS3nZqYxRGdDJHRD9sGVByai3ZSHArb4xKD3HVi4y8ITIFBznlpZ6gmqG6v nWy8nfcUNeOxRVrW7wkaoinZl0obo9Jorjngrvv3M67QKK2FvSeQxEZGN16CCcRw5If5 kEFMqDWk6bLLzK/fIkwXnEOUB/OpT+qropT6HD2oidXW5NDYHlVTQ41+UTOihVRuhqCl ZvlqrREt3TcwpAqsMLZ52XDUZ1Xodth4PcQ6wKyhz20uHGD3K0b/CRuo+jbIfCFz2NRf wPD1UqnAjTJnRb9c2sYvzoDGWmrc14yyCVNKE/e9PXNuYginqyJhFoWyeCkuwK0NJ492 aSXQ== X-Gm-Message-State: AGi0PuakuBbBgthd4epxSorOvyptPtUoR50hS2+Z1FAr3avx5CwWGGEy 8hSxZf6zPsIKaNqVc2AXekkIkQ== X-Google-Smtp-Source: APiQypLNBibrDEkmU26vNK/H2B4HHaDmQUq4KsnyA9kFgWs9TyFaMKwt6Je2RIQdoW/cLaJwHs3MBQ== X-Received: by 2002:a17:90a:1181:: with SMTP id e1mr19462391pja.234.1589142289061; Sun, 10 May 2020 13:24:49 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id t80sm7691838pfc.23.2020.05.10.13.24.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:45 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 08/18] pstore/zone: Introduce common layer to manage storage zones Date: Sun, 10 May 2020 13:24:26 -0700 Message-Id: <20200510202436.63222-9-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132451_288554_A3F21A93 X-CRM114-Status: GOOD ( 23.73 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1043 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao Implement a common set of APIs needed to support pstore storage zones, based on how ramoops is designed. This will be used by pstore/blk with the intention of migrating pstore/ram in the future. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-2-git-send-email-liaoweixiong@allwinnertech.com Co-developed-by: Kees Cook Signed-off-by: Kees Cook --- fs/pstore/Kconfig | 7 + fs/pstore/Makefile | 3 + fs/pstore/zone.c | 985 ++++++++++++++++++++++++++++++++++++ include/linux/pstore_zone.h | 44 ++ 4 files changed, 1039 insertions(+) create mode 100644 fs/pstore/zone.c create mode 100644 include/linux/pstore_zone.h diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 8f0369aad22a..98d2457bdd9f 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -153,3 +153,10 @@ config PSTORE_RAM "ramoops.ko". For more information, see Documentation/admin-guide/ramoops.rst. + +config PSTORE_ZONE + tristate + depends on PSTORE + help + The common layer for pstore/blk (and pstore/ram in the future) + to manage storage in zones. diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile index 967b5891f325..58a967cbe4af 100644 --- a/fs/pstore/Makefile +++ b/fs/pstore/Makefile @@ -12,3 +12,6 @@ pstore-$(CONFIG_PSTORE_PMSG) += pmsg.o ramoops-objs += ram.o ram_core.o obj-$(CONFIG_PSTORE_RAM) += ramoops.o + +pstore_zone-objs += zone.o +obj-$(CONFIG_PSTORE_ZONE) += pstore_zone.o diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c new file mode 100644 index 000000000000..a388c299ebb1 --- /dev/null +++ b/fs/pstore/zone.c @@ -0,0 +1,985 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Provide a pstore intermediate backend, organized into kernel memory + * allocated zones that are then mapped and flushed into a single + * contiguous region on a storage backend of some kind (block, mtd, etc). + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +/** + * struct psz_head - header of zone to flush to storage + * + * @sig: signature to indicate header (PSZ_SIG xor PSZONE-type value) + * @datalen: length of data in @data + * @data: zone data. + */ +struct psz_buffer { +#define PSZ_SIG (0x43474244) /* DBGC */ + uint32_t sig; + atomic_t datalen; + uint8_t data[]; +}; + +/** + * struct psz_kmsg_header - kmsg dump-specific header to flush to storage + * + * @magic: magic num for oops header + * @time: oops/panic trigger time + * @compressed: whether conpressed + * @counter: oops/panic counter + * @reason: identify oops or panic + * @data: pointer to log data + * + * This is a sub-header for a kmsg dump, trailing after &psz_buffer. + */ +struct psz_kmsg_header { +#define OOPS_HEADER_MAGIC 0x4dfc3ae5 /* Just a random number */ + uint32_t magic; + struct timespec64 time; + bool compressed; + uint32_t counter; + enum kmsg_dump_reason reason; + uint8_t data[]; +}; + +/** + * struct pstore_zone - single stored buffer + * + * @off: zone offset of storage + * @type: front-end type for this zone + * @name: front-end name for this zone + * @buffer: pointer to data buffer managed by this zone + * @oldbuf: pointer to old data buffer + * @buffer_size: bytes in @buffer->data + * @should_recover: whether this zone should recover from storage + * @dirty: whether the data in @buffer dirty + * + * zone structure in memory. + */ +struct pstore_zone { + loff_t off; + const char *name; + enum pstore_type_id type; + + struct psz_buffer *buffer; + struct psz_buffer *oldbuf; + size_t buffer_size; + bool should_recover; + atomic_t dirty; +}; + +/** + * struct psz_context - all about running state of pstore/zone + * + * @opszs: oops/panic storage zones + * @kmsg_max_cnt: max count of @opszs + * @kmsg_read_cnt: counter to read oops zone + * @kmsg_write_cnt: counter to write + * @oops_counter: counter to oops + * @panic_counter: counter to panic + * @recovered: whether finish recovering data from storage + * @on_panic: whether occur panic + * @pstore_zone_info_lock: lock to @pstore_zone_info + * @pstore_zone_info: information from back-end + * @pstore: structure for pstore + */ +struct psz_context { + struct pstore_zone **opszs; + unsigned int kmsg_max_cnt; + unsigned int kmsg_read_cnt; + unsigned int kmsg_write_cnt; + /* + * the counter should be recovered when recover. + * It records the oops/panic times after burning rather than booting. + */ + unsigned int oops_counter; + unsigned int panic_counter; + atomic_t recovered; + atomic_t on_panic; + + /* + * pstore_zone_info_lock protects this entire structure during calls + * to register_pstore_zone()/unregister_pstore_zone(). + */ + struct mutex pstore_zone_info_lock; + struct pstore_zone_info *pstore_zone_info; + struct pstore_info pstore; +}; +static struct psz_context pstore_zone_cxt; + +/** + * enum psz_flush_mode - flush mode for psz_zone_write() + * + * @FLUSH_NONE: do not flush to storage but update data on memory + * @FLUSH_PART: just flush part of data including meta data to storage + * @FLUSH_META: just flush meta data of zone to storage + * @FLUSH_ALL: flush all of zone + */ +enum psz_flush_mode { + FLUSH_NONE = 0, + FLUSH_PART, + FLUSH_META, + FLUSH_ALL, +}; + +static inline int buffer_datalen(struct pstore_zone *zone) +{ + return atomic_read(&zone->buffer->datalen); +} + +static inline bool is_on_panic(void) +{ + return atomic_read(&pstore_zone_cxt.on_panic); +} + +static ssize_t psz_zone_read(struct pstore_zone *zone, char *buf, + size_t len, unsigned long off) +{ + if (!buf || !zone->buffer) + return -EINVAL; + if (off > zone->buffer_size) + return -EINVAL; + len = min_t(size_t, len, zone->buffer_size - off); + memcpy(buf, zone->buffer->data + off, len); + return len; +} + +static int psz_zone_write(struct pstore_zone *zone, + enum psz_flush_mode flush_mode, const char *buf, + size_t len, unsigned long off) +{ + struct pstore_zone_info *info = pstore_zone_cxt.pstore_zone_info; + ssize_t wcnt = 0; + ssize_t (*writeop)(const char *buf, size_t bytes, loff_t pos); + size_t wlen; + + if (off > zone->buffer_size) + return -EINVAL; + + wlen = min_t(size_t, len, zone->buffer_size - off); + if (buf && wlen) { + memcpy(zone->buffer->data + off, buf, wlen); + atomic_set(&zone->buffer->datalen, wlen + off); + } + + /* avoid to damage old records */ + if (!is_on_panic() && !atomic_read(&pstore_zone_cxt.recovered)) + goto dirty; + + writeop = is_on_panic() ? info->panic_write : info->write; + if (!writeop) + goto dirty; + + switch (flush_mode) { + case FLUSH_NONE: + if (unlikely(buf && wlen)) + goto dirty; + return 0; + case FLUSH_PART: + wcnt = writeop((const char *)zone->buffer->data + off, wlen, + zone->off + sizeof(*zone->buffer) + off); + if (wcnt != wlen) + goto dirty; + fallthrough; + case FLUSH_META: + wlen = sizeof(struct psz_buffer); + wcnt = writeop((const char *)zone->buffer, wlen, zone->off); + if (wcnt != wlen) + goto dirty; + break; + case FLUSH_ALL: + wlen = zone->buffer_size + sizeof(*zone->buffer); + wcnt = writeop((const char *)zone->buffer, wlen, zone->off); + if (wcnt != wlen) + goto dirty; + break; + } + + return 0; +dirty: + atomic_set(&zone->dirty, true); + return -EBUSY; +} + +static int psz_flush_dirty_zone(struct pstore_zone *zone) +{ + int ret; + + if (unlikely(!zone)) + return -EINVAL; + + if (unlikely(!atomic_read(&pstore_zone_cxt.recovered))) + return -EBUSY; + + if (!atomic_xchg(&zone->dirty, false)) + return 0; + + ret = psz_zone_write(zone, FLUSH_ALL, NULL, 0, 0); + if (ret) + atomic_set(&zone->dirty, true); + return ret; +} + +static int psz_flush_dirty_zones(struct pstore_zone **zones, unsigned int cnt) +{ + int i, ret; + struct pstore_zone *zone; + + if (!zones) + return -EINVAL; + + for (i = 0; i < cnt; i++) { + zone = zones[i]; + if (!zone) + return -EINVAL; + ret = psz_flush_dirty_zone(zone); + if (ret) + return ret; + } + return 0; +} + +static int psz_move_zone(struct pstore_zone *old, struct pstore_zone *new) +{ + const char *data = (const char *)old->buffer->data; + int ret; + + ret = psz_zone_write(new, FLUSH_ALL, data, buffer_datalen(old), 0); + if (ret) { + atomic_set(&new->buffer->datalen, 0); + atomic_set(&new->dirty, false); + return ret; + } + atomic_set(&old->buffer->datalen, 0); + return 0; +} + +static int psz_kmsg_recover_data(struct psz_context *cxt) +{ + struct pstore_zone_info *info = cxt->pstore_zone_info; + struct pstore_zone *zone = NULL; + struct psz_buffer *buf; + unsigned long i; + ssize_t rcnt; + + if (!info->read) + return -EINVAL; + + for (i = 0; i < cxt->kmsg_max_cnt; i++) { + zone = cxt->opszs[i]; + if (unlikely(!zone)) + return -EINVAL; + if (atomic_read(&zone->dirty)) { + unsigned int wcnt = cxt->kmsg_write_cnt; + struct pstore_zone *new = cxt->opszs[wcnt]; + int ret; + + ret = psz_move_zone(zone, new); + if (ret) { + pr_err("move zone from %lu to %d failed\n", + i, wcnt); + return ret; + } + cxt->kmsg_write_cnt = (wcnt + 1) % cxt->kmsg_max_cnt; + } + if (!zone->should_recover) + continue; + buf = zone->buffer; + rcnt = info->read((char *)buf, zone->buffer_size + sizeof(*buf), + zone->off); + if (rcnt != zone->buffer_size + sizeof(*buf)) + return (int)rcnt < 0 ? (int)rcnt : -EIO; + } + return 0; +} + +static int psz_kmsg_recover_meta(struct psz_context *cxt) +{ + struct pstore_zone_info *info = cxt->pstore_zone_info; + struct pstore_zone *zone; + size_t rcnt, len; + struct psz_buffer *buf; + struct psz_kmsg_header *hdr; + struct timespec64 time = { }; + unsigned long i; + /* + * Recover may on panic, we can't allocate any memory by kmalloc. + * So, we use local array instead. + */ + char buffer_header[sizeof(*buf) + sizeof(*hdr)] = {0}; + + if (!info->read) + return -EINVAL; + + len = sizeof(*buf) + sizeof(*hdr); + buf = (struct psz_buffer *)buffer_header; + for (i = 0; i < cxt->kmsg_max_cnt; i++) { + zone = cxt->opszs[i]; + if (unlikely(!zone)) + return -EINVAL; + + rcnt = info->read((char *)buf, len, zone->off); + if (rcnt != len) { + pr_err("read %s with id %lu failed\n", zone->name, i); + return (int)rcnt < 0 ? (int)rcnt : -EIO; + } + + if (buf->sig != zone->buffer->sig) { + pr_debug("no valid data in oops zone %lu\n", i); + continue; + } + + if (zone->buffer_size < atomic_read(&buf->datalen)) { + pr_info("found overtop zone: %s: id %lu, off %lld, size %zu\n", + zone->name, i, zone->off, + zone->buffer_size); + continue; + } + + hdr = (struct psz_kmsg_header *)buf->data; + if (hdr->magic != OOPS_HEADER_MAGIC) { + pr_info("found invalid zone: %s: id %lu, off %lld, size %zu\n", + zone->name, i, zone->off, + zone->buffer_size); + continue; + } + + /* + * we get the newest zone, and the next one must be the oldest + * or unused zone, because we do write one by one like a circle. + */ + if (hdr->time.tv_sec >= time.tv_sec) { + time.tv_sec = hdr->time.tv_sec; + cxt->kmsg_write_cnt = (i + 1) % cxt->kmsg_max_cnt; + } + + if (hdr->reason == KMSG_DUMP_OOPS) + cxt->oops_counter = + max(cxt->oops_counter, hdr->counter); + else if (hdr->reason == KMSG_DUMP_PANIC) + cxt->panic_counter = + max(cxt->panic_counter, hdr->counter); + + if (!atomic_read(&buf->datalen)) { + pr_debug("found erased zone: %s: id %lu, off %lld, size %zu, datalen %d\n", + zone->name, i, zone->off, + zone->buffer_size, + atomic_read(&buf->datalen)); + continue; + } + + if (!is_on_panic()) + zone->should_recover = true; + pr_debug("found nice zone: %s: id %lu, off %lld, size %zu, datalen %d\n", + zone->name, i, zone->off, + zone->buffer_size, atomic_read(&buf->datalen)); + } + + return 0; +} + +static int psz_kmsg_recover(struct psz_context *cxt) +{ + int ret; + + if (!cxt->opszs) + return 0; + + ret = psz_kmsg_recover_meta(cxt); + if (ret) + goto recover_fail; + + ret = psz_kmsg_recover_data(cxt); + if (ret) + goto recover_fail; + + return 0; +recover_fail: + pr_debug("psz_recover_kmsg failed\n"); + return ret; +} + +/** + * psz_recovery() - recover data from storage + * @cxt: the context of pstore/zone + * + * recovery means reading data back from storage after rebooting + * + * Return: 0 on success, others on failure. + */ +static inline int psz_recovery(struct psz_context *cxt) +{ + int ret = -EBUSY; + + if (atomic_read(&cxt->recovered)) + return 0; + + ret = psz_kmsg_recover(cxt); + if (ret) + goto recover_fail; + + pr_debug("recover end!\n"); + atomic_set(&cxt->recovered, 1); + return 0; + +recover_fail: + pr_err("recover failed\n"); + return ret; +} + +static int psz_pstore_open(struct pstore_info *psi) +{ + struct psz_context *cxt = psi->data; + + cxt->kmsg_read_cnt = 0; + return 0; +} + +static inline bool psz_ok(struct pstore_zone *zone) +{ + if (zone && zone->buffer && buffer_datalen(zone)) + return true; + return false; +} + +static inline int psz_kmsg_erase(struct psz_context *cxt, + struct pstore_zone *zone, struct pstore_record *record) +{ + struct psz_buffer *buffer = zone->buffer; + struct psz_kmsg_header *hdr = + (struct psz_kmsg_header *)buffer->data; + + if (unlikely(!psz_ok(zone))) + return 0; + /* this zone is already updated, no need to erase */ + if (record->count != hdr->counter) + return 0; + + atomic_set(&zone->buffer->datalen, 0); + return psz_zone_write(zone, FLUSH_META, NULL, 0, 0); +} + +static int psz_pstore_erase(struct pstore_record *record) +{ + struct psz_context *cxt = record->psi->data; + + switch (record->type) { + case PSTORE_TYPE_DMESG: + if (record->id >= cxt->kmsg_max_cnt) + return -EINVAL; + return psz_kmsg_erase(cxt, cxt->opszs[record->id], record); + default: + return -EINVAL; + } +} + +static void psz_write_kmsg_hdr(struct pstore_zone *zone, + struct pstore_record *record) +{ + struct psz_context *cxt = record->psi->data; + struct psz_buffer *buffer = zone->buffer; + struct psz_kmsg_header *hdr = + (struct psz_kmsg_header *)buffer->data; + + hdr->magic = OOPS_HEADER_MAGIC; + hdr->compressed = record->compressed; + hdr->time.tv_sec = record->time.tv_sec; + hdr->time.tv_nsec = record->time.tv_nsec; + hdr->reason = record->reason; + if (hdr->reason == KMSG_DUMP_OOPS) + hdr->counter = ++cxt->oops_counter; + else + hdr->counter = ++cxt->panic_counter; +} + +static inline int notrace psz_kmsg_write_record(struct psz_context *cxt, + struct pstore_record *record) +{ + size_t size, hlen; + struct pstore_zone *zone; + unsigned int zonenum; + + zonenum = cxt->kmsg_write_cnt; + zone = cxt->opszs[zonenum]; + if (unlikely(!zone)) + return -ENOSPC; + cxt->kmsg_write_cnt = (zonenum + 1) % cxt->kmsg_max_cnt; + + pr_debug("write %s to zone id %d\n", zone->name, zonenum); + psz_write_kmsg_hdr(zone, record); + hlen = sizeof(struct psz_kmsg_header); + size = min_t(size_t, record->size, zone->buffer_size - hlen); + return psz_zone_write(zone, FLUSH_ALL, record->buf, size, hlen); +} + +static int notrace psz_kmsg_write(struct psz_context *cxt, + struct pstore_record *record) +{ + int ret; + + /* + * Explicitly only take the first part of any new crash. + * If our buffer is larger than kmsg_bytes, this can never happen, + * and if our buffer is smaller than kmsg_bytes, we don't want the + * report split across multiple records. + */ + if (record->part != 1) + return -ENOSPC; + + if (!cxt->opszs) + return -ENOSPC; + + ret = psz_kmsg_write_record(cxt, record); + if (!ret) { + pr_debug("try to flush other dirty oops zones\n"); + psz_flush_dirty_zones(cxt->opszs, cxt->kmsg_max_cnt); + } + + /* always return 0 as we had handled it on buffer */ + return 0; +} + +static int notrace psz_pstore_write(struct pstore_record *record) +{ + struct psz_context *cxt = record->psi->data; + + if (record->type == PSTORE_TYPE_DMESG && + record->reason == KMSG_DUMP_PANIC) + atomic_set(&cxt->on_panic, 1); + + switch (record->type) { + case PSTORE_TYPE_DMESG: + return psz_kmsg_write(cxt, record); + default: + return -EINVAL; + } +} + +static struct pstore_zone *psz_read_next_zone(struct psz_context *cxt) +{ + struct pstore_zone *zone = NULL; + + while (cxt->kmsg_read_cnt < cxt->kmsg_max_cnt) { + zone = cxt->opszs[cxt->kmsg_read_cnt++]; + if (psz_ok(zone)) + return zone; + } + + return NULL; +} + +static int psz_kmsg_read_hdr(struct pstore_zone *zone, + struct pstore_record *record) +{ + struct psz_buffer *buffer = zone->buffer; + struct psz_kmsg_header *hdr = + (struct psz_kmsg_header *)buffer->data; + + if (hdr->magic != OOPS_HEADER_MAGIC) + return -EINVAL; + record->compressed = hdr->compressed; + record->time.tv_sec = hdr->time.tv_sec; + record->time.tv_nsec = hdr->time.tv_nsec; + record->reason = hdr->reason; + record->count = hdr->counter; + return 0; +} + +static ssize_t psz_kmsg_read(struct pstore_zone *zone, + struct pstore_record *record) +{ + ssize_t size, hlen = 0; + + size = buffer_datalen(zone); + /* Clear and skip this oops record if it has no valid header */ + if (psz_kmsg_read_hdr(zone, record)) { + atomic_set(&zone->buffer->datalen, 0); + atomic_set(&zone->dirty, 0); + return -ENOMSG; + } + size -= sizeof(struct psz_kmsg_header); + + if (!record->compressed) { + char *buf = kasprintf(GFP_KERNEL, "%s: Total %d times\n", + kmsg_dump_reason_str(record->reason), + record->count); + hlen = strlen(buf); + record->buf = krealloc(buf, hlen + size, GFP_KERNEL); + if (!record->buf) { + kfree(buf); + return -ENOMEM; + } + } else { + record->buf = kmalloc(size, GFP_KERNEL); + if (!record->buf) + return -ENOMEM; + } + + size = psz_zone_read(zone, record->buf + hlen, size, + sizeof(struct psz_kmsg_header)); + if (unlikely(size < 0)) { + kfree(record->buf); + return -ENOMSG; + } + + return size + hlen; +} + +static ssize_t psz_pstore_read(struct pstore_record *record) +{ + struct psz_context *cxt = record->psi->data; + ssize_t (*readop)(struct pstore_zone *zone, + struct pstore_record *record); + struct pstore_zone *zone; + ssize_t ret; + + /* before read, we must recover from storage */ + ret = psz_recovery(cxt); + if (ret) + return ret; + +next_zone: + zone = psz_read_next_zone(cxt); + if (!zone) + return 0; + + record->type = zone->type; + switch (record->type) { + case PSTORE_TYPE_DMESG: + readop = psz_kmsg_read; + record->id = cxt->kmsg_read_cnt - 1; + break; + default: + goto next_zone; + } + + ret = readop(zone, record); + if (ret == -ENOMSG) + goto next_zone; + return ret; +} + +static struct psz_context pstore_zone_cxt = { + .pstore_zone_info_lock = + __MUTEX_INITIALIZER(pstore_zone_cxt.pstore_zone_info_lock), + .recovered = ATOMIC_INIT(0), + .on_panic = ATOMIC_INIT(0), + .pstore = { + .owner = THIS_MODULE, + .open = psz_pstore_open, + .read = psz_pstore_read, + .write = psz_pstore_write, + .erase = psz_pstore_erase, + }, +}; + +static void psz_free_zone(struct pstore_zone **pszone) +{ + struct pstore_zone *zone = *pszone; + + if (!zone) + return; + + kfree(zone->buffer); + kfree(zone); + *pszone = NULL; +} + +static void psz_free_zones(struct pstore_zone ***pszones, unsigned int *cnt) +{ + struct pstore_zone **zones = *pszones; + + if (!zones) + return; + + while (*cnt > 0) { + (*cnt)--; + psz_free_zone(&(zones[*cnt])); + } + kfree(zones); + *pszones = NULL; +} + +static void psz_free_all_zones(struct psz_context *cxt) +{ + if (cxt->opszs) + psz_free_zones(&cxt->opszs, &cxt->kmsg_max_cnt); +} + +static struct pstore_zone *psz_init_zone(enum pstore_type_id type, + loff_t *off, size_t size) +{ + struct pstore_zone_info *info = pstore_zone_cxt.pstore_zone_info; + struct pstore_zone *zone; + const char *name = pstore_type_to_name(type); + + if (!size) + return NULL; + + if (*off + size > info->total_size) { + pr_err("no room for %s (0x%zx@0x%llx over 0x%lx)\n", + name, size, *off, info->total_size); + return ERR_PTR(-ENOMEM); + } + + zone = kzalloc(sizeof(struct pstore_zone), GFP_KERNEL); + if (!zone) + return ERR_PTR(-ENOMEM); + + zone->buffer = kmalloc(size, GFP_KERNEL); + if (!zone->buffer) { + kfree(zone); + return ERR_PTR(-ENOMEM); + } + memset(zone->buffer, 0xFF, size); + zone->off = *off; + zone->name = name; + zone->type = type; + zone->buffer_size = size - sizeof(struct psz_buffer); + zone->buffer->sig = type ^ PSZ_SIG; + atomic_set(&zone->dirty, 0); + atomic_set(&zone->buffer->datalen, 0); + + *off += size; + + pr_debug("pszone %s: off 0x%llx, %zu header, %zu data\n", zone->name, + zone->off, sizeof(*zone->buffer), zone->buffer_size); + return zone; +} + +static struct pstore_zone **psz_init_zones(enum pstore_type_id type, + loff_t *off, size_t total_size, ssize_t record_size, + unsigned int *cnt) +{ + struct pstore_zone_info *info = pstore_zone_cxt.pstore_zone_info; + struct pstore_zone **zones, *zone; + const char *name = pstore_type_to_name(type); + int c, i; + + *cnt = 0; + if (!total_size || !record_size) + return NULL; + + if (*off + total_size > info->total_size) { + pr_err("no room for zones %s (0x%zx@0x%llx over 0x%lx)\n", + name, total_size, *off, info->total_size); + return ERR_PTR(-ENOMEM); + } + + c = total_size / record_size; + zones = kcalloc(c, sizeof(*zones), GFP_KERNEL); + if (!zones) { + pr_err("allocate for zones %s failed\n", name); + return ERR_PTR(-ENOMEM); + } + memset(zones, 0, c * sizeof(*zones)); + + for (i = 0; i < c; i++) { + zone = psz_init_zone(type, off, record_size); + if (!zone || IS_ERR(zone)) { + pr_err("initialize zones %s failed\n", name); + psz_free_zones(&zones, &i); + return (void *)zone; + } + zones[i] = zone; + } + + *cnt = c; + return zones; +} + +static int psz_alloc_zones(struct psz_context *cxt) +{ + struct pstore_zone_info *info = cxt->pstore_zone_info; + loff_t off = 0; + int err; + size_t size; + + size = info->total_size; + cxt->opszs = psz_init_zones(PSTORE_TYPE_DMESG, &off, size, + info->kmsg_size, &cxt->kmsg_max_cnt); + if (IS_ERR(cxt->opszs)) { + err = PTR_ERR(cxt->opszs); + cxt->opszs = NULL; + goto fail_out; + } + + return 0; +fail_out: + return err; +} + +/** + * register_pstore_zone() - register to pstore/zone + * + * @info: back-end driver information. See &struct pstore_zone_info. + * + * Only one back-end at one time. + * + * Return: 0 on success, others on failure. + */ +int register_pstore_zone(struct pstore_zone_info *info) +{ + int err = -EINVAL; + struct psz_context *cxt = &pstore_zone_cxt; + + if (info->total_size < 4096) { + pr_warn("total_size must be >= 4096\n"); + return -EINVAL; + } + + if (!info->kmsg_size) { + pr_warn("at least one record size must be non-zero\n"); + return -EINVAL; + } + + if (!info->name || !info->name[0]) + return -EINVAL; + +#define check_size(name, size) { \ + if (info->name > 0 && info->name < (size)) { \ + pr_err(#name " must be over %d\n", (size)); \ + return -EINVAL; \ + } \ + if (info->name & (size - 1)) { \ + pr_err(#name " must be a multiple of %d\n", \ + (size)); \ + return -EINVAL; \ + } \ + } + + check_size(total_size, 4096); + check_size(kmsg_size, SECTOR_SIZE); + +#undef check_size + + /* + * the @read and @write must be applied. + * if no @read, pstore may mount failed. + * if no @write, pstore do not support to remove record file. + */ + if (!info->read || !info->write) { + pr_err("no valid general read/write interface\n"); + return -EINVAL; + } + + mutex_lock(&cxt->pstore_zone_info_lock); + if (cxt->pstore_zone_info) { + pr_warn("'%s' already loaded: ignoring '%s'\n", + cxt->pstore_zone_info->name, info->name); + mutex_unlock(&cxt->pstore_zone_info_lock); + return -EBUSY; + } + cxt->pstore_zone_info = info; + + pr_debug("register %s with properties:\n", info->name); + pr_debug("\ttotal size : %ld Bytes\n", info->total_size); + pr_debug("\tkmsg size : %ld Bytes\n", info->kmsg_size); + + err = psz_alloc_zones(cxt); + if (err) { + pr_err("alloc zones failed\n"); + goto fail_out; + } + + if (info->kmsg_size) { + cxt->pstore.bufsize = cxt->opszs[0]->buffer_size - + sizeof(struct psz_kmsg_header); + cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL); + if (!cxt->pstore.buf) { + err = -ENOMEM; + goto fail_free; + } + } + cxt->pstore.data = cxt; + + pr_info("registered %s as backend for", info->name); + cxt->pstore.max_reason = info->max_reason; + cxt->pstore.name = info->name; + if (info->kmsg_size) { + cxt->pstore.flags |= PSTORE_FLAGS_DMESG; + pr_cont(" kmsg(%s", + kmsg_dump_reason_str(cxt->pstore.max_reason)); + if (cxt->pstore_zone_info->panic_write) + pr_cont(",panic_write"); + pr_cont(")"); + } + pr_cont("\n"); + + err = pstore_register(&cxt->pstore); + if (err) { + pr_err("registering with pstore failed\n"); + goto fail_free; + } + mutex_unlock(&pstore_zone_cxt.pstore_zone_info_lock); + + return 0; + +fail_free: + kfree(cxt->pstore.buf); + cxt->pstore.buf = NULL; + cxt->pstore.bufsize = 0; + psz_free_all_zones(cxt); +fail_out: + pstore_zone_cxt.pstore_zone_info = NULL; + mutex_unlock(&pstore_zone_cxt.pstore_zone_info_lock); + return err; +} +EXPORT_SYMBOL_GPL(register_pstore_zone); + +/** + * unregister_pstore_zone() - unregister to pstore/zone + * + * @info: back-end driver information. See struct pstore_zone_info. + */ +void unregister_pstore_zone(struct pstore_zone_info *info) +{ + struct psz_context *cxt = &pstore_zone_cxt; + + mutex_lock(&cxt->pstore_zone_info_lock); + if (!cxt->pstore_zone_info) { + mutex_unlock(&cxt->pstore_zone_info_lock); + return; + } + + /* Stop incoming writes from pstore. */ + pstore_unregister(&cxt->pstore); + + /* Clean up allocations. */ + kfree(cxt->pstore.buf); + cxt->pstore.buf = NULL; + cxt->pstore.bufsize = 0; + cxt->pstore_zone_info = NULL; + + psz_free_all_zones(cxt); + + /* Clear counters and zone state. */ + cxt->oops_counter = 0; + cxt->panic_counter = 0; + atomic_set(&cxt->recovered, 0); + atomic_set(&cxt->on_panic, 0); + + mutex_unlock(&cxt->pstore_zone_info_lock); +} +EXPORT_SYMBOL_GPL(unregister_pstore_zone); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("WeiXiong Liao "); +MODULE_AUTHOR("Kees Cook "); +MODULE_DESCRIPTION("Storage Manager for pstore/blk"); diff --git a/include/linux/pstore_zone.h b/include/linux/pstore_zone.h new file mode 100644 index 000000000000..eb005d9ae40c --- /dev/null +++ b/include/linux/pstore_zone.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __PSTORE_ZONE_H_ +#define __PSTORE_ZONE_H_ + +#include + +typedef ssize_t (*pstore_zone_read_op)(char *, size_t, loff_t); +typedef ssize_t (*pstore_zone_write_op)(const char *, size_t, loff_t); +/** + * struct pstore_zone_info - pstore/zone back-end driver structure + * + * @owner: Module which is responsible for this back-end driver. + * @name: Name of the back-end driver. + * @total_size: The total size in bytes pstore/zone can use. It must be greater + * than 4096 and be multiple of 4096. + * @kmsg_size: The size of oops/panic zone. Zero means disabled, otherwise, + * it must be multiple of SECTOR_SIZE(512 Bytes). + * @max_reason: Maximum kmsg dump reason to store. + * @read: The general read operation. Both of the function parameters + * @size and @offset are relative value to storage. + * On success, the number of bytes should be returned, others + * means error. + * @write: The same as @read. + * @panic_write:The write operation only used for panic case. It's optional + * if you do not care panic log. The parameters and return value + * are the same as @read. + */ +struct pstore_zone_info { + struct module *owner; + const char *name; + + unsigned long total_size; + unsigned long kmsg_size; + int max_reason; + pstore_zone_read_op read; + pstore_zone_write_op write; + pstore_zone_write_op panic_write; +}; + +extern int register_pstore_zone(struct pstore_zone_info *info); +extern void unregister_pstore_zone(struct pstore_zone_info *info); + +#endif From patchwork Sun May 10 20:24:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287363 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=MMphXEd5; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=LPWDgYKu; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwdD0Bgrz9sSg for ; Mon, 11 May 2020 06:28:48 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=9joyi3df5mKNEWMSV/GA7vGAQPnRVO27AP+Co5LvEb4=; b=MMphXEd5XzhPxw /orm/EYR6U3Znvsb+Suyk8UI+dI77nC8E+6zU4CMgiMuWBVRy/sMwueq5r+TCr+57Zqw8FLWdsy8x znc6bSUXgS/OPELiuaOo51cjm476ExLsGOxNp0SsPeljAjsty/NaxUtYr35LkyXcf2fTZAun8+B4R yytI1gHS4vAWFJjYUugSxb+QIxVnw2SnGkXcmf63N9x8EvV4fJPAx7s2l94SAnNcz2+aoHa00r7cA AMwRJi6olegJwq2t8ggAGbbYYxQ8kBLd8ByLXVxwGQuohjvwYdGGHcGXbPJLYqTSa22g6RwjBS3g3 FgivDDF5G4riDzGhH15Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsYo-0008Mb-Ao; Sun, 10 May 2020 20:28:30 +0000 Received: from mail-pl1-x636.google.com ([2607:f8b0:4864:20::636]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVI-0002Wx-VP for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:25:01 +0000 Received: by mail-pl1-x636.google.com with SMTP id b12so1106616plz.13 for ; Sun, 10 May 2020 13:24:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=orfXLacS8yqZyDT5q8FIVvYw32KcFrHhapVeCPPfREA=; b=LPWDgYKuQCci0R3tKMmym9Dhl6SCvFPWwYwmQOId1TIXypK4uQPhWefiX+ZEZP0b+0 RcqY2Qm8QRXA2xE9Yv8dY+aWYg2D9FsE6TD5ImyQyYvBzs2lm+1uLxUAIz/NMjhO7vP9 9OHnYIRIhC5nHqkkN2vTR1iI4L7WLmiiHgL18= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=orfXLacS8yqZyDT5q8FIVvYw32KcFrHhapVeCPPfREA=; b=JtDTCnG5XvWRgVMQEVCTes6PJYvNKVeGPUDjcWbJznCb9kN+nlI4OOzYCdTQ6bewvU EC50FoPB7E2d3hcZSkdYm9hDEgj8hGvDjjTgi9prExCPt5nZmh2ZA6R1rzqK5q2axgmC Nys3oOxQqaBM5WjEAd1pGFfLIcwH6j6K3j4AAAoNsdlRjOj5QcL0ViyBGYHmH/l04CC+ reWscwy3BZyB8B/GGEusM6q4xtcFhXe8FssKbd8Lm10Vyyhdy9U2g8QyCEeJDmUS0Zrh h9lQhmVxP+1+AezbGhUyegQx1lYLJiNeJHMKOD41/pGISa49lhS3Hpd7xOS3DtKp7Sjv c+kg== X-Gm-Message-State: AGi0PuaaJo4pcFwEtEWJOF1XJHbnxsFe0whu+Tqj1+BTC2RWC8islypo X7LiEWSlORAsAhhI1sOkdP/OuQ== X-Google-Smtp-Source: APiQypL03VN09/WaC0kGukJHxMZpgA9qN7evYB+XTnBfKxwYPavu9f4GZSOqsofh4X44gJl8QXlVyg== X-Received: by 2002:a17:90a:138c:: with SMTP id i12mr18024777pja.36.1589142290444; Sun, 10 May 2020 13:24:50 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id w1sm6232477pgh.53.2020.05.10.13.24.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:45 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 09/18] pstore/blk: Introduce backend for block devices Date: Sun, 10 May 2020 13:24:27 -0700 Message-Id: <20200510202436.63222-10-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132453_175237_A769CC0C X-CRM114-Status: GOOD ( 25.61 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:636 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao pstore/blk is similar to pstore/ram, but uses a block device as the storage rather than persistent ram. The pstore/blk backend solves two common use-cases that used to preclude using pstore/ram: - not all devices have a battery that could be used to persist regular RAM across power failures. - most embedded intelligent equipment have no persistent ram, which increases costs, instead preferring cheaper solutions, like block devices. pstore/blk provides separate configurations for the end user and for the block drivers. User configuration determines how pstore/blk operates, such as record sizes, max kmsg dump reasons, etc. These can be set by Kconfig and/or module parameters, but module parameter have priority over Kconfig. Driver configuration covers all the details about the target block device, such as total size of the device and how to perform read/write operations. These are provided by block drivers, calling pstore_register_blkdev(), including an optional panic_write callback used to bypass regular IO APIs in an effort to avoid potentially destabilized kernel code during a panic. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-3-git-send-email-liaoweixiong@allwinnertech.com Co-developed-by: Kees Cook Signed-off-by: Kees Cook --- fs/pstore/Kconfig | 64 ++++++ fs/pstore/Makefile | 3 + fs/pstore/blk.c | 436 +++++++++++++++++++++++++++++++++++++ include/linux/pstore_blk.h | 51 +++++ 4 files changed, 554 insertions(+) create mode 100644 fs/pstore/blk.c create mode 100644 include/linux/pstore_blk.h diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 98d2457bdd9f..92ba73bd0b62 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -160,3 +160,67 @@ config PSTORE_ZONE help The common layer for pstore/blk (and pstore/ram in the future) to manage storage in zones. + +config PSTORE_BLK + tristate "Log panic/oops to a block device" + depends on PSTORE + depends on BLOCK + select PSTORE_ZONE + default n + help + This enables panic and oops message to be logged to a block dev + where it can be read back at some later point. + + If unsure, say N. + +config PSTORE_BLK_BLKDEV + string "block device identifier" + depends on PSTORE_BLK + default "" + help + Which block device should be used for pstore/blk. + + It accept the following variants: + 1) device number in hexadecimal represents + itself no leading 0x, for example b302. + 2) /dev/ represents the device number of disk + 3) /dev/ represents the device number + of partition - device number of disk plus the partition number + 4) /dev/p - same as the above, this form is + used when disk name of partitioned disk ends with a digit. + 5) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the + unique id of a partition if the partition table provides it. + The UUID may be either an EFI/GPT UUID, or refer to an MSDOS + partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero- + filled hex representation of the 32-bit "NT disk signature", and PP + is a zero-filled hex representation of the 1-based partition number. + 6) PARTUUID=/PARTNROFF= to select a partition in relation + to a partition with a known unique id. + 7) : major and minor number of the device separated by + a colon. + + NOTE that, both Kconfig and module parameters can configure + pstore/blk, but module parameters have priority over Kconfig. + +config PSTORE_BLK_KMSG_SIZE + int "Size in Kbytes of kmsg dump log to store" + depends on PSTORE_BLK + default 64 + help + This just sets size of kmsg dump (oops, panic, etc) log for + pstore/blk. The size is in KB and must be a multiple of 4. + + NOTE that, both Kconfig and module parameters can configure + pstore/blk, but module parameters have priority over Kconfig. + +config PSTORE_BLK_MAX_REASON + int "Maximum kmsg dump reason to store" + depends on PSTORE_BLK + default 2 + help + The maximum reason for kmsg dumps to store. The default is + 2 (KMSG_DUMP_OOPS), see include/linux/kmsg_dump.h's + enum kmsg_dump_reason for more details. + + NOTE that, both Kconfig and module parameters can configure + pstore/blk, but module parameters have priority over Kconfig. diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile index 58a967cbe4af..c270467aeece 100644 --- a/fs/pstore/Makefile +++ b/fs/pstore/Makefile @@ -15,3 +15,6 @@ obj-$(CONFIG_PSTORE_RAM) += ramoops.o pstore_zone-objs += zone.o obj-$(CONFIG_PSTORE_ZONE) += pstore_zone.o + +pstore_blk-objs += blk.o +obj-$(CONFIG_PSTORE_BLK) += pstore_blk.o diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c new file mode 100644 index 000000000000..cec1fa261d1b --- /dev/null +++ b/fs/pstore/blk.c @@ -0,0 +1,436 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implements pstore backend driver that write to block (or non-block) storage + * devices, using the pstore/zone API. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include "../../block/blk.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static long kmsg_size = CONFIG_PSTORE_BLK_KMSG_SIZE; +module_param(kmsg_size, long, 0400); +MODULE_PARM_DESC(kmsg_size, "kmsg dump record size in kbytes"); + +static int max_reason = CONFIG_PSTORE_BLK_MAX_REASON; +module_param(max_reason, int, 0400); +MODULE_PARM_DESC(max_reason, + "maximum reason for kmsg dump (default 2: Oops and Panic)"); + +/* + * blkdev - the block device to use for pstore storage + * + * Usually, this will be a partition of a block device. + * + * blkdev accepts the following variants: + * 1) device number in hexadecimal represents itself + * no leading 0x, for example b302. + * 2) /dev/ represents the device number of disk + * 3) /dev/ represents the device number + * of partition - device number of disk plus the partition number + * 4) /dev/p - same as the above, that form is + * used when disk name of partitioned disk ends on a digit. + * 5) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the + * unique id of a partition if the partition table provides it. + * The UUID may be either an EFI/GPT UUID, or refer to an MSDOS + * partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero- + * filled hex representation of the 32-bit "NT disk signature", and PP + * is a zero-filled hex representation of the 1-based partition number. + * 6) PARTUUID=/PARTNROFF= to select a partition in relation to + * a partition with a known unique id. + * 7) : major and minor number of the device separated by + * a colon. + */ +static char blkdev[80] = CONFIG_PSTORE_BLK_BLKDEV; +module_param_string(blkdev, blkdev, 80, 0400); +MODULE_PARM_DESC(blkdev, "block device for pstore storage"); + +/* + * All globals must only be accessed under the pstore_blk_lock + * during the register/unregister functions. + */ +static DEFINE_MUTEX(pstore_blk_lock); +static struct block_device *psblk_bdev; +static struct pstore_zone_info *pstore_zone_info; +static pstore_blk_panic_write_op blkdev_panic_write; +static struct bdev_info { + dev_t devt; + sector_t nr_sects; + sector_t start_sect; +} g_bdev_info; + +/** + * struct pstore_device_info - back-end pstore/blk driver structure. + * + * @total_size: The total size in bytes pstore/blk can use. It must be greater + * than 4096 and be multiple of 4096. + * @flags: Refer to macro starting with PSTORE_FLAGS defined in + * linux/pstore.h. It means what front-ends this device support. + * Zero means all backends for compatible. + * @read: The general read operation. Both of the function parameters + * @size and @offset are relative value to bock device (not the + * whole disk). + * On success, the number of bytes should be returned, others + * means error. + * @write: The same as @read. + * @panic_write:The write operation only used for panic case. It's optional + * if you do not care panic log. The parameters and return value + * are the same as @read. + */ +struct pstore_device_info { + unsigned long total_size; + unsigned int flags; + pstore_zone_read_op read; + pstore_zone_write_op write; + pstore_zone_write_op panic_write; +}; + +static int psblk_register_do(struct pstore_device_info *dev) +{ + int ret; + + if (!dev || !dev->total_size || !dev->read || !dev->write) + return -EINVAL; + + mutex_lock(&pstore_blk_lock); + + /* someone already registered before */ + if (pstore_zone_info) { + mutex_unlock(&pstore_blk_lock); + return -EBUSY; + } + pstore_zone_info = kzalloc(sizeof(struct pstore_zone_info), GFP_KERNEL); + if (!pstore_zone_info) { + mutex_unlock(&pstore_blk_lock); + return -ENOMEM; + } + + /* zero means not limit on which backends to attempt to store. */ + if (!dev->flags) + dev->flags = UINT_MAX; + +#define verify_size(name, alignsize, enabled) { \ + long _##name_ = (enabled) ? (name) : 0; \ + _##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \ + if (_##name_ & ((alignsize) - 1)) { \ + pr_info(#name " must align to %d\n", \ + (alignsize)); \ + _##name_ = ALIGN(name, (alignsize)); \ + } \ + name = _##name_ / 1024; \ + pstore_zone_info->name = _##name_; \ + } + + verify_size(kmsg_size, 4096, dev->flags & PSTORE_FLAGS_DMESG); +#undef verify_size + + pstore_zone_info->total_size = dev->total_size; + pstore_zone_info->max_reason = max_reason; + pstore_zone_info->read = dev->read; + pstore_zone_info->write = dev->write; + pstore_zone_info->panic_write = dev->panic_write; + pstore_zone_info->name = KBUILD_MODNAME; + pstore_zone_info->owner = THIS_MODULE; + + ret = register_pstore_zone(pstore_zone_info); + if (ret) { + kfree(pstore_zone_info); + pstore_zone_info = NULL; + } + mutex_unlock(&pstore_blk_lock); + return ret; +} + +static void psblk_unregister_do(struct pstore_device_info *dev) +{ + mutex_lock(&pstore_blk_lock); + if (pstore_zone_info && pstore_zone_info->read == dev->read) { + unregister_pstore_zone(pstore_zone_info); + kfree(pstore_zone_info); + pstore_zone_info = NULL; + } + mutex_unlock(&pstore_blk_lock); +} + +/** + * psblk_get_bdev() - open block device + * + * @holder: Exclusive holder identifier + * @info: Information about bdev to fill in + * + * Return: pointer to block device on success and others on error. + * + * On success, the returned block_device has reference count of one. + */ +static struct block_device *psblk_get_bdev(void *holder, + struct bdev_info *info) +{ + struct block_device *bdev = ERR_PTR(-ENODEV); + fmode_t mode = FMODE_READ | FMODE_WRITE; + sector_t nr_sects; + + if (WARN_ON(!mutex_is_locked(&pstore_blk_lock))) + return ERR_PTR(-EINVAL); + + if (pstore_zone_info) + return ERR_PTR(-EBUSY); + + if (!blkdev[0]) + return ERR_PTR(-ENODEV); + + if (holder) + mode |= FMODE_EXCL; + bdev = blkdev_get_by_path(blkdev, mode, holder); + if (IS_ERR(bdev)) { + dev_t devt; + + devt = name_to_dev_t(blkdev); + if (devt == 0) + return ERR_PTR(-ENODEV); + bdev = blkdev_get_by_dev(devt, mode, holder); + } + + nr_sects = part_nr_sects_read(bdev->bd_part); + if (!nr_sects) { + pr_err("not enough space for '%s'\n", blkdev); + blkdev_put(bdev, mode); + return ERR_PTR(-ENOSPC); + } + + if (info) { + info->devt = bdev->bd_dev; + info->nr_sects = nr_sects; + info->start_sect = get_start_sect(bdev); + } + + return bdev; +} + +static void psblk_put_bdev(struct block_device *bdev, void *holder) +{ + fmode_t mode = FMODE_READ | FMODE_WRITE; + + if (!bdev) + return; + + if (WARN_ON(!mutex_is_locked(&pstore_blk_lock))) + return; + + if (holder) + mode |= FMODE_EXCL; + blkdev_put(bdev, mode); +} + +static ssize_t psblk_generic_blk_read(char *buf, size_t bytes, loff_t pos) +{ + struct block_device *bdev = psblk_bdev; + struct file file; + struct kiocb kiocb; + struct iov_iter iter; + struct kvec iov = {.iov_base = buf, .iov_len = bytes}; + + if (!bdev) + return -ENODEV; + + memset(&file, 0, sizeof(struct file)); + file.f_mapping = bdev->bd_inode->i_mapping; + file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME; + file.f_inode = bdev->bd_inode; + file_ra_state_init(&file.f_ra, file.f_mapping); + + init_sync_kiocb(&kiocb, &file); + kiocb.ki_pos = pos; + iov_iter_kvec(&iter, READ, &iov, 1, bytes); + + return generic_file_read_iter(&kiocb, &iter); +} + +static ssize_t psblk_generic_blk_write(const char *buf, size_t bytes, + loff_t pos) +{ + struct block_device *bdev = psblk_bdev; + struct iov_iter iter; + struct kiocb kiocb; + struct file file; + ssize_t ret; + struct kvec iov = {.iov_base = (void *)buf, .iov_len = bytes}; + + if (!bdev) + return -ENODEV; + + /* Console/Ftrace backend may handle buffer until flush dirty zones */ + if (in_interrupt() || irqs_disabled()) + return -EBUSY; + + memset(&file, 0, sizeof(struct file)); + file.f_mapping = bdev->bd_inode->i_mapping; + file.f_flags = O_DSYNC | __O_SYNC | O_NOATIME; + file.f_inode = bdev->bd_inode; + + init_sync_kiocb(&kiocb, &file); + kiocb.ki_pos = pos; + iov_iter_kvec(&iter, WRITE, &iov, 1, bytes); + + inode_lock(bdev->bd_inode); + ret = generic_write_checks(&kiocb, &iter); + if (ret > 0) + ret = generic_perform_write(&file, &iter, pos); + inode_unlock(bdev->bd_inode); + + if (likely(ret > 0)) { + const struct file_operations f_op = {.fsync = blkdev_fsync}; + + file.f_op = &f_op; + kiocb.ki_pos += ret; + ret = generic_write_sync(&kiocb, ret); + } + return ret; +} + +static ssize_t psblk_blk_panic_write(const char *buf, size_t size, + loff_t off) +{ + int ret; + + if (!blkdev_panic_write) + return -EOPNOTSUPP; + + /* size and off must align to SECTOR_SIZE for block device */ + ret = blkdev_panic_write(buf, off >> SECTOR_SHIFT, + size >> SECTOR_SHIFT); + return ret ? -EIO : size; +} + +static int __register_pstore_blk(struct pstore_blk_info *info) +{ + char bdev_name[BDEVNAME_SIZE]; + struct block_device *bdev; + struct pstore_device_info dev; + struct bdev_info binfo; + void *holder = blkdev; + int ret = -ENODEV; + + if (WARN_ON(!mutex_is_locked(&pstore_blk_lock))) + return -EINVAL; + + /* hold bdev exclusively */ + memset(&binfo, 0, sizeof(binfo)); + bdev = psblk_get_bdev(holder, &binfo); + if (IS_ERR(bdev)) { + pr_err("failed to open '%s'!\n", blkdev); + ret = PTR_ERR(bdev); + goto err_put_bdev; + } + + /* only allow driver matching the @blkdev */ + if (!binfo.devt || MAJOR(binfo.devt) != info->major) { + pr_debug("invalid major %u (expect %u)\n", + info->major, MAJOR(binfo.devt)); + ret = -ENODEV; + goto err_put_bdev; + } + + /* psblk_bdev must be assigned before register to pstore/blk */ + psblk_bdev = bdev; + blkdev_panic_write = info->panic_write; + + /* Copy back block device details. */ + info->devt = binfo.devt; + info->nr_sects = binfo.nr_sects; + info->start_sect = binfo.start_sect; + + memset(&dev, 0, sizeof(dev)); + dev.total_size = info->nr_sects << SECTOR_SHIFT; + dev.flags = info->flags; + dev.read = psblk_generic_blk_read; + dev.write = psblk_generic_blk_write; + dev.panic_write = info->panic_write ? psblk_blk_panic_write : NULL; + + ret = psblk_register_do(&dev); + if (ret) + goto err_put_bdev; + + bdevname(bdev, bdev_name); + pr_info("attached %s%s\n", bdev_name, + info->panic_write ? "" : " (no dedicated panic_write!)"); + return 0; + +err_put_bdev: + psblk_bdev = NULL; + blkdev_panic_write = NULL; + psblk_put_bdev(bdev, holder); + return ret; +} + +/** + * register_pstore_blk() - register block device to pstore/blk + * + * @info: details on the desired block device interface + * + * Return: + * * 0 - OK + * * Others - something error. + */ +int register_pstore_blk(struct pstore_blk_info *info) +{ + int ret; + + mutex_lock(&pstore_blk_lock); + ret = __register_pstore_blk(info); + mutex_unlock(&pstore_blk_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(register_pstore_blk); + +static void __unregister_pstore_blk(unsigned int major) +{ + struct pstore_device_info dev = { .read = psblk_generic_blk_read }; + void *holder = blkdev; + + WARN_ON(!mutex_is_locked(&pstore_blk_lock)); + if (psblk_bdev && MAJOR(psblk_bdev->bd_dev) == major) { + psblk_unregister_do(&dev); + psblk_put_bdev(psblk_bdev, holder); + blkdev_panic_write = NULL; + psblk_bdev = NULL; + memset(&g_bdev_info, 0, sizeof(g_bdev_info)); + } +} + +/** + * unregister_pstore_blk() - unregister block device from pstore/blk + * + * @major: the major device number of device + */ +void unregister_pstore_blk(unsigned int major) +{ + mutex_lock(&pstore_blk_lock); + __unregister_pstore_blk(major); + mutex_unlock(&pstore_blk_lock); +} +EXPORT_SYMBOL_GPL(unregister_pstore_blk); + +static void __exit pstore_blk_exit(void) +{ + mutex_lock(&pstore_blk_lock); + if (psblk_bdev) + __unregister_pstore_blk(MAJOR(psblk_bdev->bd_dev)); + mutex_unlock(&pstore_blk_lock); +} +module_exit(pstore_blk_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("WeiXiong Liao "); +MODULE_AUTHOR("Kees Cook "); +MODULE_DESCRIPTION("pstore backend for block devices"); diff --git a/include/linux/pstore_blk.h b/include/linux/pstore_blk.h new file mode 100644 index 000000000000..4501977b1336 --- /dev/null +++ b/include/linux/pstore_blk.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __PSTORE_BLK_H_ +#define __PSTORE_BLK_H_ + +#include +#include +#include + +/** + * typedef pstore_blk_panic_write_op - panic write operation to block device + * + * @buf: the data to write + * @start_sect: start sector to block device + * @sects: sectors count on buf + * + * Return: On success, zero should be returned. Others mean error. + * + * Panic write to block device must be aligned to SECTOR_SIZE. + */ +typedef int (*pstore_blk_panic_write_op)(const char *buf, sector_t start_sect, + sector_t sects); + +/** + * struct pstore_blk_info - pstore/blk registration details + * + * @major: Which major device number to support with pstore/blk + * @flags: The supported PSTORE_FLAGS_* from linux/pstore.h. + * @panic_write:The write operation only used for the panic case. + * This can be NULL, but is recommended to avoid losing + * crash data if the kernel's IO path or work queues are + * broken during a panic. + * @devt: The dev_t that pstore/blk has attached to. + * @nr_sects: Number of sectors on @devt. + * @start_sect: Starting sector on @devt. + */ +struct pstore_blk_info { + unsigned int major; + unsigned int flags; + pstore_blk_panic_write_op panic_write; + + /* Filled in by pstore/blk after registration. */ + dev_t devt; + sector_t nr_sects; + sector_t start_sect; +}; + +int register_pstore_blk(struct pstore_blk_info *info); +void unregister_pstore_blk(unsigned int major); + +#endif From patchwork Sun May 10 20:24:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287359 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=AXG0f6xO; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=eKXtZJOg; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Kwbh1lkBz9sNH for ; Mon, 11 May 2020 06:27:28 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Zp34ueaOX/Yz3wnhU0ulD8+3PZ0i6lmdROUHFnifgc4=; b=AXG0f6xOfWdcTG yeiQKl8SyfoM1z6k7kTDWsgPcyYLJUsFsuZdayMSKE2HSktjHxvlVhHDjHqxW+SMRQh6LgQetM9DL CfTDjechaE8LdFM1TRpVZ9bLKphU8WAGTIJEeZ3yXOS3IK5Rta9YOyPhmA3GsYOWqI+HJE+0rTCje o7TxgvK0EFABSEaLVhIf7uVfNLICeXUCbmes/twAUdLwXQ8hrSiuDyMBTGJNEGaXbWrOXUp43GreN bKxBI8X3N6miDWEINOaSa0L3GjjIcxP1JHseguq0D179DWA9Wj82gChtrlqL0B+x+iD44gOlosy1L poUyfdIA2oldbhnJWwHQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsXa-0007GD-Ku; Sun, 10 May 2020 20:27:14 +0000 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVH-0002WE-57 for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:54 +0000 Received: by mail-pg1-x541.google.com with SMTP id f23so2881708pgj.4 for ; Sun, 10 May 2020 13:24:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lC3zWWwpi5wheGmcJZBiqc6/+t8dKumNhD7bi+nBUvo=; b=eKXtZJOgXtR/ykv1BbS77lri4XnNwLnsa0cIsUyQZfvKy7AZNjjVkznCGgNP7xl3yc SJ5AqycXk7XXEiN6WuiBBy0J2RVDBf95+/X19SaefNhRHtrpNsdBx0tlz3yocdLgA8xb rZ2dFPXcmoRnq/iLAnnF2rMMGwJuphh0HUg/A= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lC3zWWwpi5wheGmcJZBiqc6/+t8dKumNhD7bi+nBUvo=; b=aSkjn9Bqlc3MrllHfZd/GaTuV45dM8MxII339ivpoTD9KVuCiK2u3xlqBOKqg4tBeb Q3jtLNwoKsoCFjx/reM7EVdeWJQsYd64CZxXP4DVI4DNmt1MrDC6eZgNJLfjdn3sHnat hoiteK+2JzRpGLeQgvQ38/2P4xAJTRFfTn+t7LDkHJmmWjvzl3C/isgcZwjMFPq414Pg QHg7/wDHi4CVnuVvHy+BDyfJGet16XBrtOljia0BuSJeb8w1Hi2gYAyJErwKoq9VZ7SV 3BG55KvE47rgrq8YW6HoiBZKJE32OcRh+w5Ipv0LGBZLG3ISISEft79oTPVWlTR/sb3u krlw== X-Gm-Message-State: AGi0Puab6kYyj4JjqUGEGVgN/drCtPwX813fUgfyfM+hxXTb+tRi+2vX C1CMydjUlthZi8Y3KneM7cZ2M2RHrq4= X-Google-Smtp-Source: APiQypLjhC1+A2FMCjcftbwCQiazJFPh01EJ7W3N09QK4rJuS9AiRFcvtsAQCZZjhbC8QzZzU3J76w== X-Received: by 2002:a63:30c4:: with SMTP id w187mr11745455pgw.276.1589142289880; Sun, 10 May 2020 13:24:49 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id d20sm7807279pjs.12.2020.05.10.13.24.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:45 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 10/18] pstore/zone,blk: Add support for pmsg frontend Date: Sun, 10 May 2020 13:24:28 -0700 Message-Id: <20200510202436.63222-11-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132451_360991_C0C88296 X-CRM114-Status: GOOD ( 24.79 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:541 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao Add pmsg support to pstore/blk (through pstore/zone). To enable, pmsg_size must be greater than 0 and a multiple of 4096. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-5-git-send-email-liaoweixiong@allwinnertech.com Signed-off-by: Kees Cook --- fs/pstore/Kconfig | 12 ++ fs/pstore/blk.c | 9 ++ fs/pstore/zone.c | 269 ++++++++++++++++++++++++++++++++++-- include/linux/pstore_zone.h | 2 + 4 files changed, 282 insertions(+), 10 deletions(-) diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 92ba73bd0b62..f18cd126d83f 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -224,3 +224,15 @@ config PSTORE_BLK_MAX_REASON NOTE that, both Kconfig and module parameters can configure pstore/blk, but module parameters have priority over Kconfig. + +config PSTORE_BLK_PMSG_SIZE + int "Size in Kbytes of pmsg to store" + depends on PSTORE_BLK + depends on PSTORE_PMSG + default 64 + help + This just sets size of pmsg (pmsg_size) for pstore/blk. The size is + in KB and must be a multiple of 4. + + NOTE that, both Kconfig and module parameters can configure + pstore/blk, but module parameters have priority over Kconfig. diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c index cec1fa261d1b..516a5f80d627 100644 --- a/fs/pstore/blk.c +++ b/fs/pstore/blk.c @@ -27,6 +27,14 @@ module_param(max_reason, int, 0400); MODULE_PARM_DESC(max_reason, "maximum reason for kmsg dump (default 2: Oops and Panic)"); +#if IS_ENABLED(CONFIG_PSTORE_PMSG) +static long pmsg_size = CONFIG_PSTORE_BLK_PMSG_SIZE; +#else +static long pmsg_size = -1; +#endif +module_param(pmsg_size, long, 0400); +MODULE_PARM_DESC(pmsg_size, "pmsg size in kbytes"); + /* * blkdev - the block device to use for pstore storage * @@ -132,6 +140,7 @@ static int psblk_register_do(struct pstore_device_info *dev) } verify_size(kmsg_size, 4096, dev->flags & PSTORE_FLAGS_DMESG); + verify_size(pmsg_size, 4096, dev->flags & PSTORE_FLAGS_PMSG); #undef verify_size pstore_zone_info->total_size = dev->total_size; diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c index a388c299ebb1..03dc87791c24 100644 --- a/fs/pstore/zone.c +++ b/fs/pstore/zone.c @@ -27,12 +27,14 @@ * * @sig: signature to indicate header (PSZ_SIG xor PSZONE-type value) * @datalen: length of data in @data + * @start: offset into @data where the beginning of the stored bytes begin * @data: zone data. */ struct psz_buffer { #define PSZ_SIG (0x43474244) /* DBGC */ uint32_t sig; atomic_t datalen; + atomic_t start; uint8_t data[]; }; @@ -88,9 +90,11 @@ struct pstore_zone { * struct psz_context - all about running state of pstore/zone * * @opszs: oops/panic storage zones + * @ppsz: pmsg storage zone * @kmsg_max_cnt: max count of @opszs * @kmsg_read_cnt: counter to read oops zone * @kmsg_write_cnt: counter to write + * @pmsg_read_cnt: counter to read pmsg zone * @oops_counter: counter to oops * @panic_counter: counter to panic * @recovered: whether finish recovering data from storage @@ -101,9 +105,11 @@ struct pstore_zone { */ struct psz_context { struct pstore_zone **opszs; + struct pstore_zone *ppsz; unsigned int kmsg_max_cnt; unsigned int kmsg_read_cnt; unsigned int kmsg_write_cnt; + unsigned int pmsg_read_cnt; /* * the counter should be recovered when recover. * It records the oops/panic times after burning rather than booting. @@ -143,15 +149,20 @@ static inline int buffer_datalen(struct pstore_zone *zone) return atomic_read(&zone->buffer->datalen); } +static inline int buffer_start(struct pstore_zone *zone) +{ + return atomic_read(&zone->buffer->start); +} + static inline bool is_on_panic(void) { return atomic_read(&pstore_zone_cxt.on_panic); } -static ssize_t psz_zone_read(struct pstore_zone *zone, char *buf, +static ssize_t psz_zone_read_buffer(struct pstore_zone *zone, char *buf, size_t len, unsigned long off) { - if (!buf || !zone->buffer) + if (!buf || !zone || !zone->buffer) return -EINVAL; if (off > zone->buffer_size) return -EINVAL; @@ -160,6 +171,18 @@ static ssize_t psz_zone_read(struct pstore_zone *zone, char *buf, return len; } +static int psz_zone_read_oldbuf(struct pstore_zone *zone, char *buf, + size_t len, unsigned long off) +{ + if (!buf || !zone || !zone->oldbuf) + return -EINVAL; + if (off > zone->buffer_size) + return -EINVAL; + len = min_t(size_t, len, zone->buffer_size - off); + memcpy(buf, zone->oldbuf->data + off, len); + return 0; +} + static int psz_zone_write(struct pstore_zone *zone, enum psz_flush_mode flush_mode, const char *buf, size_t len, unsigned long off) @@ -415,6 +438,93 @@ static int psz_kmsg_recover(struct psz_context *cxt) return ret; } +static int psz_recover_zone(struct psz_context *cxt, struct pstore_zone *zone) +{ + struct pstore_zone_info *info = cxt->pstore_zone_info; + struct psz_buffer *oldbuf, tmpbuf; + int ret = 0; + char *buf; + ssize_t rcnt, len, start, off; + + if (!zone || zone->oldbuf) + return 0; + + if (is_on_panic()) { + /* save data as much as possible */ + psz_flush_dirty_zone(zone); + return 0; + } + + if (unlikely(!info->read)) + return -EINVAL; + + len = sizeof(struct psz_buffer); + rcnt = info->read((char *)&tmpbuf, len, zone->off); + if (rcnt != len) { + pr_debug("read zone %s failed\n", zone->name); + return (int)rcnt < 0 ? (int)rcnt : -EIO; + } + + if (tmpbuf.sig != zone->buffer->sig) { + pr_debug("no valid data in zone %s\n", zone->name); + return 0; + } + + if (zone->buffer_size < atomic_read(&tmpbuf.datalen) || + zone->buffer_size < atomic_read(&tmpbuf.start)) { + pr_info("found overtop zone: %s: off %lld, size %zu\n", + zone->name, zone->off, zone->buffer_size); + /* just keep going */ + return 0; + } + + if (!atomic_read(&tmpbuf.datalen)) { + pr_debug("found erased zone: %s: off %lld, size %zu, datalen %d\n", + zone->name, zone->off, zone->buffer_size, + atomic_read(&tmpbuf.datalen)); + return 0; + } + + pr_debug("found nice zone: %s: off %lld, size %zu, datalen %d\n", + zone->name, zone->off, zone->buffer_size, + atomic_read(&tmpbuf.datalen)); + + len = atomic_read(&tmpbuf.datalen) + sizeof(*oldbuf); + oldbuf = kzalloc(len, GFP_KERNEL); + if (!oldbuf) + return -ENOMEM; + + memcpy(oldbuf, &tmpbuf, sizeof(*oldbuf)); + buf = (char *)oldbuf + sizeof(*oldbuf); + len = atomic_read(&oldbuf->datalen); + start = atomic_read(&oldbuf->start); + off = zone->off + sizeof(*oldbuf); + + /* get part of data */ + rcnt = info->read(buf, len - start, off + start); + if (rcnt != len - start) { + pr_err("read zone %s failed\n", zone->name); + ret = (int)rcnt < 0 ? (int)rcnt : -EIO; + goto free_oldbuf; + } + + /* get the rest of data */ + rcnt = info->read(buf + len - start, start, off); + if (rcnt != start) { + pr_err("read zone %s failed\n", zone->name); + ret = (int)rcnt < 0 ? (int)rcnt : -EIO; + goto free_oldbuf; + } + + zone->oldbuf = oldbuf; + psz_flush_dirty_zone(zone); + return 0; + +free_oldbuf: + kfree(oldbuf); + return ret; +} + /** * psz_recovery() - recover data from storage * @cxt: the context of pstore/zone @@ -434,6 +544,10 @@ static inline int psz_recovery(struct psz_context *cxt) if (ret) goto recover_fail; + ret = psz_recover_zone(cxt, cxt->ppsz); + if (ret) + goto recover_fail; + pr_debug("recover end!\n"); atomic_set(&cxt->recovered, 1); return 0; @@ -448,9 +562,17 @@ static int psz_pstore_open(struct pstore_info *psi) struct psz_context *cxt = psi->data; cxt->kmsg_read_cnt = 0; + cxt->pmsg_read_cnt = 0; return 0; } +static inline bool psz_old_ok(struct pstore_zone *zone) +{ + if (zone && zone->oldbuf && atomic_read(&zone->oldbuf->datalen)) + return true; + return false; +} + static inline bool psz_ok(struct pstore_zone *zone) { if (zone && zone->buffer && buffer_datalen(zone)) @@ -475,6 +597,25 @@ static inline int psz_kmsg_erase(struct psz_context *cxt, return psz_zone_write(zone, FLUSH_META, NULL, 0, 0); } +static inline int psz_record_erase(struct psz_context *cxt, + struct pstore_zone *zone) +{ + if (unlikely(!psz_old_ok(zone))) + return 0; + + kfree(zone->oldbuf); + zone->oldbuf = NULL; + /* + * if there are new data in zone buffer, that means the old data + * are already invalid. It is no need to flush 0 (erase) to + * block device. + */ + if (!buffer_datalen(zone)) + return psz_zone_write(zone, FLUSH_META, NULL, 0, 0); + psz_flush_dirty_zone(zone); + return 0; +} + static int psz_pstore_erase(struct pstore_record *record) { struct psz_context *cxt = record->psi->data; @@ -484,6 +625,8 @@ static int psz_pstore_erase(struct pstore_record *record) if (record->id >= cxt->kmsg_max_cnt) return -EINVAL; return psz_kmsg_erase(cxt, cxt->opszs[record->id], record); + case PSTORE_TYPE_PMSG: + return psz_record_erase(cxt, cxt->ppsz); default: return -EINVAL; } @@ -504,8 +647,10 @@ static void psz_write_kmsg_hdr(struct pstore_zone *zone, hdr->reason = record->reason; if (hdr->reason == KMSG_DUMP_OOPS) hdr->counter = ++cxt->oops_counter; - else + else if (hdr->reason == KMSG_DUMP_PANIC) hdr->counter = ++cxt->panic_counter; + else + hdr->counter = 0; } static inline int notrace psz_kmsg_write_record(struct psz_context *cxt, @@ -555,6 +700,53 @@ static int notrace psz_kmsg_write(struct psz_context *cxt, return 0; } +static int notrace psz_record_write(struct pstore_zone *zone, + struct pstore_record *record) +{ + size_t start, rem; + int cnt = record->size; + bool is_full_data = false; + char *buf = record->buf; + + if (!zone || !record) + return -ENOSPC; + + if (atomic_read(&zone->buffer->datalen) >= zone->buffer_size) + is_full_data = true; + + if (unlikely(cnt > zone->buffer_size)) { + buf += cnt - zone->buffer_size; + cnt = zone->buffer_size; + } + + start = buffer_start(zone); + rem = zone->buffer_size - start; + if (unlikely(rem < cnt)) { + psz_zone_write(zone, FLUSH_PART, buf, rem, start); + buf += rem; + cnt -= rem; + start = 0; + is_full_data = true; + } + + atomic_set(&zone->buffer->start, cnt + start); + psz_zone_write(zone, FLUSH_PART, buf, cnt, start); + + /** + * psz_zone_write will set datalen as start + cnt. + * It work if actual data length lesser than buffer size. + * If data length greater than buffer size, pmsg will rewrite to + * beginning of zone, which make buffer->datalen wrongly. + * So we should reset datalen as buffer size once actual data length + * greater than buffer size. + */ + if (is_full_data) { + atomic_set(&zone->buffer->datalen, zone->buffer_size); + psz_zone_write(zone, FLUSH_META, NULL, 0, 0); + } + return 0; +} + static int notrace psz_pstore_write(struct pstore_record *record) { struct psz_context *cxt = record->psi->data; @@ -566,6 +758,8 @@ static int notrace psz_pstore_write(struct pstore_record *record) switch (record->type) { case PSTORE_TYPE_DMESG: return psz_kmsg_write(cxt, record); + case PSTORE_TYPE_PMSG: + return psz_record_write(cxt->ppsz, record); default: return -EINVAL; } @@ -581,6 +775,13 @@ static struct pstore_zone *psz_read_next_zone(struct psz_context *cxt) return zone; } + if (cxt->pmsg_read_cnt == 0) { + cxt->pmsg_read_cnt++; + zone = cxt->ppsz; + if (psz_old_ok(zone)) + return zone; + } + return NULL; } @@ -631,7 +832,7 @@ static ssize_t psz_kmsg_read(struct pstore_zone *zone, return -ENOMEM; } - size = psz_zone_read(zone, record->buf + hlen, size, + size = psz_zone_read_buffer(zone, record->buf + hlen, size, sizeof(struct psz_kmsg_header)); if (unlikely(size < 0)) { kfree(record->buf); @@ -641,6 +842,32 @@ static ssize_t psz_kmsg_read(struct pstore_zone *zone, return size + hlen; } +static ssize_t psz_record_read(struct pstore_zone *zone, + struct pstore_record *record) +{ + size_t len; + struct psz_buffer *buf; + + if (!zone || !record) + return -ENOSPC; + + buf = (struct psz_buffer *)zone->oldbuf; + if (!buf) + return -ENOMSG; + + len = atomic_read(&buf->datalen); + record->buf = kmalloc(len, GFP_KERNEL); + if (!record->buf) + return -ENOMEM; + + if (unlikely(psz_zone_read_oldbuf(zone, record->buf, len, 0))) { + kfree(record->buf); + return -ENOMSG; + } + + return len; +} + static ssize_t psz_pstore_read(struct pstore_record *record) { struct psz_context *cxt = record->psi->data; @@ -665,6 +892,9 @@ static ssize_t psz_pstore_read(struct pstore_record *record) readop = psz_kmsg_read; record->id = cxt->kmsg_read_cnt - 1; break; + case PSTORE_TYPE_PMSG: + readop = psz_record_read; + break; default: goto next_zone; } @@ -720,6 +950,8 @@ static void psz_free_all_zones(struct psz_context *cxt) { if (cxt->opszs) psz_free_zones(&cxt->opszs, &cxt->kmsg_max_cnt); + if (cxt->ppsz) + psz_free_zone(&cxt->ppsz); } static struct pstore_zone *psz_init_zone(enum pstore_type_id type, @@ -753,8 +985,10 @@ static struct pstore_zone *psz_init_zone(enum pstore_type_id type, zone->type = type; zone->buffer_size = size - sizeof(struct psz_buffer); zone->buffer->sig = type ^ PSZ_SIG; + zone->oldbuf = NULL; atomic_set(&zone->dirty, 0); atomic_set(&zone->buffer->datalen, 0); + atomic_set(&zone->buffer->start, 0); *off += size; @@ -809,19 +1043,28 @@ static int psz_alloc_zones(struct psz_context *cxt) struct pstore_zone_info *info = cxt->pstore_zone_info; loff_t off = 0; int err; - size_t size; + size_t off_size = 0; + + off_size += info->pmsg_size; + cxt->ppsz = psz_init_zone(PSTORE_TYPE_PMSG, &off, info->pmsg_size); + if (IS_ERR(cxt->ppsz)) { + err = PTR_ERR(cxt->ppsz); + cxt->ppsz = NULL; + goto free_out; + } - size = info->total_size; - cxt->opszs = psz_init_zones(PSTORE_TYPE_DMESG, &off, size, + cxt->opszs = psz_init_zones(PSTORE_TYPE_DMESG, &off, + info->total_size - off_size, info->kmsg_size, &cxt->kmsg_max_cnt); if (IS_ERR(cxt->opszs)) { err = PTR_ERR(cxt->opszs); cxt->opszs = NULL; - goto fail_out; + goto free_out; } return 0; -fail_out: +free_out: + psz_free_all_zones(cxt); return err; } @@ -844,7 +1087,7 @@ int register_pstore_zone(struct pstore_zone_info *info) return -EINVAL; } - if (!info->kmsg_size) { + if (!info->kmsg_size && !info->pmsg_size) { pr_warn("at least one record size must be non-zero\n"); return -EINVAL; } @@ -866,6 +1109,7 @@ int register_pstore_zone(struct pstore_zone_info *info) check_size(total_size, 4096); check_size(kmsg_size, SECTOR_SIZE); + check_size(pmsg_size, SECTOR_SIZE); #undef check_size @@ -891,6 +1135,7 @@ int register_pstore_zone(struct pstore_zone_info *info) pr_debug("register %s with properties:\n", info->name); pr_debug("\ttotal size : %ld Bytes\n", info->total_size); pr_debug("\tkmsg size : %ld Bytes\n", info->kmsg_size); + pr_debug("\tpmsg size : %ld Bytes\n", info->pmsg_size); err = psz_alloc_zones(cxt); if (err) { @@ -920,6 +1165,10 @@ int register_pstore_zone(struct pstore_zone_info *info) pr_cont(",panic_write"); pr_cont(")"); } + if (info->pmsg_size) { + cxt->pstore.flags |= PSTORE_FLAGS_PMSG; + pr_cont(" pmsg"); + } pr_cont("\n"); err = pstore_register(&cxt->pstore); diff --git a/include/linux/pstore_zone.h b/include/linux/pstore_zone.h index eb005d9ae40c..29c367a3bd80 100644 --- a/include/linux/pstore_zone.h +++ b/include/linux/pstore_zone.h @@ -17,6 +17,7 @@ typedef ssize_t (*pstore_zone_write_op)(const char *, size_t, loff_t); * @kmsg_size: The size of oops/panic zone. Zero means disabled, otherwise, * it must be multiple of SECTOR_SIZE(512 Bytes). * @max_reason: Maximum kmsg dump reason to store. + * @pmsg_size: The size of pmsg zone which is the same as @kmsg_size. * @read: The general read operation. Both of the function parameters * @size and @offset are relative value to storage. * On success, the number of bytes should be returned, others @@ -33,6 +34,7 @@ struct pstore_zone_info { unsigned long total_size; unsigned long kmsg_size; int max_reason; + unsigned long pmsg_size; pstore_zone_read_op read; pstore_zone_write_op write; pstore_zone_write_op panic_write; From patchwork Sun May 10 20:24:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287364 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=nCK7TVpP; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=PT992yl1; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwdH2lVqz9sSd for ; Mon, 11 May 2020 06:28:51 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=EGjiKGhWKdzI0zmCR6SBGlthPQD1iKC6/RMWzLkBLR4=; b=nCK7TVpPH6OarL oN8U7WjNd49kk02yIG+QRdthvbGdAhUfQdwDum0QHuTnPfSa8HCT6t8VTT45HKBOFpmCQ/iijUeIk 7LwiF8+IUnyFtipQtHEw0YU12YQEWhvcu04lKPi+8Xr/sj7ZULkt8rREJ5e/cw9tM7low/3dkfbmj HqbUhtgp6HBt8tNkUuZc2EGsej2bL9UlgCquMa+W31+t1Q5NLcfa5upHYZaNMXAkgvmlX+JK+gTE5 WK2MH5vCbqkQswjtmNXIVvbjSTw+XU7sSDlfaVWOhymm8JrCHYi6wxFFXBizjnVvkdxiZVQM+KOyB 0FNv2odgpeG8Mh0zIH8Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsZ4-0000An-SB; Sun, 10 May 2020 20:28:46 +0000 Received: from mail-pj1-x1044.google.com ([2607:f8b0:4864:20::1044]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVI-0002Xg-Ma for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:59 +0000 Received: by mail-pj1-x1044.google.com with SMTP id t40so6723158pjb.3 for ; Sun, 10 May 2020 13:24:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FmKTLbovjfKjTN0vHBWlO6lvLE5eqFfmlm1KjpD+FQg=; b=PT992yl1YtXSgolejvEUef7UYpXJZjgz2ToItmqYoEKNVRbni8EEDoAmW4b8FmbdbW IrGyQgQMZQmshhqu3q49psD4a7Snwj+jhXAlLSwM/QwAeV9RbwHlIosSMNq2Lw9A2qsH NJP7XcklGp3FY1q5Jn/ZlPZjUKW1UmUgjlfXc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FmKTLbovjfKjTN0vHBWlO6lvLE5eqFfmlm1KjpD+FQg=; b=BMtmGKJHjFcLVac7nVraR7XvJSXI4UbI/b0F9RY6LYHA/gXapSAcMYaefJQPxaSOD/ mRo2tHnYf6T9xpI7Ebu4mmqE4/4yqcIoNbQAboUQfs942fPrko77H3XafaY5yoIv2f+3 Vr9XQjzcImD9ebpNZ2ucrsPVEDljoEhie0dt9+WJt8K/oG9C+kKeFWkbsE/I4RvLv50e LWilZpw1p2unKrT5yND0qZ6w6iwLZXRK2GGI1FA3SuBXqyVwdGWJshnpi1mF7GFk2Fzl MbyHL6Auv3H60tfdi7xIYjtVVW6TfjrA2nl1O/qn4XvaPg6CgPGSDSB6ieUu01brmEB2 aNDg== X-Gm-Message-State: AGi0PuagEvfs47DFYTEa3VliCg7C4h8f7zjYvQQRkL33meNPsjP4L0F5 dYWasikc1Q4PdfBu/mlyhYzn7g== X-Google-Smtp-Source: APiQypJR2fHsTXN9co4qUFxFypu7mvJnIIxnJvBdLNWTiL2jmJ9dvYn4I9mX5VNCESY45A2lN4bu/A== X-Received: by 2002:a17:90a:9f8a:: with SMTP id o10mr18705310pjp.118.1589142291060; Sun, 10 May 2020 13:24:51 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id x10sm6215290pgq.79.2020.05.10.13.24.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:45 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 11/18] pstore/zone,blk: Add console frontend support Date: Sun, 10 May 2020 13:24:29 -0700 Message-Id: <20200510202436.63222-12-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132452_868731_66DC1A2F X-CRM114-Status: GOOD ( 23.54 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1044 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao Support backend for console. To enable console backend, just make console_size be greater than 0 and a multiple of 4096. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-6-git-send-email-liaoweixiong@allwinnertech.com Signed-off-by: Kees Cook --- fs/pstore/Kconfig | 12 ++++++ fs/pstore/blk.c | 12 +++++- fs/pstore/zone.c | 83 ++++++++++++++++++++++++++++++++++--- include/linux/pstore_zone.h | 4 +- 4 files changed, 103 insertions(+), 8 deletions(-) diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index f18cd126d83f..f1484f751c5e 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -236,3 +236,15 @@ config PSTORE_BLK_PMSG_SIZE NOTE that, both Kconfig and module parameters can configure pstore/blk, but module parameters have priority over Kconfig. + +config PSTORE_BLK_CONSOLE_SIZE + int "Size in Kbytes of console to store" + depends on PSTORE_BLK + depends on PSTORE_CONSOLE + default 64 + help + This just sets size of console (console_size) for pstore/blk. The + size is in KB and must be a multiple of 4. + + NOTE that, both Kconfig and module parameters can configure + pstore/blk, but module parameters have priority over Kconfig. diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c index 516a5f80d627..145e00bd7de9 100644 --- a/fs/pstore/blk.c +++ b/fs/pstore/blk.c @@ -35,6 +35,14 @@ static long pmsg_size = -1; module_param(pmsg_size, long, 0400); MODULE_PARM_DESC(pmsg_size, "pmsg size in kbytes"); +#if IS_ENABLED(CONFIG_PSTORE_CONSOLE) +static long console_size = CONFIG_PSTORE_BLK_CONSOLE_SIZE; +#else +static long console_size = -1; +#endif +module_param(console_size, long, 0400); +MODULE_PARM_DESC(console_size, "console size in kbytes"); + /* * blkdev - the block device to use for pstore storage * @@ -90,7 +98,8 @@ static struct bdev_info { * whole disk). * On success, the number of bytes should be returned, others * means error. - * @write: The same as @read. + * @write: The same as @read, but the following error number: + * -EBUSY means try to write again later. * @panic_write:The write operation only used for panic case. It's optional * if you do not care panic log. The parameters and return value * are the same as @read. @@ -141,6 +150,7 @@ static int psblk_register_do(struct pstore_device_info *dev) verify_size(kmsg_size, 4096, dev->flags & PSTORE_FLAGS_DMESG); verify_size(pmsg_size, 4096, dev->flags & PSTORE_FLAGS_PMSG); + verify_size(console_size, 4096, dev->flags & PSTORE_FLAGS_CONSOLE); #undef verify_size pstore_zone_info->total_size = dev->total_size; diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c index 03dc87791c24..f3bd6a7dc06d 100644 --- a/fs/pstore/zone.c +++ b/fs/pstore/zone.c @@ -91,10 +91,12 @@ struct pstore_zone { * * @opszs: oops/panic storage zones * @ppsz: pmsg storage zone + * @cpsz: console storage zone * @kmsg_max_cnt: max count of @opszs * @kmsg_read_cnt: counter to read oops zone * @kmsg_write_cnt: counter to write * @pmsg_read_cnt: counter to read pmsg zone + * @console_read_cnt: counter to read console zone * @oops_counter: counter to oops * @panic_counter: counter to panic * @recovered: whether finish recovering data from storage @@ -106,10 +108,12 @@ struct pstore_zone { struct psz_context { struct pstore_zone **opszs; struct pstore_zone *ppsz; + struct pstore_zone *cpsz; unsigned int kmsg_max_cnt; unsigned int kmsg_read_cnt; unsigned int kmsg_write_cnt; unsigned int pmsg_read_cnt; + unsigned int console_read_cnt; /* * the counter should be recovered when recover. * It records the oops/panic times after burning rather than booting. @@ -129,6 +133,9 @@ struct psz_context { }; static struct psz_context pstore_zone_cxt; +static void psz_flush_all_dirty_zones(struct work_struct *); +static DECLARE_DELAYED_WORK(psz_cleaner, psz_flush_all_dirty_zones); + /** * enum psz_flush_mode - flush mode for psz_zone_write() * @@ -237,6 +244,9 @@ static int psz_zone_write(struct pstore_zone *zone, return 0; dirty: atomic_set(&zone->dirty, true); + /* flush dirty zones nicely */ + if (wcnt == -EBUSY && !is_on_panic()) + schedule_delayed_work(&psz_cleaner, msecs_to_jiffies(500)); return -EBUSY; } @@ -293,6 +303,21 @@ static int psz_move_zone(struct pstore_zone *old, struct pstore_zone *new) return 0; } +static void psz_flush_all_dirty_zones(struct work_struct *work) +{ + struct psz_context *cxt = &pstore_zone_cxt; + int ret = 0; + + if (cxt->ppsz) + ret |= psz_flush_dirty_zone(cxt->ppsz); + if (cxt->cpsz) + ret |= psz_flush_dirty_zone(cxt->cpsz); + if (cxt->opszs) + ret |= psz_flush_dirty_zones(cxt->opszs, cxt->kmsg_max_cnt); + if (ret && cxt->pstore_zone_info) + schedule_delayed_work(&psz_cleaner, msecs_to_jiffies(1000)); +} + static int psz_kmsg_recover_data(struct psz_context *cxt) { struct pstore_zone_info *info = cxt->pstore_zone_info; @@ -548,6 +573,10 @@ static inline int psz_recovery(struct psz_context *cxt) if (ret) goto recover_fail; + ret = psz_recover_zone(cxt, cxt->cpsz); + if (ret) + goto recover_fail; + pr_debug("recover end!\n"); atomic_set(&cxt->recovered, 1); return 0; @@ -563,6 +592,7 @@ static int psz_pstore_open(struct pstore_info *psi) cxt->kmsg_read_cnt = 0; cxt->pmsg_read_cnt = 0; + cxt->console_read_cnt = 0; return 0; } @@ -627,8 +657,9 @@ static int psz_pstore_erase(struct pstore_record *record) return psz_kmsg_erase(cxt, cxt->opszs[record->id], record); case PSTORE_TYPE_PMSG: return psz_record_erase(cxt, cxt->ppsz); - default: - return -EINVAL; + case PSTORE_TYPE_CONSOLE: + return psz_record_erase(cxt, cxt->cpsz); + default: return -EINVAL; } } @@ -691,9 +722,10 @@ static int notrace psz_kmsg_write(struct psz_context *cxt, return -ENOSPC; ret = psz_kmsg_write_record(cxt, record); - if (!ret) { - pr_debug("try to flush other dirty oops zones\n"); - psz_flush_dirty_zones(cxt->opszs, cxt->kmsg_max_cnt); + if (!ret && is_on_panic()) { + /* ensure all data are flushed to storage when panic */ + pr_debug("try to flush other dirty zones\n"); + psz_flush_all_dirty_zones(NULL); } /* always return 0 as we had handled it on buffer */ @@ -755,9 +787,18 @@ static int notrace psz_pstore_write(struct pstore_record *record) record->reason == KMSG_DUMP_PANIC) atomic_set(&cxt->on_panic, 1); + /* + * if on panic, do not write except panic records + * Fix case that panic_write prints log which wakes up console backend. + */ + if (is_on_panic() && record->type != PSTORE_TYPE_DMESG) + return -EBUSY; + switch (record->type) { case PSTORE_TYPE_DMESG: return psz_kmsg_write(cxt, record); + case PSTORE_TYPE_CONSOLE: + return psz_record_write(cxt->cpsz, record); case PSTORE_TYPE_PMSG: return psz_record_write(cxt->ppsz, record); default: @@ -782,6 +823,13 @@ static struct pstore_zone *psz_read_next_zone(struct psz_context *cxt) return zone; } + if (cxt->console_read_cnt == 0) { + cxt->console_read_cnt++; + zone = cxt->cpsz; + if (psz_old_ok(zone)) + return zone; + } + return NULL; } @@ -892,6 +940,8 @@ static ssize_t psz_pstore_read(struct pstore_record *record) readop = psz_kmsg_read; record->id = cxt->kmsg_read_cnt - 1; break; + case PSTORE_TYPE_CONSOLE: + fallthrough; case PSTORE_TYPE_PMSG: readop = psz_record_read; break; @@ -952,6 +1002,8 @@ static void psz_free_all_zones(struct psz_context *cxt) psz_free_zones(&cxt->opszs, &cxt->kmsg_max_cnt); if (cxt->ppsz) psz_free_zone(&cxt->ppsz); + if (cxt->cpsz) + psz_free_zone(&cxt->cpsz); } static struct pstore_zone *psz_init_zone(enum pstore_type_id type, @@ -1053,6 +1105,15 @@ static int psz_alloc_zones(struct psz_context *cxt) goto free_out; } + off_size += info->console_size; + cxt->cpsz = psz_init_zone(PSTORE_TYPE_CONSOLE, &off, + info->console_size); + if (IS_ERR(cxt->cpsz)) { + err = PTR_ERR(cxt->cpsz); + cxt->cpsz = NULL; + goto free_out; + } + cxt->opszs = psz_init_zones(PSTORE_TYPE_DMESG, &off, info->total_size - off_size, info->kmsg_size, &cxt->kmsg_max_cnt); @@ -1087,7 +1148,7 @@ int register_pstore_zone(struct pstore_zone_info *info) return -EINVAL; } - if (!info->kmsg_size && !info->pmsg_size) { + if (!info->kmsg_size && !info->pmsg_size && !info->console_size) { pr_warn("at least one record size must be non-zero\n"); return -EINVAL; } @@ -1110,6 +1171,7 @@ int register_pstore_zone(struct pstore_zone_info *info) check_size(total_size, 4096); check_size(kmsg_size, SECTOR_SIZE); check_size(pmsg_size, SECTOR_SIZE); + check_size(console_size, SECTOR_SIZE); #undef check_size @@ -1136,6 +1198,7 @@ int register_pstore_zone(struct pstore_zone_info *info) pr_debug("\ttotal size : %ld Bytes\n", info->total_size); pr_debug("\tkmsg size : %ld Bytes\n", info->kmsg_size); pr_debug("\tpmsg size : %ld Bytes\n", info->pmsg_size); + pr_debug("\tconsole size : %ld Bytes\n", info->console_size); err = psz_alloc_zones(cxt); if (err) { @@ -1169,6 +1232,10 @@ int register_pstore_zone(struct pstore_zone_info *info) cxt->pstore.flags |= PSTORE_FLAGS_PMSG; pr_cont(" pmsg"); } + if (info->console_size) { + cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE; + pr_cont(" console"); + } pr_cont("\n"); err = pstore_register(&cxt->pstore); @@ -1210,6 +1277,10 @@ void unregister_pstore_zone(struct pstore_zone_info *info) /* Stop incoming writes from pstore. */ pstore_unregister(&cxt->pstore); + /* Flush any pending writes. */ + psz_flush_all_dirty_zones(NULL); + flush_delayed_work(&psz_cleaner); + /* Clean up allocations. */ kfree(cxt->pstore.buf); cxt->pstore.buf = NULL; diff --git a/include/linux/pstore_zone.h b/include/linux/pstore_zone.h index 29c367a3bd80..904ee67f4ba2 100644 --- a/include/linux/pstore_zone.h +++ b/include/linux/pstore_zone.h @@ -18,11 +18,12 @@ typedef ssize_t (*pstore_zone_write_op)(const char *, size_t, loff_t); * it must be multiple of SECTOR_SIZE(512 Bytes). * @max_reason: Maximum kmsg dump reason to store. * @pmsg_size: The size of pmsg zone which is the same as @kmsg_size. + * @console_size:The size of console zone which is the same as @kmsg_size. * @read: The general read operation. Both of the function parameters * @size and @offset are relative value to storage. * On success, the number of bytes should be returned, others * means error. - * @write: The same as @read. + * @write: The same as @read, but -EBUSY means try to write again later. * @panic_write:The write operation only used for panic case. It's optional * if you do not care panic log. The parameters and return value * are the same as @read. @@ -35,6 +36,7 @@ struct pstore_zone_info { unsigned long kmsg_size; int max_reason; unsigned long pmsg_size; + unsigned long console_size; pstore_zone_read_op read; pstore_zone_write_op write; pstore_zone_write_op panic_write; From patchwork Sun May 10 20:24:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287365 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=NWssl6Sv; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=R841LBMl; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Kwdt43kgz9sNH for ; Mon, 11 May 2020 06:29:22 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=qU3vB9ut3ogxs6iRXLb7kVdr99D2IQup3LUl+uTa6UI=; b=NWssl6Svw5uUQT zPz1MYlrnnfYwPTy+gcP/aoSv4tg87oZt+LWdPRRrWkDH3soUOfvz8iZ/n/vxB9rR2XkwqjBK2PdX HgSbYN8qSknfe++Wv/Jn0wDyxAL2a8uHPg5aWEmZfBajDjk05eDvwPZ7GB5lDTGOPk8oyN8lLjlJv eBDFRJbYi0tR1B6boUcB/iCFtV9XAfIys9bL8OVnuV/MlEaXj0BErjYzOsQicAQo+s0K16CcA6Ldv jQwTQQgJKqohKlDCJxaVKtBjoVpUtnrQYvCHFSWQc+wMwYHRuWHVFo7fIgkYsSBAlO4LvMz7E0j2w VXYSPZCo4+VdIxICNKUw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsZN-0000Qc-GV; Sun, 10 May 2020 20:29:05 +0000 Received: from mail-pj1-x1041.google.com ([2607:f8b0:4864:20::1041]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVJ-0002YK-2w for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:59 +0000 Received: by mail-pj1-x1041.google.com with SMTP id t40so6723165pjb.3 for ; Sun, 10 May 2020 13:24:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=LYCp84ZPSyDNpS0LsIDxWQHJqbs/k4mYW7FnHvCsWl8=; b=R841LBMlwg2X8Gf1WiPOLNQInaeSZAkK8XzstORQxb+V+Y7/A0cx56qOuC3qarxiEe D1d/k6nF0bHX3iCFMjwc8h37LE2AXrlsD6ULo9P6ASJ722APLcvxYIandrWOPrBU89YM yLy/FfwyjMLMkZVE29JvAtwVw5hOM5xZKxpME= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LYCp84ZPSyDNpS0LsIDxWQHJqbs/k4mYW7FnHvCsWl8=; b=Ppmq8tJPxSG5prGjuUfwKl0awKSjEB1vHKU/xFlSF3VbLuMJV3CQO1NWy87eBVFJRK SjvFJovz6gv0cVXXgunFJbfzaD00M0tUxaoJL/ahOh01MO/lVJ9j0bSuCCLhzUEwYQxQ 4up7FvpQ8cLnTtDgV+w+UjXQQt8I3H68LMPZVkN1UQp7b0+oHKwMgKs36DX7SaoeSxUD ZSE6eOosn5FmrWYNfrD2izAKpEdHC5VLDaWX0BCgvqvWZD5rejn8pVs+xqVxoAi5o4Bb qpYc1Nn8Qt2M8uVOI6iKzvNIh7bCk6/6g3RQzMN5l6sQTfHrKzKuHDf88BQLIiP/GXfF zpYw== X-Gm-Message-State: AGi0Pubr+yWP07ToZcFnIX0HWHzInwsccKsmF82G0rgjg8u3+hay8uhi bxdpivbIsNDRVPeXbOgXKRQzIw== X-Google-Smtp-Source: APiQypI+jajhgiptq5KxrYXzEpqNCSV5CDJA6VCZgkIIedUB7Zny7L75D7Rd8KStAcsPOlMScnoJcw== X-Received: by 2002:a17:90a:f108:: with SMTP id cc8mr18726362pjb.198.1589142291725; Sun, 10 May 2020 13:24:51 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id q2sm7466964pfl.174.2020.05.10.13.24.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:45 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 12/18] pstore/zone,blk: Add ftrace frontend support Date: Sun, 10 May 2020 13:24:30 -0700 Message-Id: <20200510202436.63222-13-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132453_186363_FBE65AF7 X-CRM114-Status: GOOD ( 22.64 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1041 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao Support backend for ftrace. To enable ftrace backend, just make ftrace_size be greater than 0 and a multiple of 4096. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-7-git-send-email-liaoweixiong@allwinnertech.com Signed-off-by: Kees Cook --- fs/pstore/Kconfig | 12 ++++ fs/pstore/blk.c | 9 +++ fs/pstore/zone.c | 113 +++++++++++++++++++++++++++++++++++- include/linux/pstore_zone.h | 2 + 4 files changed, 135 insertions(+), 1 deletion(-) diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index f1484f751c5e..16a0440d8d5a 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -248,3 +248,15 @@ config PSTORE_BLK_CONSOLE_SIZE NOTE that, both Kconfig and module parameters can configure pstore/blk, but module parameters have priority over Kconfig. + +config PSTORE_BLK_FTRACE_SIZE + int "Size in Kbytes of ftarce to store" + depends on PSTORE_BLK + depends on PSTORE_FTRACE + default 64 + help + This just sets size of ftrace (ftrace_size) for pstore/blk. The + size is in KB and must be a multiple of 4. + + NOTE that, both Kconfig and module parameters can configure + pstore/blk, but module parameters have priority over Kconfig. diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c index 145e00bd7de9..e45937e3517c 100644 --- a/fs/pstore/blk.c +++ b/fs/pstore/blk.c @@ -43,6 +43,14 @@ static long console_size = -1; module_param(console_size, long, 0400); MODULE_PARM_DESC(console_size, "console size in kbytes"); +#if IS_ENABLED(CONFIG_PSTORE_FTRACE) +static long ftrace_size = CONFIG_PSTORE_BLK_FTRACE_SIZE; +#else +static long ftrace_size = -1; +#endif +module_param(ftrace_size, long, 0400); +MODULE_PARM_DESC(ftrace_size, "ftrace size in kbytes"); + /* * blkdev - the block device to use for pstore storage * @@ -151,6 +159,7 @@ static int psblk_register_do(struct pstore_device_info *dev) verify_size(kmsg_size, 4096, dev->flags & PSTORE_FLAGS_DMESG); verify_size(pmsg_size, 4096, dev->flags & PSTORE_FLAGS_PMSG); verify_size(console_size, 4096, dev->flags & PSTORE_FLAGS_CONSOLE); + verify_size(ftrace_size, 4096, dev->flags & PSTORE_FLAGS_FTRACE); #undef verify_size pstore_zone_info->total_size = dev->total_size; diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c index f3bd6a7dc06d..45c0a422f1de 100644 --- a/fs/pstore/zone.c +++ b/fs/pstore/zone.c @@ -92,11 +92,14 @@ struct pstore_zone { * @opszs: oops/panic storage zones * @ppsz: pmsg storage zone * @cpsz: console storage zone + * @fpszs: ftrace storage zones * @kmsg_max_cnt: max count of @opszs * @kmsg_read_cnt: counter to read oops zone * @kmsg_write_cnt: counter to write * @pmsg_read_cnt: counter to read pmsg zone * @console_read_cnt: counter to read console zone + * @ftrace_max_cnt: max count of @fpszs + * @ftrace_read_cnt: counter to read ftrace zone * @oops_counter: counter to oops * @panic_counter: counter to panic * @recovered: whether finish recovering data from storage @@ -109,11 +112,14 @@ struct psz_context { struct pstore_zone **opszs; struct pstore_zone *ppsz; struct pstore_zone *cpsz; + struct pstore_zone **fpszs; unsigned int kmsg_max_cnt; unsigned int kmsg_read_cnt; unsigned int kmsg_write_cnt; unsigned int pmsg_read_cnt; unsigned int console_read_cnt; + unsigned int ftrace_max_cnt; + unsigned int ftrace_read_cnt; /* * the counter should be recovered when recover. * It records the oops/panic times after burning rather than booting. @@ -314,6 +320,8 @@ static void psz_flush_all_dirty_zones(struct work_struct *work) ret |= psz_flush_dirty_zone(cxt->cpsz); if (cxt->opszs) ret |= psz_flush_dirty_zones(cxt->opszs, cxt->kmsg_max_cnt); + if (cxt->fpszs) + ret |= psz_flush_dirty_zones(cxt->fpszs, cxt->ftrace_max_cnt); if (ret && cxt->pstore_zone_info) schedule_delayed_work(&psz_cleaner, msecs_to_jiffies(1000)); } @@ -550,6 +558,31 @@ static int psz_recover_zone(struct psz_context *cxt, struct pstore_zone *zone) return ret; } +static int psz_recover_zones(struct psz_context *cxt, + struct pstore_zone **zones, unsigned int cnt) +{ + int ret; + unsigned int i; + struct pstore_zone *zone; + + if (!zones) + return 0; + + for (i = 0; i < cnt; i++) { + zone = zones[i]; + if (unlikely(!zone)) + continue; + ret = psz_recover_zone(cxt, zone); + if (ret) + goto recover_fail; + } + + return 0; +recover_fail: + pr_debug("recover %s[%u] failed\n", zone->name, i); + return ret; +} + /** * psz_recovery() - recover data from storage * @cxt: the context of pstore/zone @@ -577,6 +610,10 @@ static inline int psz_recovery(struct psz_context *cxt) if (ret) goto recover_fail; + ret = psz_recover_zones(cxt, cxt->fpszs, cxt->ftrace_max_cnt); + if (ret) + goto recover_fail; + pr_debug("recover end!\n"); atomic_set(&cxt->recovered, 1); return 0; @@ -593,6 +630,7 @@ static int psz_pstore_open(struct pstore_info *psi) cxt->kmsg_read_cnt = 0; cxt->pmsg_read_cnt = 0; cxt->console_read_cnt = 0; + cxt->ftrace_read_cnt = 0; return 0; } @@ -659,6 +697,10 @@ static int psz_pstore_erase(struct pstore_record *record) return psz_record_erase(cxt, cxt->ppsz); case PSTORE_TYPE_CONSOLE: return psz_record_erase(cxt, cxt->cpsz); + case PSTORE_TYPE_FTRACE: + if (record->id >= cxt->ftrace_max_cnt) + return -EINVAL; + return psz_record_erase(cxt, cxt->fpszs[record->id]); default: return -EINVAL; } } @@ -801,6 +843,13 @@ static int notrace psz_pstore_write(struct pstore_record *record) return psz_record_write(cxt->cpsz, record); case PSTORE_TYPE_PMSG: return psz_record_write(cxt->ppsz, record); + case PSTORE_TYPE_FTRACE: { + int zonenum = smp_processor_id(); + + if (!cxt->fpszs) + return -ENOSPC; + return psz_record_write(cxt->fpszs[zonenum], record); + } default: return -EINVAL; } @@ -816,6 +865,14 @@ static struct pstore_zone *psz_read_next_zone(struct psz_context *cxt) return zone; } + if (cxt->ftrace_read_cnt < cxt->ftrace_max_cnt) + /* + * No need psz_old_ok(). Let psz_ftrace_read() do so for + * combination. psz_ftrace_read() should traverse over + * all zones in case of some zone without data. + */ + return cxt->fpszs[cxt->ftrace_read_cnt++]; + if (cxt->pmsg_read_cnt == 0) { cxt->pmsg_read_cnt++; zone = cxt->ppsz; @@ -890,6 +947,37 @@ static ssize_t psz_kmsg_read(struct pstore_zone *zone, return size + hlen; } +/* try to combine all ftrace zones */ +static ssize_t psz_ftrace_read(struct pstore_zone *zone, + struct pstore_record *record) +{ + struct psz_context *cxt = record->psi->data; + struct psz_buffer *buf; + int ret; + + if (!zone || !record) + return -ENOSPC; + + if (!psz_old_ok(zone)) + goto out; + + buf = (struct psz_buffer *)zone->oldbuf; + if (!buf) + return -ENOMSG; + + ret = pstore_ftrace_combine_log(&record->buf, &record->size, + (char *)buf->data, atomic_read(&buf->datalen)); + if (unlikely(ret)) + return ret; + +out: + if (cxt->ftrace_read_cnt < cxt->ftrace_max_cnt) + /* then, read next ftrace zone */ + return -ENOMSG; + record->id = 0; + return record->size ? record->size : -ENOMSG; +} + static ssize_t psz_record_read(struct pstore_zone *zone, struct pstore_record *record) { @@ -940,6 +1028,9 @@ static ssize_t psz_pstore_read(struct pstore_record *record) readop = psz_kmsg_read; record->id = cxt->kmsg_read_cnt - 1; break; + case PSTORE_TYPE_FTRACE: + readop = psz_ftrace_read; + break; case PSTORE_TYPE_CONSOLE: fallthrough; case PSTORE_TYPE_PMSG: @@ -1004,6 +1095,8 @@ static void psz_free_all_zones(struct psz_context *cxt) psz_free_zone(&cxt->ppsz); if (cxt->cpsz) psz_free_zone(&cxt->cpsz); + if (cxt->fpszs) + psz_free_zones(&cxt->fpszs, &cxt->ftrace_max_cnt); } static struct pstore_zone *psz_init_zone(enum pstore_type_id type, @@ -1114,6 +1207,17 @@ static int psz_alloc_zones(struct psz_context *cxt) goto free_out; } + off_size += info->ftrace_size; + cxt->fpszs = psz_init_zones(PSTORE_TYPE_FTRACE, &off, + info->ftrace_size, + info->ftrace_size / nr_cpu_ids, + &cxt->ftrace_max_cnt); + if (IS_ERR(cxt->fpszs)) { + err = PTR_ERR(cxt->fpszs); + cxt->fpszs = NULL; + goto free_out; + } + cxt->opszs = psz_init_zones(PSTORE_TYPE_DMESG, &off, info->total_size - off_size, info->kmsg_size, &cxt->kmsg_max_cnt); @@ -1148,7 +1252,8 @@ int register_pstore_zone(struct pstore_zone_info *info) return -EINVAL; } - if (!info->kmsg_size && !info->pmsg_size && !info->console_size) { + if (!info->kmsg_size && !info->pmsg_size && !info->console_size && + !info->ftrace_size) { pr_warn("at least one record size must be non-zero\n"); return -EINVAL; } @@ -1172,6 +1277,7 @@ int register_pstore_zone(struct pstore_zone_info *info) check_size(kmsg_size, SECTOR_SIZE); check_size(pmsg_size, SECTOR_SIZE); check_size(console_size, SECTOR_SIZE); + check_size(ftrace_size, SECTOR_SIZE); #undef check_size @@ -1199,6 +1305,7 @@ int register_pstore_zone(struct pstore_zone_info *info) pr_debug("\tkmsg size : %ld Bytes\n", info->kmsg_size); pr_debug("\tpmsg size : %ld Bytes\n", info->pmsg_size); pr_debug("\tconsole size : %ld Bytes\n", info->console_size); + pr_debug("\tftrace size : %ld Bytes\n", info->ftrace_size); err = psz_alloc_zones(cxt); if (err) { @@ -1236,6 +1343,10 @@ int register_pstore_zone(struct pstore_zone_info *info) cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE; pr_cont(" console"); } + if (info->ftrace_size) { + cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; + pr_cont(" ftrace"); + } pr_cont("\n"); err = pstore_register(&cxt->pstore); diff --git a/include/linux/pstore_zone.h b/include/linux/pstore_zone.h index 904ee67f4ba2..6f16b0dd834a 100644 --- a/include/linux/pstore_zone.h +++ b/include/linux/pstore_zone.h @@ -19,6 +19,7 @@ typedef ssize_t (*pstore_zone_write_op)(const char *, size_t, loff_t); * @max_reason: Maximum kmsg dump reason to store. * @pmsg_size: The size of pmsg zone which is the same as @kmsg_size. * @console_size:The size of console zone which is the same as @kmsg_size. + * @ftrace_size:The size of ftrace zone which is the same as @kmsg_size. * @read: The general read operation. Both of the function parameters * @size and @offset are relative value to storage. * On success, the number of bytes should be returned, others @@ -37,6 +38,7 @@ struct pstore_zone_info { int max_reason; unsigned long pmsg_size; unsigned long console_size; + unsigned long ftrace_size; pstore_zone_read_op read; pstore_zone_write_op write; pstore_zone_write_op panic_write; From patchwork Sun May 10 20:24:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287366 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=Fp7GGpOZ; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=YO/36Hir; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Kwf12Q2nz9sNH for ; Mon, 11 May 2020 06:29:29 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=+/Y6nD3t0whO/ogGC376T2FtLXUOk1nMHvfcdlo8j/k=; b=Fp7GGpOZajaXhu Q3FTJmGHNCmnY7YOvm/EC02OP5yZzP+xlehOzdbnVWpgjw0zGMN1vyoYg9zG/O9kPGANiBuLibdOs 8KZzMXgARkSTrUBfPOrIOcIDOH92qGBeMPyn3rrPiBUjI2GFa6wi5LN90cNW1TIXI3Z6fbBVl2bi9 /7Q/RCbgxvez0YYuce2uFjXXG4CXc2lNrZndxh5EwH7NZpNAmwLSWnGEvevfUfuTyslKLhLAEyp2T Kj7MJMNDC+Msdz9i15/tPwm4O7+WsMu1KaWyVFw6TjVdJ3LCZAx08GoYw/sJAWxUN4n3SBa7RZtVh 4nah96r4lVPxwyiKpN9g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsZh-0000iM-94; Sun, 10 May 2020 20:29:25 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVM-0002bo-9X for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:25:03 +0000 Received: by mail-pl1-x644.google.com with SMTP id u22so3011817plq.12 for ; Sun, 10 May 2020 13:24:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=B4KToDakeSIDINzenNlRbKu8/1saqdpIGQDx77bj6t4=; b=YO/36Hirq2tXPfKm+WDOVx/THJ2QSfgXwCnutQ1EfFTV2EVY2xNWE5mhhE0c03X/f6 +sDbJXQoCGb6QmyD2NCW+X31+wl0C+EP6EHJkyDPVKHUChtStF3OsFR5gfSQZAHztqGr G3QbbRUuZIQYuIDDB7TJUBZc2RF7e80Kgv9dg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=B4KToDakeSIDINzenNlRbKu8/1saqdpIGQDx77bj6t4=; b=Z5nfKUPYZPi1s5KCGoP588j5QTd7tTRTnsZC8ZDtprXWwz/nUZROCmSQJqijZEMFTP TAuP9gc/niNmye0aGuY8kHnWTZAn4gTuKIJYrmNyKtLaLuXgRKWP+EIQO8bfpEX4ctvG J6dFgLB8Qm/TLJGpASxYI6LaocMmjL9zbaUer7V1WFFJICWWXF3mTfeCZRzNEmsyE2Di LYdegsKygku8TZcGF9sotgSDtgIv+dRLp7s/JMZB1KWVmhhsZOtZnZBkfmAb1Bk0gGWX NKCoZVBkpklpwQKXHlEEkX5gGW75t7yZ2pgRPi9WRPxp562Y956Kq2JZuEQBoi6W86ot WBgA== X-Gm-Message-State: AGi0PuakOH7Dwjup6WLRp6+aFBUkNRjgbhzA8JRrxCl7mxeZXaBXHSEi RZbZ5xX7NJG/zuR8Pl4+Hzo5ZA== X-Google-Smtp-Source: APiQypL0QdKk6bSnO901J4d5LYI5jRWQFDcJ7l+38P1hDVDppXzPcL5UTmdyJxUbphAiPce96jVmTQ== X-Received: by 2002:a17:90a:db46:: with SMTP id u6mr18239979pjx.15.1589142294621; Sun, 10 May 2020 13:24:54 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id gz14sm7937183pjb.42.2020.05.10.13.24.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:52 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 13/18] Documentation: Add details for pstore/blk Date: Sun, 10 May 2020 13:24:31 -0700 Message-Id: <20200510202436.63222-14-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132456_945092_057FB324 X-CRM114-Status: GOOD ( 24.42 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao Add details on using pstore/blk, the new backend of pstore to record dumps to block devices, in Documentation/admin-guide/pstore-blk.rst Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-8-git-send-email-liaoweixiong@allwinnertech.com Signed-off-by: Kees Cook --- Documentation/admin-guide/pstore-blk.rst | 229 +++++++++++++++++++++++ MAINTAINERS | 1 + fs/pstore/Kconfig | 2 + 3 files changed, 232 insertions(+) create mode 100644 Documentation/admin-guide/pstore-blk.rst diff --git a/Documentation/admin-guide/pstore-blk.rst b/Documentation/admin-guide/pstore-blk.rst new file mode 100644 index 000000000000..bef8c7436721 --- /dev/null +++ b/Documentation/admin-guide/pstore-blk.rst @@ -0,0 +1,229 @@ +.. SPDX-License-Identifier: GPL-2.0 + +pstore block oops/panic logger +============================== + +Introduction +------------ + +pstore block (pstore/blk) is an oops/panic logger that writes its logs to a +block device before the system crashes. You can get these log files by +mounting pstore filesystem like:: + + mount -t pstore pstore /sys/fs/pstore + + +pstore block concepts +--------------------- + +pstore/blk provides efficient configuration method for pstore/blk, which +divides all configurations into two parts, configurations for user and +configurations for driver. + +Configurations for user determine how pstore/blk works, such as pmsg_size, +kmsg_size and so on. All of them support both Kconfig and module parameters, +but module parameters have priority over Kconfig. + +Configurations for driver are all about block device, such as total_size +of block device and read/write operations. + +Configurations for user +----------------------- + +All of these configurations support both Kconfig and module parameters, but +module parameters have priority over Kconfig. + +Here is an example for module parameters:: + + pstore_blk.blkdev=179:7 pstore_blk.kmsg_size=64 + +The detail of each configurations may be of interest to you. + +blkdev +~~~~~~ + +The block device to use. Most of the time, it is a partition of block device. +It's required for pstore/blk. + +It accepts the following variants: + +1. device number in hexadecimal represents itself; no + leading 0x, for example b302. +#. /dev/ represents the device number of disk +#. /dev/ represents the device number of partition - device + number of disk plus the partition number +#. /dev/p - same as the above; this form is used when disk + name of partitioned disk ends with a digit. +#. PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF represents the unique id of + a partition if the partition table provides it. The UUID may be either an + EFI/GPT UUID, or refer to an MSDOS partition using the format SSSSSSSS-PP, + where SSSSSSSS is a zero-filled hex representation of the 32-bit + "NT disk signature", and PP is a zero-filled hex representation of the + 1-based partition number. +#. PARTUUID=/PARTNROFF= to select a partition in relation to a + partition with a known unique id. +#. : major and minor number of the device separated by a colon. + +kmsg_size +~~~~~~~~~ + +The chunk size in KB for oops/panic front-end. It **MUST** be a multiple of 4. +It's optional if you do not care oops/panic log. + +There are multiple chunks for oops/panic front-end depending on the remaining +space except other pstore front-ends. + +pstore/blk will log to oops/panic chunks one by one, and always overwrite the +oldest chunk if there is no more free chunk. + +pmsg_size +~~~~~~~~~ + +The chunk size in KB for pmsg front-end. It **MUST** be a multiple of 4. +It's optional if you do not care pmsg log. + +Unlike oops/panic front-end, there is only one chunk for pmsg front-end. + +Pmsg is a user space accessible pstore object. Writes to */dev/pmsg0* are +appended to the chunk. On reboot the contents are available in +*/sys/fs/pstore/pmsg-pstore-blk-0*. + +console_size +~~~~~~~~~~~~ + +The chunk size in KB for console front-end. It **MUST** be a multiple of 4. +It's optional if you do not care console log. + +Similar to pmsg front-end, there is only one chunk for console front-end. + +All log of console will be appended to the chunk. On reboot the contents are +available in */sys/fs/pstore/console-pstore-blk-0*. + +ftrace_size +~~~~~~~~~~~ + +The chunk size in KB for ftrace front-end. It **MUST** be a multiple of 4. +It's optional if you do not care console log. + +Similar to oops front-end, there are multiple chunks for ftrace front-end +depending on the count of cpu processors. Each chunk size is equal to +ftrace_size / processors_count. + +All log of ftrace will be appended to the chunk. On reboot the contents are +combined and available in */sys/fs/pstore/ftrace-pstore-blk-0*. + +Persistent function tracing might be useful for debugging software or hardware +related hangs. Here is an example of usage:: + + # mount -t pstore pstore /sys/fs/pstore + # mount -t debugfs debugfs /sys/kernel/debug/ + # echo 1 > /sys/kernel/debug/pstore/record_ftrace + # reboot -f + [...] + # mount -t pstore pstore /sys/fs/pstore + # tail /sys/fs/pstore/ftrace-pstore-blk-0 + CPU:0 ts:5914676 c0063828 c0063b94 call_cpuidle <- cpu_startup_entry+0x1b8/0x1e0 + CPU:0 ts:5914678 c039ecdc c006385c cpuidle_enter_state <- call_cpuidle+0x44/0x48 + CPU:0 ts:5914680 c039e9a0 c039ecf0 cpuidle_enter_freeze <- cpuidle_enter_state+0x304/0x314 + CPU:0 ts:5914681 c0063870 c039ea30 sched_idle_set_state <- cpuidle_enter_state+0x44/0x314 + CPU:1 ts:5916720 c0160f59 c015ee04 kernfs_unmap_bin_file <- __kernfs_remove+0x140/0x204 + CPU:1 ts:5916721 c05ca625 c015ee0c __mutex_lock_slowpath <- __kernfs_remove+0x148/0x204 + CPU:1 ts:5916723 c05c813d c05ca630 yield_to <- __mutex_lock_slowpath+0x314/0x358 + CPU:1 ts:5916724 c05ca2d1 c05ca638 __ww_mutex_lock <- __mutex_lock_slowpath+0x31c/0x358 + +max_reason +~~~~~~~~~~ + +Limiting which kinds of kmsg dumps are stored can be controlled via +the ``max_reason`` value, as defined in include/linux/kmsg_dump.h's +``enum kmsg_dump_reason``. For example, to store both Oopses and Panics, +``max_reason`` should be set to 2 (KMSG_DUMP_OOPS), to store only Panics +``max_reason`` should be set to 1 (KMSG_DUMP_PANIC). Setting this to 0 +(KMSG_DUMP_UNDEF), means the reason filtering will be controlled by the +``printk.always_kmsg_dump`` boot param: if unset, it'll be KMSG_DUMP_OOPS, +otherwise KMSG_DUMP_MAX. + +Configurations for driver +------------------------- + +Only a block device driver cares about these configurations. A block device +driver uses ``register_pstore_blk`` to register to pstore/blk. + +.. kernel-doc:: fs/pstore/blk.c + :identifiers: register_pstore_blk + +Compression and header +---------------------- + +Block device is large enough for uncompressed oops data. Actually we do not +recommend data compression because pstore/blk will insert some information into +the first line of oops/panic data. For example:: + + Panic: Total 16 times + +It means that it's OOPS|Panic for the 16th time since the first booting. +Sometimes the number of occurrences of oops|panic since the first booting is +important to judge whether the system is stable. + +The following line is inserted by pstore filesystem. For example:: + + Oops#2 Part1 + +It means that it's OOPS for the 2nd time on the last boot. + +Reading the data +---------------- + +The dump data can be read from the pstore filesystem. The format for these +files is ``dmesg-pstore-blk-[N]`` for oops/panic front-end, +``pmsg-pstore-blk-0`` for pmsg front-end and so on. The timestamp of the +dump file records the trigger time. To delete a stored record from block +device, simply unlink the respective pstore file. + +Attentions in panic read/write APIs +----------------------------------- + +If on panic, the kernel is not going to run for much longer, the tasks will not +be scheduled and most kernel resources will be out of service. It +looks like a single-threaded program running on a single-core computer. + +The following points require special attention for panic read/write APIs: + +1. Can **NOT** allocate any memory. + If you need memory, just allocate while the block driver is initializing + rather than waiting until the panic. +#. Must be polled, **NOT** interrupt driven. + No task schedule any more. The block driver should delay to ensure the write + succeeds, but NOT sleep. +#. Can **NOT** take any lock. + There is no other task, nor any shared resource; you are safe to break all + locks. +#. Just use CPU to transfer. + Do not use DMA to transfer unless you are sure that DMA will not keep lock. +#. Control registers directly. + Please control registers directly rather than use Linux kernel resources. + Do I/O map while initializing rather than wait until a panic occurs. +#. Reset your block device and controller if necessary. + If you are not sure of the state of your block device and controller when + a panic occurs, you are safe to stop and reset them. + +pstore/blk supports psblk_blkdev_info(), which is defined in +*linux/pstore_blk.h*, to get information of using block device, such as the +device number, sector count and start sector of the whole disk. + +pstore block internals +---------------------- + +For developer reference, here are all the important structures and APIs: + +.. kernel-doc:: fs/pstore/zone.c + :internal: + +.. kernel-doc:: include/linux/pstore_zone.h + :internal: + +.. kernel-doc:: fs/pstore/blk.c + :export: + +.. kernel-doc:: include/linux/pstore_blk.h + :internal: diff --git a/MAINTAINERS b/MAINTAINERS index e64e5db31497..9c1f4feff418 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13660,6 +13660,7 @@ M: Tony Luck S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore F: Documentation/admin-guide/ramoops.rst +F: Documentation/admin-guide/pstore-blk.rst F: Documentation/devicetree/bindings/reserved-memory/ramoops.txt F: drivers/acpi/apei/erst.c F: drivers/firmware/efi/efi-pstore.c diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 16a0440d8d5a..8371d29651a6 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -171,6 +171,8 @@ config PSTORE_BLK This enables panic and oops message to be logged to a block dev where it can be read back at some later point. + For more information, see Documentation/admin-guide/pstore-blk.rst + If unsure, say N. config PSTORE_BLK_BLKDEV From patchwork Sun May 10 20:24:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287361 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=EhadWizU; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=dEoaVsI8; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49KwcW3Qvvz9sNH for ; Mon, 11 May 2020 06:28:11 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Nlnm12FVZJdHjRugV3DYfVlnKnSfdj6X7fuFIrdMjwo=; b=EhadWizUAAp1v4 egGxrVIUeSDVmIs2rpM/aqjmYHMoxXzpK8Fr+Ww3Kx6nVwm1Uk+yxAYko68Ha+ZLnNIheqSaqjWs9 n/gDXJ+NG+Sbk3p60E3UZi+t1tADzUQ/35iHMzYYcOnuRsygnccV1Ma1HVQe9QvVEr9iD3BE6KfY8 48/fjpkojy2oyDI9tVGOMMX5CbparGL39RMZm92PVZOoXH7+PseDP942FpYje/9xOBT/OPiKCsP92 BIDN9A1VsLHyGr//9/EPsqlwsCaD6v/mHXdT7X59Y8h029x0JkWEHUFKir9H6cYkSjYrTzu7kNkPX uEnstrf6KTqDIfcN9D8Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsYD-0007o1-JI; Sun, 10 May 2020 20:27:53 +0000 Received: from mail-pj1-x1041.google.com ([2607:f8b0:4864:20::1041]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVK-0002Zq-GW for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:59 +0000 Received: by mail-pj1-x1041.google.com with SMTP id a7so6736631pju.2 for ; Sun, 10 May 2020 13:24:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=djXoO40SYWuMqieCahe2S9nP61MHvZmDKOFDi+VFn9I=; b=dEoaVsI8K/4skWYK4+myWQBMdhHpF0BHWQfkbzAVAaQTqnotO7LNuwTKPLDWnC+2ft Kx5l3kIA81lzCf4/iKonrcSpocj5nNQJT0u9FWHCjsWnJhAc31Xj/pGsfI4lzKScgBaj PMQ6yjlQUSk6OR2EC+QSOtuYPZX/+NPII3TPQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=djXoO40SYWuMqieCahe2S9nP61MHvZmDKOFDi+VFn9I=; b=I58NMq9VM91LnlouZCMxKX7FVAR3OprvJj2BzGhGByOskbal+EXaY0XEBn4li2wL1F 1POX5r4BVNhqgFEurqhEYZJw5C7NcRN0xFn6XXnKzctUhsNoYCKsyNP8p05/GkXD47bn 67U5j0En0yyvl4jOHtRQHyIwE0HJFkI83/LF/m9CiWZpSY8XCPpVO9dDNhfgsfrBCQ+O 2fTnc0RMMVM3I5Pl5d3uDk5ilriJ/+KJlqB7B/ackKSHBKimHcb0cXmImQyXpUKkAmTX CzOl9hiPgqa+a3I6fsA+YtFmLV/lQxKVSZA1/k7gv1/5AdtAAoB0shvyZEgVUjA9DAHH xIMw== X-Gm-Message-State: AGi0PuYGCxTt/8LKEF7okvZhjexzqks/qB1P2JtepTkv+SV4jPg8xY0t QX4KhB8mdrUkD9bdRQiYlptsTw== X-Google-Smtp-Source: APiQypJVoMKhlFIut16BX/usNCkk/C+Igt9st/Vh4mVegaZVEBmygXfm3rHfXBwjWiIkkgTmHYMAjA== X-Received: by 2002:a17:90a:9f8a:: with SMTP id o10mr18705405pjp.118.1589142293172; Sun, 10 May 2020 13:24:53 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id cc8sm7949234pjb.11.2020.05.10.13.24.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:51 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 14/18] pstore/zone: Provide way to skip "broken" zone for MTD devices Date: Sun, 10 May 2020 13:24:32 -0700 Message-Id: <20200510202436.63222-15-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132454_689705_0A6D207D X-CRM114-Status: GOOD ( 19.44 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:1041 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao One requirement to support MTD devices in pstore/zone is having a way to declare certain regions as broken. Add this support to pstore/zone. The MTD driver should return -ENOMSG when encountering a bad region, which tells pstore/zone to skip and try the next one. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-9-git-send-email-liaoweixiong@allwinnertech.com Signed-off-by: Kees Cook --- fs/pstore/blk.c | 10 ++++-- fs/pstore/zone.c | 65 ++++++++++++++++++++++++++++++------- include/linux/pstore_blk.h | 3 +- include/linux/pstore_zone.h | 12 ++++--- 4 files changed, 71 insertions(+), 19 deletions(-) diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c index e45937e3517c..cf11094e6b3a 100644 --- a/fs/pstore/blk.c +++ b/fs/pstore/blk.c @@ -108,9 +108,12 @@ static struct bdev_info { * means error. * @write: The same as @read, but the following error number: * -EBUSY means try to write again later. + * -ENOMSG means to try next zone. * @panic_write:The write operation only used for panic case. It's optional - * if you do not care panic log. The parameters and return value - * are the same as @read. + * if you do not care panic log. The parameters are relative + * value to storage. + * On success, the number of bytes should be returned, others + * excluding -ENOMSG mean error. -ENOMSG means to try next zone. */ struct pstore_device_info { unsigned long total_size; @@ -336,6 +339,9 @@ static ssize_t psblk_blk_panic_write(const char *buf, size_t size, /* size and off must align to SECTOR_SIZE for block device */ ret = blkdev_panic_write(buf, off >> SECTOR_SHIFT, size >> SECTOR_SHIFT); + /* try next zone */ + if (ret == -ENOMSG) + return ret; return ret ? -EIO : size; } diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c index 45c0a422f1de..17c9a0439d6e 100644 --- a/fs/pstore/zone.c +++ b/fs/pstore/zone.c @@ -249,6 +249,9 @@ static int psz_zone_write(struct pstore_zone *zone, return 0; dirty: + /* no need to mark dirty if going to try next zone */ + if (wcnt == -ENOMSG) + return -ENOMSG; atomic_set(&zone->dirty, true); /* flush dirty zones nicely */ if (wcnt == -EBUSY && !is_on_panic()) @@ -391,7 +394,11 @@ static int psz_kmsg_recover_meta(struct psz_context *cxt) return -EINVAL; rcnt = info->read((char *)buf, len, zone->off); - if (rcnt != len) { + if (rcnt == -ENOMSG) { + pr_debug("%s with id %lu may be broken, skip\n", + zone->name, i); + continue; + } else if (rcnt != len) { pr_err("read %s with id %lu failed\n", zone->name, i); return (int)rcnt < 0 ? (int)rcnt : -EIO; } @@ -726,24 +733,58 @@ static void psz_write_kmsg_hdr(struct pstore_zone *zone, hdr->counter = 0; } +/* + * In case zone is broken, which may occur to MTD device, we try each zones, + * start at cxt->kmsg_write_cnt. + */ static inline int notrace psz_kmsg_write_record(struct psz_context *cxt, struct pstore_record *record) { + int ret = -EBUSY; size_t size, hlen; struct pstore_zone *zone; - unsigned int zonenum; + unsigned int i; - zonenum = cxt->kmsg_write_cnt; - zone = cxt->opszs[zonenum]; - if (unlikely(!zone)) - return -ENOSPC; - cxt->kmsg_write_cnt = (zonenum + 1) % cxt->kmsg_max_cnt; + for (i = 0; i < cxt->kmsg_max_cnt; i++) { + unsigned int zonenum, len; + + zonenum = (cxt->kmsg_write_cnt + i) % cxt->kmsg_max_cnt; + zone = cxt->opszs[zonenum]; + if (unlikely(!zone)) + return -ENOSPC; + + /* avoid destroying old data, allocate a new one */ + len = zone->buffer_size + sizeof(*zone->buffer); + zone->oldbuf = zone->buffer; + zone->buffer = kzalloc(len, GFP_KERNEL); + if (!zone->buffer) { + zone->buffer = zone->oldbuf; + return -ENOMEM; + } + zone->buffer->sig = zone->oldbuf->sig; + + pr_debug("write %s to zone id %d\n", zone->name, zonenum); + psz_write_kmsg_hdr(zone, record); + hlen = sizeof(struct psz_kmsg_header); + size = min_t(size_t, record->size, zone->buffer_size - hlen); + ret = psz_zone_write(zone, FLUSH_ALL, record->buf, size, hlen); + if (likely(!ret || ret != -ENOMSG)) { + cxt->kmsg_write_cnt = zonenum + 1; + cxt->kmsg_write_cnt %= cxt->kmsg_max_cnt; + /* no need to try next zone, free last zone buffer */ + kfree(zone->oldbuf); + zone->oldbuf = NULL; + return ret; + } - pr_debug("write %s to zone id %d\n", zone->name, zonenum); - psz_write_kmsg_hdr(zone, record); - hlen = sizeof(struct psz_kmsg_header); - size = min_t(size_t, record->size, zone->buffer_size - hlen); - return psz_zone_write(zone, FLUSH_ALL, record->buf, size, hlen); + pr_debug("zone %u may be broken, try next dmesg zone\n", + zonenum); + kfree(zone->buffer); + zone->buffer = zone->oldbuf; + zone->oldbuf = NULL; + } + + return -EBUSY; } static int notrace psz_kmsg_write(struct psz_context *cxt, diff --git a/include/linux/pstore_blk.h b/include/linux/pstore_blk.h index 4501977b1336..ccba8c068752 100644 --- a/include/linux/pstore_blk.h +++ b/include/linux/pstore_blk.h @@ -14,7 +14,8 @@ * @start_sect: start sector to block device * @sects: sectors count on buf * - * Return: On success, zero should be returned. Others mean error. + * Return: On success, zero should be returned. Others excluding -ENOMSG + * mean error. -ENOMSG means to try next zone. * * Panic write to block device must be aligned to SECTOR_SIZE. */ diff --git a/include/linux/pstore_zone.h b/include/linux/pstore_zone.h index 6f16b0dd834a..e79a18e41064 100644 --- a/include/linux/pstore_zone.h +++ b/include/linux/pstore_zone.h @@ -23,11 +23,15 @@ typedef ssize_t (*pstore_zone_write_op)(const char *, size_t, loff_t); * @read: The general read operation. Both of the function parameters * @size and @offset are relative value to storage. * On success, the number of bytes should be returned, others - * means error. - * @write: The same as @read, but -EBUSY means try to write again later. + * mean error. + * @write: The same as @read, but the following error number: + * -EBUSY means try to write again later. + * -ENOMSG means to try next zone. * @panic_write:The write operation only used for panic case. It's optional - * if you do not care panic log. The parameters and return value - * are the same as @read. + * if you do not care panic log. The parameters are relative + * value to storage. + * On success, the number of bytes should be returned, others + * excluding -ENOMSG mean error. -ENOMSG means to try next zone. */ struct pstore_zone_info { struct module *owner; From patchwork Sun May 10 20:24:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287362 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=PGE67g3P; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=RZCkHmVA; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Kwcd4l4tz9sNH for ; Mon, 11 May 2020 06:28:17 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=3ydTZxb3/ceolx0wKZoWkfE8ayYwncDp1v8GkzSy2Qc=; b=PGE67g3Pvw1xWd uoVVS55V4FeNHafXm97bU34/Nxx1OqbHCYm47VG9WkIbirgAbHRusbVsF73+3Pdt1rgmQFk//+MSp OXBgVBb924OEMkpCac+AUQ5INVM0YfUKgktP9k+Z7n8jwvCRphuffbwkFFWTyXY6XTm35yW2qBg0b R2VpNpQ2oCDJsboA2H7g+K9Ue44uALnQ3u66IaZCdoF8BHwdDL0pI1tUa+ZIlxD84W3HiODiAXXpo JhijG4am3FaoxF0an+A1p4uYTgTxEWmdgGSEiLLUR/obHpSAO6AdzVwSISM1oEHi2YSgoS5FEDrEi /HMWHw/MLx3PoN4NGfxA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsYX-000849-A3; Sun, 10 May 2020 20:28:13 +0000 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsVK-0002aE-SC for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:24:58 +0000 Received: by mail-pf1-x444.google.com with SMTP id x15so3167737pfa.1 for ; Sun, 10 May 2020 13:24:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=gDtEYHl+vhPbK8gExr5i1enY2u7ASw/t7gafPT2Tua4=; b=RZCkHmVAC0P+C+6umcgVArdbYqZtRYnJRAlIhCh7f3a3cUMxFuV3H96Y96URE7Gof/ u2VScQV+I5XS16Po+v3nw+05j9q1Km7Nj2pCvYr9O7F55AFy5XX2XIGOqxzR6uakM1Hi E0hhPic0V5ljBYELraELCZtE7STLs0OQLG804= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gDtEYHl+vhPbK8gExr5i1enY2u7ASw/t7gafPT2Tua4=; b=PnwxIyTjlsjo5wEfTig65IVjLOej6aE7e4Li1WVIrVdxhg2E4HzUx4c6/ofP3WtDhS dA/H81EEVYxtnXoKYtyeYJ7Dd9yhFWtnjNJyHoKuPdqPi6cPy0QPEdGiDBIF+6HEg/fp qOF3N5yaCSywJM5i5COd1cV8p7CN93m0P3Fv2BaAMoA9SVP4NNb1Sy3gTWWY+IEeVZBw VF1kmNOeiVtp5pE+DRJYkP9w1gZ7NqImviIadNd1mtsDXcHZ8DxVtiv04zHjbwHr65sr b20qCvtwQINrDpLn+kwCqJO19cYk6Y0/YAGcif3dAdi6dFgUbeTrOfryEcHllLZF9xgD Rceg== X-Gm-Message-State: AGi0PuaC1OVXZPBnxYHpU1nGZy34aCElg4+l0UWt6EHR5ogadOvEi1yj 0lfCFdMRSt+AcnUWWeO5dZBl0w== X-Google-Smtp-Source: APiQypLYkPhTk56rTdjpKjnLfkUUxgxCThNOHV4aV+bIc6cfzxu6EZU0TNu2gO+Z81qJwGnSbxv6Wg== X-Received: by 2002:a63:c644:: with SMTP id x4mr11682741pgg.385.1589142293702; Sun, 10 May 2020 13:24:53 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id v127sm7279503pfv.77.2020.05.10.13.24.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:24:52 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 15/18] pstore/blk: Provide way to query pstore configuration Date: Sun, 10 May 2020 13:24:33 -0700 Message-Id: <20200510202436.63222-16-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_132454_957715_A30A84A6 X-CRM114-Status: GOOD ( 13.65 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:444 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao In order to configure itself, the MTD backend needs to be able to query the current pstore configuration. Introduce pstore_blk_get_config() for this purpose. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-10-git-send-email-liaoweixiong@allwinnertech.com Co-developed-by: Kees Cook Signed-off-by: Kees Cook --- fs/pstore/blk.c | 37 ++++++++++++++++++++++++++++++------- include/linux/pstore_blk.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c index cf11094e6b3a..e8e907ea8b03 100644 --- a/fs/pstore/blk.c +++ b/fs/pstore/blk.c @@ -93,6 +93,17 @@ static struct bdev_info { sector_t start_sect; } g_bdev_info; +#define check_size(name, alignsize) ({ \ + long _##name_ = (name); \ + _##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \ + if (_##name_ & ((alignsize) - 1)) { \ + pr_info(#name " must align to %d\n", \ + (alignsize)); \ + _##name_ = ALIGN(name, (alignsize)); \ + } \ + _##name_; \ +}) + /** * struct pstore_device_info - back-end pstore/blk driver structure. * @@ -148,13 +159,11 @@ static int psblk_register_do(struct pstore_device_info *dev) dev->flags = UINT_MAX; #define verify_size(name, alignsize, enabled) { \ - long _##name_ = (enabled) ? (name) : 0; \ - _##name_ = _##name_ <= 0 ? 0 : (_##name_ * 1024); \ - if (_##name_ & ((alignsize) - 1)) { \ - pr_info(#name " must align to %d\n", \ - (alignsize)); \ - _##name_ = ALIGN(name, (alignsize)); \ - } \ + long _##name_; \ + if (enabled) \ + _##name_ = check_size(name, alignsize); \ + else \ + _##name_ = 0; \ name = _##name_ / 1024; \ pstore_zone_info->name = _##name_; \ } @@ -455,6 +464,20 @@ void unregister_pstore_blk(unsigned int major) } EXPORT_SYMBOL_GPL(unregister_pstore_blk); +/* get information of pstore/blk */ +int pstore_blk_get_config(struct pstore_blk_config *info) +{ + strncpy(info->device, blkdev, 80); + info->max_reason = max_reason; + info->kmsg_size = check_size(kmsg_size, 4096); + info->pmsg_size = check_size(pmsg_size, 4096); + info->ftrace_size = check_size(ftrace_size, 4096); + info->console_size = check_size(console_size, 4096); + + return 0; +} +EXPORT_SYMBOL_GPL(pstore_blk_get_config); + static void __exit pstore_blk_exit(void) { mutex_lock(&pstore_blk_lock); diff --git a/include/linux/pstore_blk.h b/include/linux/pstore_blk.h index ccba8c068752..0c40774e71e0 100644 --- a/include/linux/pstore_blk.h +++ b/include/linux/pstore_blk.h @@ -49,4 +49,32 @@ struct pstore_blk_info { int register_pstore_blk(struct pstore_blk_info *info); void unregister_pstore_blk(unsigned int major); +/** + * struct pstore_blk_config - the pstore_blk backend configuration + * + * @device: Name of the desired block device + * @max_reason: Maximum kmsg dump reason to store to block device + * @kmsg_size: Total size of for kmsg dumps + * @pmsg_size: Total size of the pmsg storage area + * @console_size: Total size of the console storage area + * @ftrace_size: Total size for ftrace logging data (for all CPUs) + */ +struct pstore_blk_config { + char device[80]; + enum kmsg_dump_reason max_reason; + unsigned long kmsg_size; + unsigned long pmsg_size; + unsigned long console_size; + unsigned long ftrace_size; +}; + +/** + * pstore_blk_get_config - get a copy of the pstore_blk backend configuration + * + * @info: The sturct pstore_blk_config to be filled in + * + * Failure returns negative error code, and success returns 0. + */ +int pstore_blk_get_config(struct pstore_blk_config *info); + #endif From patchwork Sun May 10 20:24:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287368 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=mgVslKfV; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=KpM9TlJY; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Kwj94fgFz9sSm for ; Mon, 11 May 2020 06:32:13 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=oUXvF9D57pxwAls/PiUq0SL+4AJIvQb9ISiLu8aXD3A=; b=mgVslKfVnGKzS3 5FGT7aRas2mtWFhPN9OFoh2F1jJVg8ThzNp/teLBh5bWCf7f9HUFO+ZHpsobnwpzBuA26UrvyVx1t 3syfhDU3qF1Xioe45DTRyN458WFFxO5vxaneXu8IadFKoQSUMIXupuwU2qV+frcyN7uZ9Ufi+ChFX CCFmAKXLWguBB6OSEDh3VP49olNVMZUwxQM24HQkmAEAHkKKJqhlSmKLJ9ixIvQDMXjvERgFrsboT AbRX1+xTz5G8Ky54m0IFXXZ2fZ16Cz/srl23Km6Z6vypNiPvf08BgCEqunka3esrIXCIVPEUk90X6 aO3fFzI63LQMhn/bBexA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXscM-0004O7-Og; Sun, 10 May 2020 20:32:10 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXscA-0004C6-DW for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:32:00 +0000 Received: by mail-pl1-x644.google.com with SMTP id u10so3028063pls.8 for ; Sun, 10 May 2020 13:31:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ir/tW5eoK5uXYiNLryAUfBY8WLibMB3ybmcRpMvWllk=; b=KpM9TlJYWXrXEYrwcnrm4ofE3uXbU6B5N6O0tQowisDhcGPVkHuA1atNz7bO4TNPnS Cpj0b6j2qjpNod4Ksajil38bGhzpE0w7GPuCWhEq+/C5K/ud3zj/g39ySB1raCMKZKBB ITfC9pjOPlrUfl5xYI8U/kDg5VgY77UvrAFWk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ir/tW5eoK5uXYiNLryAUfBY8WLibMB3ybmcRpMvWllk=; b=HXw0OlLCTRvI3KxkUWMDfeM5AyeAVNsWwPapD7+sCPOZT89pA/AjtMq9p8b4LJ9iuK 5kC/9OGB9TGXoEk1/eSTpuBo19dKeFFsnV1A3Xt8amVvTApaw+D/52NobOzg1S7umwpA oEXzSS3GtTlx1EM46jSRBL7JgHhOAAfNgYyJZSSBTJ5DAddsdzAgY8LNlT5aGGcELvju ReT7PYuUs0BQApkdXFTsU78MsgbaWjOacBAdFJ/4gZF8wekSGy12+46gKtsEgs3MYSge oD14SIxKzHFHT1m3w+aC3MdL2SSd+tarjCzk65uG0ddv5v+JB6qe7q34ATKSOgs1uQoH fGkA== X-Gm-Message-State: AGi0PuZ4s16e/eRRlI73lwMJ2ArJJVy9SCIz6uchOXy8CmXV6s/G8EIP UUVjiam85mAbhX6Iaxnsxs+j3Q== X-Google-Smtp-Source: APiQypKrzIJmAIxHjDnc8zD3JQGTaRexPrGGeFhcwbrBTP4WtL9nsdbrsU7LNMkKwT7i8hz1tQEg4w== X-Received: by 2002:a17:902:ea86:: with SMTP id x6mr11131121plb.75.1589142717712; Sun, 10 May 2020 13:31:57 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id 135sm7396347pfu.125.2020.05.10.13.31.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:31:56 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 16/18] pstore/blk: Support non-block storage devices Date: Sun, 10 May 2020 13:24:34 -0700 Message-Id: <20200510202436.63222-17-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_133158_464116_6A65B2A8 X-CRM114-Status: GOOD ( 20.43 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao Add support for non-block devices (e.g. MTD). A non-block driver calls pstore_blk_register_device() to register iself. In addition, pstore/zone is updated to handle non-block devices, where an erase must be done before a write. Without this, there is no way to remove records stored to an MTD. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-11-git-send-email-liaoweixiong@allwinnertech.com Signed-off-by: Kees Cook --- Documentation/admin-guide/pstore-blk.rst | 17 ++++- fs/pstore/blk.c | 94 +++++++++++++----------- fs/pstore/zone.c | 8 +- include/linux/pstore_blk.h | 38 ++++++++++ include/linux/pstore_zone.h | 6 ++ 5 files changed, 115 insertions(+), 48 deletions(-) diff --git a/Documentation/admin-guide/pstore-blk.rst b/Documentation/admin-guide/pstore-blk.rst index bef8c7436721..d45341e55e82 100644 --- a/Documentation/admin-guide/pstore-blk.rst +++ b/Documentation/admin-guide/pstore-blk.rst @@ -7,8 +7,8 @@ Introduction ------------ pstore block (pstore/blk) is an oops/panic logger that writes its logs to a -block device before the system crashes. You can get these log files by -mounting pstore filesystem like:: +block device and non-block device before the system crashes. You can get +these log files by mounting pstore filesystem like:: mount -t pstore pstore /sys/fs/pstore @@ -24,8 +24,8 @@ Configurations for user determine how pstore/blk works, such as pmsg_size, kmsg_size and so on. All of them support both Kconfig and module parameters, but module parameters have priority over Kconfig. -Configurations for driver are all about block device, such as total_size -of block device and read/write operations. +Configurations for driver are all about block device and non-block device, +such as total_size of block device and read/write operations. Configurations for user ----------------------- @@ -152,6 +152,15 @@ driver uses ``register_pstore_blk`` to register to pstore/blk. .. kernel-doc:: fs/pstore/blk.c :identifiers: register_pstore_blk +A non-block device driver uses ``register_pstore_device`` with +``struct pstore_device_info`` to register to pstore/blk. + +.. kernel-doc:: fs/pstore/blk.c + :identifiers: register_pstore_device + +.. kernel-doc:: include/linux/pstore_blk.h + :identifiers: pstore_device_info + Compression and header ---------------------- diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c index e8e907ea8b03..0dea8ded2de2 100644 --- a/fs/pstore/blk.c +++ b/fs/pstore/blk.c @@ -104,55 +104,23 @@ static struct bdev_info { _##name_; \ }) -/** - * struct pstore_device_info - back-end pstore/blk driver structure. - * - * @total_size: The total size in bytes pstore/blk can use. It must be greater - * than 4096 and be multiple of 4096. - * @flags: Refer to macro starting with PSTORE_FLAGS defined in - * linux/pstore.h. It means what front-ends this device support. - * Zero means all backends for compatible. - * @read: The general read operation. Both of the function parameters - * @size and @offset are relative value to bock device (not the - * whole disk). - * On success, the number of bytes should be returned, others - * means error. - * @write: The same as @read, but the following error number: - * -EBUSY means try to write again later. - * -ENOMSG means to try next zone. - * @panic_write:The write operation only used for panic case. It's optional - * if you do not care panic log. The parameters are relative - * value to storage. - * On success, the number of bytes should be returned, others - * excluding -ENOMSG mean error. -ENOMSG means to try next zone. - */ -struct pstore_device_info { - unsigned long total_size; - unsigned int flags; - pstore_zone_read_op read; - pstore_zone_write_op write; - pstore_zone_write_op panic_write; -}; - -static int psblk_register_do(struct pstore_device_info *dev) +static int __register_pstore_device(struct pstore_device_info *dev) { int ret; - if (!dev || !dev->total_size || !dev->read || !dev->write) + if (WARN_ON(!mutex_is_locked(&pstore_blk_lock))) return -EINVAL; - mutex_lock(&pstore_blk_lock); + if (!dev || !dev->total_size || !dev->read || !dev->write) + return -EINVAL; /* someone already registered before */ - if (pstore_zone_info) { - mutex_unlock(&pstore_blk_lock); + if (pstore_zone_info) return -EBUSY; - } + pstore_zone_info = kzalloc(sizeof(struct pstore_zone_info), GFP_KERNEL); - if (!pstore_zone_info) { - mutex_unlock(&pstore_blk_lock); + if (!pstore_zone_info) return -ENOMEM; - } /* zero means not limit on which backends to attempt to store. */ if (!dev->flags) @@ -178,6 +146,7 @@ static int psblk_register_do(struct pstore_device_info *dev) pstore_zone_info->max_reason = max_reason; pstore_zone_info->read = dev->read; pstore_zone_info->write = dev->write; + pstore_zone_info->erase = dev->erase; pstore_zone_info->panic_write = dev->panic_write; pstore_zone_info->name = KBUILD_MODNAME; pstore_zone_info->owner = THIS_MODULE; @@ -187,20 +156,51 @@ static int psblk_register_do(struct pstore_device_info *dev) kfree(pstore_zone_info); pstore_zone_info = NULL; } + return ret; +} +/** + * register_pstore_device() - register non-block device to pstore/blk + * + * @dev: non-block device information + * + * Return: + * * 0 - OK + * * Others - something error. + */ +int register_pstore_device(struct pstore_device_info *dev) +{ + int ret; + + mutex_lock(&pstore_blk_lock); + ret = __register_pstore_device(dev); mutex_unlock(&pstore_blk_lock); + return ret; } +EXPORT_SYMBOL_GPL(register_pstore_device); -static void psblk_unregister_do(struct pstore_device_info *dev) +static void __unregister_pstore_device(struct pstore_device_info *dev) { - mutex_lock(&pstore_blk_lock); + WARN_ON(!mutex_is_locked(&pstore_blk_lock)); if (pstore_zone_info && pstore_zone_info->read == dev->read) { unregister_pstore_zone(pstore_zone_info); kfree(pstore_zone_info); pstore_zone_info = NULL; } +} + +/** + * unregister_pstore_device() - unregister non-block device from pstore/blk + * + * @dev: non-block device information + */ +void unregister_pstore_device(struct pstore_device_info *dev) +{ + mutex_lock(&pstore_blk_lock); + __unregister_pstore_device(dev); mutex_unlock(&pstore_blk_lock); } +EXPORT_SYMBOL_GPL(unregister_pstore_device); /** * psblk_get_bdev() - open block device @@ -397,9 +397,10 @@ static int __register_pstore_blk(struct pstore_blk_info *info) dev.flags = info->flags; dev.read = psblk_generic_blk_read; dev.write = psblk_generic_blk_write; + dev.erase = NULL; dev.panic_write = info->panic_write ? psblk_blk_panic_write : NULL; - ret = psblk_register_do(&dev); + ret = __register_pstore_device(&dev); if (ret) goto err_put_bdev; @@ -443,7 +444,7 @@ static void __unregister_pstore_blk(unsigned int major) WARN_ON(!mutex_is_locked(&pstore_blk_lock)); if (psblk_bdev && MAJOR(psblk_bdev->bd_dev) == major) { - psblk_unregister_do(&dev); + __unregister_pstore_device(&dev); psblk_put_bdev(psblk_bdev, holder); blkdev_panic_write = NULL; psblk_bdev = NULL; @@ -483,6 +484,13 @@ static void __exit pstore_blk_exit(void) mutex_lock(&pstore_blk_lock); if (psblk_bdev) __unregister_pstore_blk(MAJOR(psblk_bdev->bd_dev)); + else { + struct pstore_device_info dev = { }; + + if (pstore_zone_info) + dev.read = pstore_zone_info->read; + __unregister_pstore_device(&dev); + } mutex_unlock(&pstore_blk_lock); } module_exit(pstore_blk_exit); diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c index 17c9a0439d6e..b04257f8420f 100644 --- a/fs/pstore/zone.c +++ b/fs/pstore/zone.c @@ -661,15 +661,21 @@ static inline int psz_kmsg_erase(struct psz_context *cxt, struct psz_buffer *buffer = zone->buffer; struct psz_kmsg_header *hdr = (struct psz_kmsg_header *)buffer->data; + size_t size; if (unlikely(!psz_ok(zone))) return 0; + /* this zone is already updated, no need to erase */ if (record->count != hdr->counter) return 0; + size = buffer_datalen(zone) + sizeof(*zone->buffer); atomic_set(&zone->buffer->datalen, 0); - return psz_zone_write(zone, FLUSH_META, NULL, 0, 0); + if (cxt->pstore_zone_info->erase) + return cxt->pstore_zone_info->erase(size, zone->off); + else + return psz_zone_write(zone, FLUSH_META, NULL, 0, 0); } static inline int psz_record_erase(struct psz_context *cxt, diff --git a/include/linux/pstore_blk.h b/include/linux/pstore_blk.h index 0c40774e71e0..61e914522b01 100644 --- a/include/linux/pstore_blk.h +++ b/include/linux/pstore_blk.h @@ -49,6 +49,44 @@ struct pstore_blk_info { int register_pstore_blk(struct pstore_blk_info *info); void unregister_pstore_blk(unsigned int major); +/** + * struct pstore_device_info - back-end pstore/blk driver structure. + * + * @total_size: The total size in bytes pstore/blk can use. It must be greater + * than 4096 and be multiple of 4096. + * @flags: Refer to macro starting with PSTORE_FLAGS defined in + * linux/pstore.h. It means what front-ends this device support. + * Zero means all backends for compatible. + * @read: The general read operation. Both of the function parameters + * @size and @offset are relative value to bock device (not the + * whole disk). + * On success, the number of bytes should be returned, others + * means error. + * @write: The same as @read, but the following error number: + * -EBUSY means try to write again later. + * -ENOMSG means to try next zone. + * @erase: The general erase operation for device with special removing + * job. Both of the function parameters @size and @offset are + * relative value to storage. + * Return 0 on success and others on failure. + * @panic_write:The write operation only used for panic case. It's optional + * if you do not care panic log. The parameters are relative + * value to storage. + * On success, the number of bytes should be returned, others + * excluding -ENOMSG mean error. -ENOMSG means to try next zone. + */ +struct pstore_device_info { + unsigned long total_size; + unsigned int flags; + pstore_zone_read_op read; + pstore_zone_write_op write; + pstore_zone_erase_op erase; + pstore_zone_write_op panic_write; +}; + +int register_pstore_device(struct pstore_device_info *dev); +void unregister_pstore_device(struct pstore_device_info *dev); + /** * struct pstore_blk_config - the pstore_blk backend configuration * diff --git a/include/linux/pstore_zone.h b/include/linux/pstore_zone.h index e79a18e41064..1e35eaa33e5e 100644 --- a/include/linux/pstore_zone.h +++ b/include/linux/pstore_zone.h @@ -7,6 +7,7 @@ typedef ssize_t (*pstore_zone_read_op)(char *, size_t, loff_t); typedef ssize_t (*pstore_zone_write_op)(const char *, size_t, loff_t); +typedef ssize_t (*pstore_zone_erase_op)(size_t, loff_t); /** * struct pstore_zone_info - pstore/zone back-end driver structure * @@ -27,6 +28,10 @@ typedef ssize_t (*pstore_zone_write_op)(const char *, size_t, loff_t); * @write: The same as @read, but the following error number: * -EBUSY means try to write again later. * -ENOMSG means to try next zone. + * @erase: The general erase operation for device with special removing + * job. Both of the function parameters @size and @offset are + * relative value to storage. + * Return 0 on success and others on failure. * @panic_write:The write operation only used for panic case. It's optional * if you do not care panic log. The parameters are relative * value to storage. @@ -45,6 +50,7 @@ struct pstore_zone_info { unsigned long ftrace_size; pstore_zone_read_op read; pstore_zone_write_op write; + pstore_zone_erase_op erase; pstore_zone_write_op panic_write; }; From patchwork Sun May 10 20:24:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287369 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=d8gs/XZx; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=IChx+8el; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Kwjk1BlWz9sNH for ; Mon, 11 May 2020 06:32:42 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=n1RJh5f4E5jxWvwZ/vDJdFuX9oAnNNLLDH0gucFxlFU=; b=d8gs/XZxFL9uyf utuTB975F6XDutO2YDKQFJ6VddpDOOvHpQCVDeaWJtRLOikNWdBOIzfAYQu8il1LLjqb8uzQyC5wR z2qLq6oU9ZQnXvfmE/+kIyJVQPCSQLqQQsWWhQ4KKBX06XHhSjoHFg8RbKPwGkXRr81vZNEaVpJSD 1vWoxfdcOgph1wL9qFGrN/adaTL8WSt+h2sRAwssBNaj/XOnTgbizpVVFkopZpqMZY7GuHSmsvYra YJXa8zUoZpPo747KQeg5J+VG7TpYgC0Scq0s/K5uV54rFK+PNPeO/ikoOwZIdRFqMObxO0p8kWEnB dBgwBe1UHNCIW83S7ZFA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsca-0004dD-Hs; Sun, 10 May 2020 20:32:24 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXscB-0004CS-7R for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:32:01 +0000 Received: by mail-pl1-x644.google.com with SMTP id f15so3031275plr.3 for ; Sun, 10 May 2020 13:31:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rKJPcb3ABykHsU2bJnW61Tee1OH0+skonK3QilRAQsI=; b=IChx+8elSlgv/IOFvlGy9MIP6tQ9BTESv6JqRsRYSPy8kp/Xr7W+qrV/OEYwNL2XQd wMuHDV0A2g3qEHR5y3hyvIjj+H9sbGPvd0LOdercKRgyy+1ecEP8O3nnZBnjJ49L7uHU 6NlRbZ8KTQ5bgmj4BgPwIM6K/Lxy8W6bi2PZ8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rKJPcb3ABykHsU2bJnW61Tee1OH0+skonK3QilRAQsI=; b=D4cO1DDhPGMlHpIrxMcqiFnkYgPUyN6uZAu6miFPz3mrfAXvKXaKBV/7nzTuWu+d8/ kFf7Bqu8GbHCXkR4ErTWzJpQs4zuRo8hAp3UHLpSQTlLxU8Q7IULrbMg8d66na5N7Rfx amBJrxjjQwwALL0+J7G6PlizRawUkwXPQ8EdeoA4xmlABO+okaNqDICTgWbfspW9VrWb pEQdd/dnqIQLKf8t/5FVq05QQwH7CQFLSG0ZQZR4Px1cDdVXrX0WhcY5OOjvCz8FgHsw FD/qHq44/KAasvDExPGjgt2kWJFZRm/LMXKR2aWuXrZeQDKdW9o+8UWmvYwv9mQj+9CB 46dQ== X-Gm-Message-State: AGi0PuaZLY4Mi7svISBQtJpJGDLdy8pyzkealLHjLTySLUQdmcgERKPt LYiHAu38pmD06eFhBoTY5Oo4yg== X-Google-Smtp-Source: APiQypIzhuhktEvn4c8fZ6yP9o1iuSxHJjBWhp2wjYjDBHF/kPk2//hi+ey5dLFPOdMuq6z3vQBVZQ== X-Received: by 2002:a17:90a:1743:: with SMTP id 3mr17665818pjm.106.1589142718563; Sun, 10 May 2020 13:31:58 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id m18sm8082218pjl.14.2020.05.10.13.31.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:31:57 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 17/18] mtd: Support kmsg dumper based on pstore/blk Date: Sun, 10 May 2020 13:24:35 -0700 Message-Id: <20200510202436.63222-18-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_133159_270270_FC998EDA X-CRM114-Status: GOOD ( 27.25 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: WeiXiong Liao This introduces mtdpstore, which is similar to mtdoops but more powerful. It uses pstore/blk, and aims to store panic and oops logs to a flash partition, where pstore can later read back and present as files in the mounted pstore filesystem. To make mtdpstore work, the "blkdev" of pstore/blk should be set as MTD device name or MTD device number. For more details, see Documentation/admin-guide/pstore-blk.rst This solves a number of issues: - Work duplication: both of pstore and mtdoops do the same job storing panic/oops log. They have very similar logic, registering to kmsg dumper and storing logs to several chunks one by one. - Layer violations: drivers should provides methods instead of polices. MTD should provide read/write/erase operations, and allow a higher level drivers to provide the chunk management, kmsg dump configuration, etc. - Missing features: pstore provides many additional features, including presenting the logs as files, logging dump time and count, and supporting other frontends like pmsg, console, etc. Signed-off-by: WeiXiong Liao Link: https://lore.kernel.org/r/1585126506-18635-12-git-send-email-liaoweixiong@allwinnertech.com Signed-off-by: Kees Cook --- Documentation/admin-guide/pstore-blk.rst | 9 +- drivers/mtd/Kconfig | 10 + drivers/mtd/Makefile | 1 + drivers/mtd/mtdpstore.c | 564 +++++++++++++++++++++++ 4 files changed, 582 insertions(+), 2 deletions(-) create mode 100644 drivers/mtd/mtdpstore.c diff --git a/Documentation/admin-guide/pstore-blk.rst b/Documentation/admin-guide/pstore-blk.rst index d45341e55e82..296d5027787a 100644 --- a/Documentation/admin-guide/pstore-blk.rst +++ b/Documentation/admin-guide/pstore-blk.rst @@ -43,9 +43,9 @@ blkdev ~~~~~~ The block device to use. Most of the time, it is a partition of block device. -It's required for pstore/blk. +It's required for pstore/blk. It is also used for MTD device. -It accepts the following variants: +It accepts the following variants for block device: 1. device number in hexadecimal represents itself; no leading 0x, for example b302. @@ -64,6 +64,11 @@ It accepts the following variants: partition with a known unique id. #. : major and minor number of the device separated by a colon. +It accepts the following variants for MTD device: + +1. MTD device name. "pstore" is recommended. +#. MTD device number. + kmsg_size ~~~~~~~~~ diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 42d401ea60ee..6ddab796216d 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -170,6 +170,16 @@ config MTD_OOPS buffer in a flash partition where it can be read back at some later point. +config MTD_PSTORE + tristate "Log panic/oops to an MTD buffer based on pstore" + depends on PSTORE_BLK + help + This enables panic and oops messages to be logged to a circular + buffer in a flash partition where it can be read back as files after + mounting pstore filesystem. + + If unsure, say N. + config MTD_SWAP tristate "Swap on MTD device support" depends on MTD && SWAP diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 56cc60ccc477..593d0593a038 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o obj-$(CONFIG_SSFDC) += ssfdc.o obj-$(CONFIG_SM_FTL) += sm_ftl.o obj-$(CONFIG_MTD_OOPS) += mtdoops.o +obj-$(CONFIG_MTD_PSTORE) += mtdpstore.o obj-$(CONFIG_MTD_SWAP) += mtdswap.o nftl-objs := nftlcore.o nftlmount.o diff --git a/drivers/mtd/mtdpstore.c b/drivers/mtd/mtdpstore.c new file mode 100644 index 000000000000..ce6da4d04864 --- /dev/null +++ b/drivers/mtd/mtdpstore.c @@ -0,0 +1,564 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define dev_fmt(fmt) "mtdoops-pstore: " fmt + +#include +#include +#include +#include +#include + +static struct mtdpstore_context { + int index; + struct pstore_blk_config info; + struct pstore_device_info dev; + struct mtd_info *mtd; + unsigned long *rmmap; /* removed bit map */ + unsigned long *usedmap; /* used bit map */ + /* + * used for panic write + * As there are no block_isbad for panic case, we should keep this + * status before panic to ensure panic_write not failed. + */ + unsigned long *badmap; /* bad block bit map */ +} oops_cxt; + +static int mtdpstore_block_isbad(struct mtdpstore_context *cxt, loff_t off) +{ + int ret; + struct mtd_info *mtd = cxt->mtd; + u64 blknum = div_u64(off, mtd->erasesize); + + if (test_bit(blknum, cxt->badmap)) + return true; + ret = mtd_block_isbad(mtd, off); + if (ret < 0) { + dev_err(&mtd->dev, "mtd_block_isbad failed, aborting\n"); + return ret; + } else if (ret > 0) { + set_bit(blknum, cxt->badmap); + return true; + } + return false; +} + +static inline int mtdpstore_panic_block_isbad(struct mtdpstore_context *cxt, + loff_t off) +{ + struct mtd_info *mtd = cxt->mtd; + u64 blknum = div_u64(off, mtd->erasesize); + + return test_bit(blknum, cxt->badmap); +} + +static inline void mtdpstore_mark_used(struct mtdpstore_context *cxt, + loff_t off) +{ + struct mtd_info *mtd = cxt->mtd; + u64 zonenum = div_u64(off, cxt->info.kmsg_size); + + dev_dbg(&mtd->dev, "mark zone %llu used\n", zonenum); + set_bit(zonenum, cxt->usedmap); +} + +static inline void mtdpstore_mark_unused(struct mtdpstore_context *cxt, + loff_t off) +{ + struct mtd_info *mtd = cxt->mtd; + u64 zonenum = div_u64(off, cxt->info.kmsg_size); + + dev_dbg(&mtd->dev, "mark zone %llu unused\n", zonenum); + clear_bit(zonenum, cxt->usedmap); +} + +static inline void mtdpstore_block_mark_unused(struct mtdpstore_context *cxt, + loff_t off) +{ + struct mtd_info *mtd = cxt->mtd; + u64 zonenum = div_u64(off, cxt->info.kmsg_size); + u32 zonecnt = cxt->mtd->erasesize / cxt->info.kmsg_size; + + while (zonecnt > 0) { + dev_dbg(&mtd->dev, "mark zone %llu unused\n", zonenum); + clear_bit(zonenum, cxt->usedmap); + zonenum++; + zonecnt--; + } +} + +static inline int mtdpstore_is_used(struct mtdpstore_context *cxt, loff_t off) +{ + u64 zonenum = div_u64(off, cxt->info.kmsg_size); + u64 blknum = div_u64(off, cxt->mtd->erasesize); + + if (test_bit(blknum, cxt->badmap)) + return true; + return test_bit(zonenum, cxt->usedmap); +} + +static int mtdpstore_block_is_used(struct mtdpstore_context *cxt, + loff_t off) +{ + u64 zonenum = div_u64(off, cxt->info.kmsg_size); + u32 zonecnt = cxt->mtd->erasesize / cxt->info.kmsg_size; + + while (zonecnt > 0) { + if (test_bit(zonenum, cxt->usedmap)) + return true; + zonenum++; + zonecnt--; + } + return false; +} + +static int mtdpstore_is_empty(struct mtdpstore_context *cxt, char *buf, + size_t size) +{ + struct mtd_info *mtd = cxt->mtd; + size_t sz; + int i; + + sz = min_t(uint32_t, size, mtd->writesize / 4); + for (i = 0; i < sz; i++) { + if (buf[i] != (char)0xFF) + return false; + } + return true; +} + +static void mtdpstore_mark_removed(struct mtdpstore_context *cxt, loff_t off) +{ + struct mtd_info *mtd = cxt->mtd; + u64 zonenum = div_u64(off, cxt->info.kmsg_size); + + dev_dbg(&mtd->dev, "mark zone %llu removed\n", zonenum); + set_bit(zonenum, cxt->rmmap); +} + +static void mtdpstore_block_clear_removed(struct mtdpstore_context *cxt, + loff_t off) +{ + u64 zonenum = div_u64(off, cxt->info.kmsg_size); + u32 zonecnt = cxt->mtd->erasesize / cxt->info.kmsg_size; + + while (zonecnt > 0) { + clear_bit(zonenum, cxt->rmmap); + zonenum++; + zonecnt--; + } +} + +static int mtdpstore_block_is_removed(struct mtdpstore_context *cxt, + loff_t off) +{ + u64 zonenum = div_u64(off, cxt->info.kmsg_size); + u32 zonecnt = cxt->mtd->erasesize / cxt->info.kmsg_size; + + while (zonecnt > 0) { + if (test_bit(zonenum, cxt->rmmap)) + return true; + zonenum++; + zonecnt--; + } + return false; +} + +static int mtdpstore_erase_do(struct mtdpstore_context *cxt, loff_t off) +{ + struct mtd_info *mtd = cxt->mtd; + struct erase_info erase; + int ret; + + dev_dbg(&mtd->dev, "try to erase off 0x%llx\n", off); + erase.len = cxt->mtd->erasesize; + erase.addr = off; + ret = mtd_erase(cxt->mtd, &erase); + if (!ret) + mtdpstore_block_clear_removed(cxt, off); + else + dev_err(&mtd->dev, "erase of region [0x%llx, 0x%llx] on \"%s\" failed\n", + (unsigned long long)erase.addr, + (unsigned long long)erase.len, cxt->info.device); + return ret; +} + +/* + * called while removing file + * + * Avoiding over erasing, do erase block only when the whole block is unused. + * If the block contains valid log, do erase lazily on flush_removed() when + * unregister. + */ +static ssize_t mtdpstore_erase(size_t size, loff_t off) +{ + struct mtdpstore_context *cxt = &oops_cxt; + + if (mtdpstore_block_isbad(cxt, off)) + return -EIO; + + mtdpstore_mark_unused(cxt, off); + + /* If the block still has valid data, mtdpstore do erase lazily */ + if (likely(mtdpstore_block_is_used(cxt, off))) { + mtdpstore_mark_removed(cxt, off); + return 0; + } + + /* all zones are unused, erase it */ + off = ALIGN_DOWN(off, cxt->mtd->erasesize); + return mtdpstore_erase_do(cxt, off); +} + +/* + * What is security for mtdpstore? + * As there is no erase for panic case, we should ensure at least one zone + * is writable. Otherwise, panic write will fail. + * If zone is used, write operation will return -ENOMSG, which means that + * pstore/blk will try one by one until gets an empty zone. So, it is not + * needed to ensure the next zone is empty, but at least one. + */ +static int mtdpstore_security(struct mtdpstore_context *cxt, loff_t off) +{ + int ret = 0, i; + struct mtd_info *mtd = cxt->mtd; + u32 zonenum = (u32)div_u64(off, cxt->info.kmsg_size); + u32 zonecnt = (u32)div_u64(cxt->mtd->size, cxt->info.kmsg_size); + u32 blkcnt = (u32)div_u64(cxt->mtd->size, cxt->mtd->erasesize); + u32 erasesize = cxt->mtd->erasesize; + + for (i = 0; i < zonecnt; i++) { + u32 num = (zonenum + i) % zonecnt; + + /* found empty zone */ + if (!test_bit(num, cxt->usedmap)) + return 0; + } + + /* If there is no any empty zone, we have no way but to do erase */ + off = ALIGN_DOWN(off, erasesize); + while (blkcnt--) { + div64_u64_rem(off + erasesize, cxt->mtd->size, (u64 *)&off); + + if (mtdpstore_block_isbad(cxt, off)) + continue; + + ret = mtdpstore_erase_do(cxt, off); + if (!ret) { + mtdpstore_block_mark_unused(cxt, off); + break; + } + } + + if (ret) + dev_err(&mtd->dev, "all blocks bad!\n"); + dev_dbg(&mtd->dev, "end security\n"); + return ret; +} + +static ssize_t mtdpstore_write(const char *buf, size_t size, loff_t off) +{ + struct mtdpstore_context *cxt = &oops_cxt; + struct mtd_info *mtd = cxt->mtd; + size_t retlen; + int ret; + + if (mtdpstore_block_isbad(cxt, off)) + return -ENOMSG; + + /* zone is used, please try next one */ + if (mtdpstore_is_used(cxt, off)) + return -ENOMSG; + + dev_dbg(&mtd->dev, "try to write off 0x%llx size %zu\n", off, size); + ret = mtd_write(cxt->mtd, off, size, &retlen, (u_char *)buf); + if (ret < 0 || retlen != size) { + dev_err(&mtd->dev, "write failure at %lld (%zu of %zu written), err %d\n", + off, retlen, size, ret); + return -EIO; + } + mtdpstore_mark_used(cxt, off); + + mtdpstore_security(cxt, off); + return retlen; +} + +static inline bool mtdpstore_is_io_error(int ret) +{ + return ret < 0 && !mtd_is_bitflip(ret) && !mtd_is_eccerr(ret); +} + +/* + * All zones will be read as pstore/blk will read zone one by one when do + * recover. + */ +static ssize_t mtdpstore_read(char *buf, size_t size, loff_t off) +{ + struct mtdpstore_context *cxt = &oops_cxt; + struct mtd_info *mtd = cxt->mtd; + size_t retlen, done; + int ret; + + if (mtdpstore_block_isbad(cxt, off)) + return -ENOMSG; + + dev_dbg(&mtd->dev, "try to read off 0x%llx size %zu\n", off, size); + for (done = 0, retlen = 0; done < size; done += retlen) { + retlen = 0; + + ret = mtd_read(cxt->mtd, off + done, size - done, &retlen, + (u_char *)buf + done); + if (mtdpstore_is_io_error(ret)) { + dev_err(&mtd->dev, "read failure at %lld (%zu of %zu read), err %d\n", + off + done, retlen, size - done, ret); + /* the zone may be broken, try next one */ + return -ENOMSG; + } + + /* + * ECC error. The impact on log data is so small. Maybe we can + * still read it and try to understand. So mtdpstore just hands + * over what it gets and user can judge whether the data is + * valid or not. + */ + if (mtd_is_eccerr(ret)) { + dev_err(&mtd->dev, "ecc error at %lld (%zu of %zu read), err %d\n", + off + done, retlen, size - done, ret); + /* driver may not set retlen when ecc error */ + retlen = retlen == 0 ? size - done : retlen; + } + } + + if (mtdpstore_is_empty(cxt, buf, size)) + mtdpstore_mark_unused(cxt, off); + else + mtdpstore_mark_used(cxt, off); + + mtdpstore_security(cxt, off); + return retlen; +} + +static ssize_t mtdpstore_panic_write(const char *buf, size_t size, loff_t off) +{ + struct mtdpstore_context *cxt = &oops_cxt; + struct mtd_info *mtd = cxt->mtd; + size_t retlen; + int ret; + + if (mtdpstore_panic_block_isbad(cxt, off)) + return -ENOMSG; + + /* zone is used, please try next one */ + if (mtdpstore_is_used(cxt, off)) + return -ENOMSG; + + ret = mtd_panic_write(cxt->mtd, off, size, &retlen, (u_char *)buf); + if (ret < 0 || size != retlen) { + dev_err(&mtd->dev, "panic write failure at %lld (%zu of %zu read), err %d\n", + off, retlen, size, ret); + return -EIO; + } + mtdpstore_mark_used(cxt, off); + + return retlen; +} + +static void mtdpstore_notify_add(struct mtd_info *mtd) +{ + int ret; + struct mtdpstore_context *cxt = &oops_cxt; + struct pstore_blk_config *info = &cxt->info; + unsigned long longcnt; + + if (!strcmp(mtd->name, info->device)) + cxt->index = mtd->index; + + if (mtd->index != cxt->index || cxt->index < 0) + return; + + dev_dbg(&mtd->dev, "found matching MTD device %s\n", mtd->name); + + if (mtd->size < info->kmsg_size * 2) { + dev_err(&mtd->dev, "MTD partition %d not big enough\n", + mtd->index); + return; + } + /* + * kmsg_size must be aligned to 4096 Bytes, which is limited by + * psblk. The default value of kmsg_size is 64KB. If kmsg_size + * is larger than erasesize, some errors will occur since mtdpsotre + * is designed on it. + */ + if (mtd->erasesize < info->kmsg_size) { + dev_err(&mtd->dev, "eraseblock size of MTD partition %d too small\n", + mtd->index); + return; + } + if (unlikely(info->kmsg_size % mtd->writesize)) { + dev_err(&mtd->dev, "record size %lu KB must align to write size %d KB\n", + info->kmsg_size / 1024, + mtd->writesize / 1024); + return; + } + + longcnt = BITS_TO_LONGS(div_u64(mtd->size, info->kmsg_size)); + cxt->rmmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + cxt->usedmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + + longcnt = BITS_TO_LONGS(div_u64(mtd->size, mtd->erasesize)); + cxt->badmap = kcalloc(longcnt, sizeof(long), GFP_KERNEL); + + cxt->dev.total_size = mtd->size; + /* just support dmesg right now */ + cxt->dev.flags = PSTORE_FLAGS_DMESG; + cxt->dev.read = mtdpstore_read; + cxt->dev.write = mtdpstore_write; + cxt->dev.erase = mtdpstore_erase; + cxt->dev.panic_write = mtdpstore_panic_write; + + ret = register_pstore_device(&cxt->dev); + if (ret) { + dev_err(&mtd->dev, "mtd%d register to psblk failed\n", + mtd->index); + return; + } + cxt->mtd = mtd; + dev_info(&mtd->dev, "Attached to MTD device %d\n", mtd->index); +} + +static int mtdpstore_flush_removed_do(struct mtdpstore_context *cxt, + loff_t off, size_t size) +{ + struct mtd_info *mtd = cxt->mtd; + u_char *buf; + int ret; + size_t retlen; + struct erase_info erase; + + buf = kmalloc(mtd->erasesize, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* 1st. read to cache */ + ret = mtd_read(mtd, off, mtd->erasesize, &retlen, buf); + if (mtdpstore_is_io_error(ret)) + goto free; + + /* 2nd. erase block */ + erase.len = mtd->erasesize; + erase.addr = off; + ret = mtd_erase(mtd, &erase); + if (ret) + goto free; + + /* 3rd. write back */ + while (size) { + unsigned int zonesize = cxt->info.kmsg_size; + + /* there is valid data on block, write back */ + if (mtdpstore_is_used(cxt, off)) { + ret = mtd_write(mtd, off, zonesize, &retlen, buf); + if (ret) + dev_err(&mtd->dev, "write failure at %lld (%zu of %u written), err %d\n", + off, retlen, zonesize, ret); + } + + off += zonesize; + size -= min_t(unsigned int, zonesize, size); + } + +free: + kfree(buf); + return ret; +} + +/* + * What does mtdpstore_flush_removed() do? + * When user remove any log file on pstore filesystem, mtdpstore should do + * something to ensure log file removed. If the whole block is no longer used, + * it's nice to erase the block. However if the block still contains valid log, + * what mtdpstore can do is to erase and write the valid log back. + */ +static int mtdpstore_flush_removed(struct mtdpstore_context *cxt) +{ + struct mtd_info *mtd = cxt->mtd; + int ret; + loff_t off; + u32 blkcnt = (u32)div_u64(mtd->size, mtd->erasesize); + + for (off = 0; blkcnt > 0; blkcnt--, off += mtd->erasesize) { + ret = mtdpstore_block_isbad(cxt, off); + if (ret) + continue; + + ret = mtdpstore_block_is_removed(cxt, off); + if (!ret) + continue; + + ret = mtdpstore_flush_removed_do(cxt, off, mtd->erasesize); + if (ret) + return ret; + } + return 0; +} + +static void mtdpstore_notify_remove(struct mtd_info *mtd) +{ + struct mtdpstore_context *cxt = &oops_cxt; + + if (mtd->index != cxt->index || cxt->index < 0) + return; + + mtdpstore_flush_removed(cxt); + + unregister_pstore_device(&cxt->dev); + kfree(cxt->badmap); + kfree(cxt->usedmap); + kfree(cxt->rmmap); + cxt->mtd = NULL; + cxt->index = -1; +} + +static struct mtd_notifier mtdpstore_notifier = { + .add = mtdpstore_notify_add, + .remove = mtdpstore_notify_remove, +}; + +static int __init mtdpstore_init(void) +{ + int ret; + struct mtdpstore_context *cxt = &oops_cxt; + struct mtd_info *mtd = cxt->mtd; + struct pstore_blk_config *info = &cxt->info; + + ret = pstore_blk_get_config(info); + if (unlikely(ret)) + return ret; + + if (strlen(info->device) == 0) { + dev_err(&mtd->dev, "mtd device must be supplied\n"); + return -EINVAL; + } + if (!info->kmsg_size) { + dev_err(&mtd->dev, "no backend enabled\n"); + return -EINVAL; + } + + /* Setup the MTD device to use */ + ret = kstrtoint((char *)info->device, 0, &cxt->index); + if (ret) + cxt->index = -1; + + register_mtd_user(&mtdpstore_notifier); + return 0; +} +module_init(mtdpstore_init); + +static void __exit mtdpstore_exit(void) +{ + unregister_mtd_user(&mtdpstore_notifier); +} +module_exit(mtdpstore_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("WeiXiong Liao "); +MODULE_DESCRIPTION("MTD backend for pstore/blk"); From patchwork Sun May 10 20:24:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 1287367 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20170209 header.b=gzOACzhG; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Fw8KyfeR; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49Kwj13rRbz9sSm for ; Mon, 11 May 2020 06:32:05 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=jGLvFoNtFLp4OkqLUMTQBFQ+8lFYOdpN+dKmwbAAs90=; b=gzOACzhGogBQNy jtx8Bm/j5etoQwBTPIqZNhpdJxc6+y1JjlVsLTzWgldKHZqEw9lhN3AVr9yppvQXDicQP4D86MA86 z+3pgm4xyRVYOTUqVOTMf5p3EwTPEGORMP6VdCy+HKN/43+nIXyr66XtxIVI0v7QDRB4dwZ4/OUzo 6C5TfJFEsu+o7KBOZPG3c2rCkBGnPdrVHfaZ4o6jqCZnqcFKpETX/SCyQlPoPBNZq0yHQCr4XGpQH dFxb7b+7QtFgrHlhiylhFVUOEZNu7jeYXdjmrsT0D/hnVwjVR4+kFO8rm80n2KxA04RS7qJvO/zEK Os/Rs9f3OA7mstNIUu7w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXscD-0004DC-3I; Sun, 10 May 2020 20:32:01 +0000 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jXsc9-0004Bp-Kr for linux-mtd@lists.infradead.org; Sun, 10 May 2020 20:31:58 +0000 Received: by mail-pg1-x541.google.com with SMTP id l12so3546373pgr.10 for ; Sun, 10 May 2020 13:31:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=IGhCzVMcFSG8RfD2dnuoWGbvQKbAh3BbNL764FWITOg=; b=Fw8KyfeRY2o+iHX91RUx34YBABbxf6VuNlYyNsnrWdXif3s/ACuQVflYL+CJptaAuw gTkwG01vIwsxYH9f/tLpXxU2UnH3b3f+//pWjovG+r86XkEYeKe1/MFAGtf/PMTdBtIm McUum85+3EHfgMNTrU3qDsZ2l6EjV1jWiANN8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=IGhCzVMcFSG8RfD2dnuoWGbvQKbAh3BbNL764FWITOg=; b=eiDHEFZq4h2CiEmR6/GH6p3ATI5Q2t6GZgl7tGgjM9CzUAXj2U2s3RGOVC5iWBLnbM 3qH3bSD01UEUjm1cq5cePm1BWWVVOtzTzbbwxGhX+Ajb/qhLTSBw7e+Bnon/As8skn0Q fsgfHltg+VxZkRcZ+zyHNiGpfsHo3Q4AscLd8K5IH6+6dJL+aobofBe++Dts+K4lk8ts UDVrcxt6UOhg4npLXgwfL/1RYq4Ug3lImEMQWl2eCEl//3DTMNJdp9dkdcM3s4dT47gr bwrAjiS5oI62HfMgcuKoH+ziRp1t9MJ6WXaIEqPbyobQrxdNxjYvOLoA5U6ZnrxFhMcE vwzw== X-Gm-Message-State: AGi0Pub7aQmko4SLoEnJbEcMAVrc+d7XNQZwRoDIlEiSOkrMK0GDxyxg Pi4v5mb/gxTrWDjpk4TiRFp6bA== X-Google-Smtp-Source: APiQypJsRU9h+Mob7IV8V9hVnNZaLYlsu6I2Ml5FQNRy6o1udqUOVm9mMtwEsQaiHAaxP5NUL+g+Lg== X-Received: by 2002:a63:dd51:: with SMTP id g17mr10543432pgj.2.1589142717130; Sun, 10 May 2020 13:31:57 -0700 (PDT) Received: from www.outflux.net (smtp.outflux.net. [198.145.64.163]) by smtp.gmail.com with ESMTPSA id f30sm8149570pje.29.2020.05.10.13.31.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 13:31:56 -0700 (PDT) From: Kees Cook To: WeiXiong Liao Subject: [PATCH v7 18/18] pstore/blk: Introduce "best_effort" mode Date: Sun, 10 May 2020 13:24:36 -0700 Message-Id: <20200510202436.63222-19-keescook@chromium.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200510202436.63222-1-keescook@chromium.org> References: <20200510202436.63222-1-keescook@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200510_133157_706419_B9867F41 X-CRM114-Status: GOOD ( 13.34 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.4 on bombadil.infradead.org summary: Content analysis details: (-0.4 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:541 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.2 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Petr Mladek , Tony Luck , Kees Cook , Jonathan Corbet , Richard Weinberger , Anton Vorontsov , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Steven Rostedt , Sergey Senozhatsky , Colin Cross , linux-mtd@lists.infradead.org, Miquel Raynal , Pavel Tatashin , Rob Herring , Vignesh Raghavendra Sender: "linux-mtd" Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org In order to use arbitrary block devices as a pstore backend, provide a new module param named "best_effort", which will allow using any block device, even if it has not provided a panic_write callback. Signed-off-by: Kees Cook --- fs/pstore/blk.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c index 0dea8ded2de2..ad46860d5a78 100644 --- a/fs/pstore/blk.c +++ b/fs/pstore/blk.c @@ -51,6 +51,10 @@ static long ftrace_size = -1; module_param(ftrace_size, long, 0400); MODULE_PARM_DESC(ftrace_size, "ftrace size in kbytes"); +static bool best_effort; +module_param(best_effort, bool, 0400); +MODULE_PARM_DESC(best_effort, "use best effort to write (i.e. do not require storage driver pstore support, default: off)"); + /* * blkdev - the block device to use for pstore storage * @@ -376,7 +380,8 @@ static int __register_pstore_blk(struct pstore_blk_info *info) } /* only allow driver matching the @blkdev */ - if (!binfo.devt || MAJOR(binfo.devt) != info->major) { + if (!binfo.devt || (!best_effort && + MAJOR(binfo.devt) != info->major)) { pr_debug("invalid major %u (expect %u)\n", info->major, MAJOR(binfo.devt)); ret = -ENODEV; @@ -479,6 +484,20 @@ int pstore_blk_get_config(struct pstore_blk_config *info) } EXPORT_SYMBOL_GPL(pstore_blk_get_config); +static int __init pstore_blk_init(void) +{ + struct pstore_blk_info info = { }; + int ret = 0; + + mutex_lock(&pstore_blk_lock); + if (!pstore_zone_info && best_effort && blkdev[0]) + ret = __register_pstore_blk(&info); + mutex_unlock(&pstore_blk_lock); + + return ret; +} +late_initcall(pstore_blk_init); + static void __exit pstore_blk_exit(void) { mutex_lock(&pstore_blk_lock);