Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp640579imu; Wed, 23 Jan 2019 03:04:36 -0800 (PST) X-Google-Smtp-Source: ALg8bN5mCmgkwCI9H4wIly8j7HF3G+mpBmrc/4/wYok8MoWlu10KeV1kedxSKTy3vYiovZhqUY/B X-Received: by 2002:a63:2406:: with SMTP id k6mr1492139pgk.229.1548241476853; Wed, 23 Jan 2019 03:04:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548241476; cv=none; d=google.com; s=arc-20160816; b=rhQoyV4UcNf+YdLZGm+hNqsSMYuZZ96PQY6o0wGwu7TA3693acI8ig/CqzVqV69AcU DS60EPyOxE5/TqrH9IxsWl091QWPlxBDxDOIQGV78gSmbkAmhyNQpt1qGBZIy+LzdUX7 hMHV6/kVIiGvi6AF8Iq2CaByy5irZSpV16aVN543auyF27OVoH8Q5qzoBwkwRRPpHaJH eppqzK3yNZrY+bVNV0sI5qVg2AR5/qUZOKMl5pNSRMoNRwypxeeE6fG0Q4dlEHXU2VIM 3Sgq97ZknlB8BsTXTo59qKisFE5fGr+WRpWjiA2wuZ/TMnooN8tbIBXMajWUHFH/ZIpV balA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=d063T8ShszL3L2O+W975cTFuQ2J+np9kVXbJeSQH2hY=; b=MXGjpw6nM8dUwh/3P3HVgF94l00PhCrPmRNwGKGK1Q0hL6IL4Pjcv6simnZT0kJ1n8 BhshBEefo8wshNBPya1ZV8pLa6/oe2Mgujd/gwXHBTd/VUPOEPbKViJXhwP26KKTq8iG s9oBPT5pW8q5lhHLhzjO3k3xMulgx28M8pwQK+p059hSHg+K0TxW3aKhrjWO9ptm/3Qs Y/EYUHnWANwr1neqoAyazk7/nQElDOoeCDKyf0Y9IW9npntc/Zp9w4PFZIiYTmHzUmne oSdfUbCODFI93Im4JDuB4r6+s9RJWSCfdTAun/DTq5VxxQcYoOwXUakA7lEEaOUHI1/p NErQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 23si18042554pfk.287.2019.01.23.03.04.21; Wed, 23 Jan 2019 03:04:36 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727512AbfAWLBv (ORCPT + 99 others); Wed, 23 Jan 2019 06:01:51 -0500 Received: from smtp2207-205.mail.aliyun.com ([121.197.207.205]:38555 "EHLO smtp2207-205.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727410AbfAWLBs (ORCPT ); Wed, 23 Jan 2019 06:01:48 -0500 X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436282|-1;CH=green;FP=0|0|0|0|0|-1|-1|-1;HT=e02c03298;MF=liaoweixiong@allwinnertech.com;NM=1;PH=DS;RN=17;RT=17;SR=0;TI=SMTPD_---.Dpcewgu_1548241289; Received: from PC-liaoweixiong.allwinnertech.com(mailfrom:liaoweixiong@allwinnertech.com fp:SMTPD_---.Dpcewgu_1548241289) by smtp.aliyun-inc.com(10.147.42.198); Wed, 23 Jan 2019 19:01:41 +0800 From: liaoweixiong To: Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , Jonathan Corbet , Rob Herring , Mark Rutland , Mauro Carvalho Chehab , Greg Kroah-Hartman , "David S. Miller" , Andrew Morton , Nicolas Ferre , Arnd Bergmann Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, liaoweixiong Subject: [RFC v6 2/4] pstore/blk: add blkoops for pstore_blk Date: Wed, 23 Jan 2019 19:00:58 +0800 Message-Id: <1548241260-4679-3-git-send-email-liaoweixiong@allwinnertech.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1548241260-4679-1-git-send-email-liaoweixiong@allwinnertech.com> References: <1548241260-4679-1-git-send-email-liaoweixiong@allwinnertech.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org blkoops is a sample for pstore/blk. It can only record oops, excluding panics as no read/write apis for panic registered. It support settings on Kconfg/device tree/module parameters. It can record oops log even power failure if "PSTORE_BLKOOPS_PART_PATH" on Kconfig or "partition-path" on dts or "part_path" on module parameter is valid. Otherwise, it can only record data to ram buffer, which will be dropped when reboot. Signed-off-by: liaoweixiong --- .../devicetree/bindings/pstore-block/blkoops.txt | 32 +++ MAINTAINERS | 3 +- fs/pstore/Kconfig | 117 ++++++++++ fs/pstore/Makefile | 2 + fs/pstore/blkoops.c | 239 +++++++++++++++++++++ 5 files changed, 392 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/pstore-block/blkoops.txt create mode 100644 fs/pstore/blkoops.c diff --git a/Documentation/devicetree/bindings/pstore-block/blkoops.txt b/Documentation/devicetree/bindings/pstore-block/blkoops.txt new file mode 100644 index 0000000..a25835b --- /dev/null +++ b/Documentation/devicetree/bindings/pstore-block/blkoops.txt @@ -0,0 +1,32 @@ +Blkoops oops logger +=================== + +Blkoops provides a block partition for oops, excluding panics now, so they can +be recovered after a reboot. + +Any space of block partition will be used for a circular buffer of oops records. +These records have a configurable size, with a size of 0 indicating that they +should be disabled. + +"partition-size" and at least one of "dmesg-size" or "pmsg-size" must be set +non-zero, but are otherwise optional as listed below. + +Blkoops will take value from Kconfig if device tree do not set, but settings +from module parameters can also overwrite them. + +Required properties: + +- compatible: must be "blkoops". + +- partition-size: size in kbytes, must be a multiple of 4. + +Optional properties: + +- partition-path: strings must begin with "/dev", tell blkoops which partition + it can used. If it is not set, blkoops will drop all data when reboot. + +- dmesg-size: maximum size in kbytes of each dump done on oops, which must be a + multiple of 4. + +- pmsg-size: maximum size in kbytes for userspace messages, which must be a + multiple of 4. diff --git a/MAINTAINERS b/MAINTAINERS index 0abecc5..534c574 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12055,7 +12055,8 @@ F: drivers/firmware/efi/efi-pstore.c F: drivers/acpi/apei/erst.c F: Documentation/admin-guide/ramoops.rst F: Documentation/devicetree/bindings/reserved-memory/ramoops.txt -K: \b(pstore|ramoops) +F: Documentation/devicetree/bindings/pstore-block/ +K: \b(pstore|ramoops|blkoops) PTP HARDWARE CLOCK SUPPORT M: Richard Cochran diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index a881c53..f0a1a49 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -159,3 +159,120 @@ config PSTORE_BLK help This enables panic and oops message to be logged to a block dev where it can be read back at some later point. + +config PSTORE_BLKOOPS + tristate "pstore block with oops logger" + depends on PSTORE_BLK + help + This is a sample for pstore block with oops logger. + + It CANNOT record panic log as no read/write apis for panic registered. + + It CAN record oops log even power failure if + "PSTORE_BLKOOPS_PART_PATH" on Kconfig or "partition-path" on dts or + "part_path" on module parameter is valid. + + Otherwise, it can only record data to ram buffer, which will be + dropped when reboot. + + NOTE that, there are three ways to set parameters of blkoops and + prioritize according to configuration flexibility. That is + Kconfig < device tree < module parameters. It means that the value can + be overwritten by higher priority settings. + 1. Kconfig + It just sets a default value. + 2. device tree + It is set on device tree, which will overwrites value from Kconfig, + but can also be overwritten by module parameters. + 3. module parameters + It is the first priority. Take care of that blkoops will take lower + priority settings if higher priority one do not set. + +config PSTORE_BLKOOPS_DMESG_SIZE + int "dmesg_size in kbytes for blkoops" + depends on PSTORE_BLKOOPS + default 64 + help + This just sets size of dmesg (dmesg_size) for pstore/blk. The value + must be a multiple of 4096. + + NOTE that, there are three ways to set parameters of blkoops and + prioritize according to configuration flexibility. That is + Kconfig < device tree < module parameters. It means that the value can + be overwritten by higher priority settings. + 1. Kconfig + It just sets a default value. + 2. device tree + It is set on device tree, which will overwrites value from Kconfig, + but can also be overwritten by module parameters. + 3. module parameters + It is the first priority. Take care of that blkoops will take lower + priority settings if higher priority one do not set. + +config PSTORE_BLKOOPS_PMSG_SIZE + int "pmsg_size in kbytes for blkoops" + depends on PSTORE_BLKOOPS + default 64 + help + This just sets size of pmsg (pmsg_size) for pstore/blk. The value must + be a multiple of 4096. Pmsg work only if "part_path" is set. + + NOTE that, there are three ways to set parameters of blkoops and + prioritize according to configuration flexibility. That is + Kconfig < device tree < module parameters. It means that the value can + be overwritten by higher priority settings. + 1. Kconfig + It just sets a default value. + 2. device tree + It is set on device tree, which will overwrites value from Kconfig, + but can also be overwritten by module parameters. + 3. module parameters + It is the first priority. Take care of that blkoops will take lower + priority settings if higher priority one do not set. + +config PSTORE_BLKOOPS_PART_SIZE + int "part_size in kbytes for blkoops" + depends on PSTORE_BLKOOPS + default 1024 + help + This just sets partition size (part_size) for pstore/blk. Pstore/blk + will allocate part_size memory to temporarily hold the data. It's the + size of partition on part_path. The value must be a multiple of 4096. + + NOTE that, there are three ways to set parameters of blkoops and + prioritize according to configuration flexibility. That is + Kconfig < device tree < module parameters. It means that the value can + be overwritten by higher priority settings. + 1. Kconfig + It just sets a default value. + 2. device tree + It is set on device tree, which will overwrites value from Kconfig, + but can also be overwritten by module parameters. + 3. module parameters + It is the first priority. Take care of that blkoops will take lower + priority settings if higher priority one do not set. + +config PSTORE_BLKOOPS_PART_PATH + string "part_path for blkoops" + depends on PSTORE_BLKOOPS + default "" + help + This just sets partition path (part_path) for pstore/blk. Pstore/blk + will record data to this block partition to avoid losing data due to + power failure. So, If it is not set, pstore/blk will drop all data + when reboot. + + The strings must begin with "/dev/". + + NOTE that, there are three ways to set parameters of blkoops and + prioritize according to configuration flexibility. That is + Kconfig < device tree < module parameters. It means that the value can + be overwritten by higher priority settings. + 1. Kconfig + It just sets a default value. + 2. device tree + It is set on device tree, which will overwrites value from Kconfig, + but can also be overwritten by module parameters. + 3. module parameters + It is the first priority. Take care of that blkoops will take lower + priority settings if higher priority one do not set. diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile index 0ee2fc8..24b3d48 100644 --- a/fs/pstore/Makefile +++ b/fs/pstore/Makefile @@ -15,3 +15,5 @@ obj-$(CONFIG_PSTORE_RAM) += ramoops.o obj-$(CONFIG_PSTORE_BLK) += pstore_blk.o pstore_blk-y += blkzone.o + +obj-$(CONFIG_PSTORE_BLKOOPS) += blkoops.o diff --git a/fs/pstore/blkoops.c b/fs/pstore/blkoops.c new file mode 100644 index 0000000..fd926a5 --- /dev/null +++ b/fs/pstore/blkoops.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * + * blkoops.c: Block device Oops logger + * + * Copyright (C) 2019 liaoweixiong + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#define MODNAME "blkoops" +#define pr_fmt(fmt) MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +static long dmesg_size = -1; +module_param(dmesg_size, long, 0400); +MODULE_PARM_DESC(dmesg_size, "demsg size in kbytes"); + +static long part_size = -1; +module_param(part_size, long, 0400); +MODULE_PARM_DESC(part_size, "partition size in kbytes"); + +#define PART_PATH_INVALID "INVALID" +static char part_path[80] = {PART_PATH_INVALID}; +module_param_string(part_path, part_path, 80, 0400); +MODULE_PARM_DESC(part_path, "path of partition in /dev for general read/write"); + +struct blkz_info blkz_info = { + .owner = THIS_MODULE, + .name = "blkoops", + .dump_oops = true, +}; + +struct blkoops_info { + unsigned long dmesg_size; + unsigned long part_size; + const char *part_path; +}; +struct blkoops_info blkoops_info = { + .dmesg_size = CONFIG_PSTORE_BLKOOPS_DMESG_SIZE * 1024, + .part_size = CONFIG_PSTORE_BLKOOPS_PART_SIZE * 1024, + .part_path = CONFIG_PSTORE_BLKOOPS_PART_PATH, +}; + +static struct platform_device *dummy; + +static int blkoops_parse_dt_size(struct device_node *np, + const char *propname, u32 *value) +{ + u32 val32 = 0; + int ret; + + ret = of_property_read_u32(np, propname, &val32); + if (ret < 0) { + if (ret != -EINVAL) + pr_err("failed to parse property %s: %d\n", + propname, ret); + return ret; + } + + if (val32 * 1024 > INT_MAX) { + pr_err("%s %u > INT_MAX\n", propname, val32); + return -EOVERFLOW; + } + + *value = val32 * 1024; + return 0; +} + +static int __init blkoops_parse_dt(struct blkoops_info *info, + struct device_node *np) +{ + int ret; + u32 value; + + pr_info("using device tree\n"); + + ret = of_property_read_string(np, "partition-path", + &info->part_path); + if (ret < 0 && ret != -EINVAL) { + pr_err("failed to parse partition path : %d\n", ret); + return ret; + } + +#define parse_size(name, field) { \ + ret = blkoops_parse_dt_size(np, name, &value); \ + if (ret < 0 && ret != -EINVAL) \ + return ret; \ + else if (ret == 0) \ + field = value; \ + } + + parse_size("partition-size", info->part_size); + parse_size("dmesg-size", info->dmesg_size); + +#undef parse_size + return 0; +} + +static int blkoops_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *of_node = dev_of_node(dev); + struct blkoops_info *info = dev->platform_data; + + if (of_node && !info) { + int err; + + info = &blkoops_info; + err = blkoops_parse_dt(info, of_node); + if (err) + return err; + } + + if (!strcmp(info->part_path, PART_PATH_INVALID) || + strlen(info->part_path) == 0) { + pr_info("no path for block partition, use ram buffer only\n"); + } else if (strncmp(info->part_path, "/dev/", 5) != 0) { + pr_err("invalid partition path %s, use ram buffer only\n", + info->part_path); + } else { + pr_debug("path for block partition: %s\n", info->part_path); + blkz_info.part_path = info->part_path; + } + +#define check_size(name, size) { \ + if (info->name & (size - 1)) { \ + pr_err(#name " must be a multiple of %d\n", \ + (size)); \ + return -EINVAL; \ + } \ + blkz_info.name = info->name; \ + } + + check_size(part_size, 4096); + check_size(dmesg_size, 4096); + +#undef check_size + + /* + * Update the module parameter variables as well so they are visible + * through /sys/module/blkoops/parameters/ + */ + dmesg_size = blkz_info.dmesg_size; + part_size = blkz_info.part_size; + if (blkz_info.part_path) + strncpy(part_path, blkz_info.part_path, 80 - 1); + else + part_path[0] = '\0'; + return blkz_register(&blkz_info); +} + +static int blkoops_remove(struct platform_device *pdev) +{ + blkz_unregister(&blkz_info); + return 0; +} + +static const struct of_device_id dt_match[] = { + { .compatible = MODNAME}, + {} +}; + +static struct platform_driver blkoops_driver = { + .probe = blkoops_probe, + .remove = blkoops_remove, + .driver = { + .name = MODNAME, + .of_match_table = dt_match, + }, +}; + +void blkoops_register_dummy(void) +{ + struct blkoops_info *info = &blkoops_info; + /* + * Prepare a dummy platform data structure to carry the module + * parameters. If mem_size isn't set, then there are no module + * parameters, and we can skip this. + */ + if (part_size < 0) + return; + + pr_info("using module parameters\n"); + + info->part_size = (unsigned long)part_size * 1024; + if (strcmp(part_path, PART_PATH_INVALID)) + info->part_path = (const char *)part_path; + if (dmesg_size >= 0) + info->dmesg_size = (unsigned long)dmesg_size * 1024; + + dummy = platform_device_register_data(NULL, MODNAME, -1, info, + sizeof(*info)); + if (IS_ERR(dummy)) { + pr_err("could not create platform device: %ld\n", + PTR_ERR(dummy)); + dummy = NULL; + } +} + +static int __init blkoops_init(void) +{ + int ret; + + blkoops_register_dummy(); + ret = platform_driver_register(&blkoops_driver); + if (ret != 0) { + platform_device_unregister(dummy); + dummy = NULL; + } + return ret; +} +module_init(blkoops_init); + +static void __exit blkoops_exit(void) +{ + platform_driver_unregister(&blkoops_driver); + platform_device_unregister(dummy); + dummy = NULL; +} +module_exit(blkoops_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("liaoweixiong "); +MODULE_DESCRIPTION("Sample for Pstore BLK with Oops logger"); -- 1.9.1