Received: by 2002:ac0:8845:0:0:0:0:0 with SMTP id g63csp348986img; Thu, 28 Feb 2019 00:01:55 -0800 (PST) X-Google-Smtp-Source: AHgI3Ibw/37OCjMIhMw1mb0wMjRBPp9fqM/HA7Y+1nYCtOoh9GBW7zf2o/v1OF5Hoy4U8xDGtlX5 X-Received: by 2002:a63:9dc3:: with SMTP id i186mr7183941pgd.305.1551340915194; Thu, 28 Feb 2019 00:01:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551340915; cv=none; d=google.com; s=arc-20160816; b=QGAChghzGV29IesUQ8I7wGX/ZZwULQ/b6E+a2qADKprzxeibx5WH4o9FUoMW3oFeVR dQWp2dLM36doGdiMXd+xe2WjEllqutXiz/gRPkPk6RDIsjz5G69EiPI2nSVNztDh4WAP M3mhIqHhANiQ/6C9RlzuEu8dMqN7cvPHr5MMxDUnHOck1uQ5azJyIOZRlnvff1FT/RVF aA4wpzB22pG1nuKuJAeHVBY2l1zDOO3lKnqJ0iqpK39k56BizE+7ZSUgAbmEnF2g6aIn zOU7KQ8qGPXKVSHA22WCgIzy9T+WZM60PNRc5ZvtcWOTpnGqgt8s4X2vUjcEmUgf6m6z xQFA== 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=uS3ST+H8YsyROanBfXtOFV09kp94tXxwI6QK5w+cAoE=; b=c1ZQw5DMgqLQNmNkPBUvKPZg+Sj5FItqjtu/VOc85cVMpM8SsvYklf4/lERQTMOWx/ YW+e5yQ331JIMWAuRoGH218uIk9fdcf/qSUKAMsBuMMg1iqgH55SRbKzwA1xaMs/pCTv Cy0qr5Da6pn+TYF0c77fCyFPDSCM0e3pked9aoLSkz0MOmqaVSYLSfsIndDrQjgPHgpe hLs+aHrwX1CmuweLo45WPY2MeLKJtzBICI1X5UWTifDgBh4+UTqR1pk8P7MP8bKpaQ4S Yz4RJMVkfe0uepJHyediK5eaKp74upEz7K5OxWfdF9Xl4SZ0Q/7JvfO1EuWmKmtf89Zs 1hBg== 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 u19si17135348pga.567.2019.02.28.00.01.39; Thu, 28 Feb 2019 00:01:55 -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 S1731561AbfB1HMn (ORCPT + 99 others); Thu, 28 Feb 2019 02:12:43 -0500 Received: from smtp2207-205.mail.aliyun.com ([121.197.207.205]:49805 "EHLO smtp2207-205.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731532AbfB1HMk (ORCPT ); Thu, 28 Feb 2019 02:12:40 -0500 X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436282|-1;CH=green;DM=CONTINUE|CONTINUE|true|0.213033-0.175736-0.611232;FP=0|0|0|0|0|-1|-1|-1;HT=e01a16378;MF=liaoweixiong@allwinnertech.com;NM=1;PH=DS;RN=15;RT=15;SR=0;TI=SMTPD_---.E2MIXMl_1551337935; Received: from PC-liaoweixiong.allwinnertech.com(mailfrom:liaoweixiong@allwinnertech.com fp:SMTPD_---.E2MIXMl_1551337935) by smtp.aliyun-inc.com(10.147.40.44); Thu, 28 Feb 2019 15:12:24 +0800 From: liaoweixiong To: Kees Cook , Anton Vorontsov , Colin Cross , Tony Luck , Jonathan Corbet , Mauro Carvalho Chehab , "David S. Miller" , Greg Kroah-Hartman , Nicolas Ferre , Arnd Bergmann , Rob Herring , Randy Dunlap Cc: linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, liaoweixiong Subject: [PATCH v12 2/4] pstore/blk: add blkoops for pstore_blk Date: Thu, 28 Feb 2019 15:12:26 +0800 Message-Id: <1551337948-16451-3-git-send-email-liaoweixiong@allwinnertech.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1551337948-16451-1-git-send-email-liaoweixiong@allwinnertech.com> References: <1551337948-16451-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/module parameters. It can record oops log even power failure if "PSTORE_BLKOOPS_BLKDEV" on Kconfig or "blkdev" on module parameter is valid. Otherwise, it can only record data to ram buffer, which will be dropped when reboot. Signed-off-by: liaoweixiong --- MAINTAINERS | 2 +- fs/pstore/Kconfig | 114 ++++++++++++++++++++++++++ fs/pstore/Makefile | 2 + fs/pstore/blkoops.c | 198 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/pstore_blk.h | 14 +++- 5 files changed, 325 insertions(+), 5 deletions(-) create mode 100644 fs/pstore/blkoops.c diff --git a/MAINTAINERS b/MAINTAINERS index 51029a4..4e9242a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12318,7 +12318,7 @@ 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) +K: \b(pstore|ramoops|blkoops) PTP HARDWARE CLOCK SUPPORT M: Richard Cochran diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index defcb75..7dfe00b 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -160,3 +160,117 @@ 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_BLKDEV" on Kconfig or "block-device" on dts or + "blkdev" 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_TOTAL_SIZE + int "total size in kbytes for blkoops" + depends on PSTORE_BLKOOPS + default 0 + help + The total size in kbytes pstore/blk can use. It must be less than or + equal to size of block device if @blkdev valid. If @total_size is zero + with @blkdev, @total_size will be set to equal to size of @blkdev. + 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_BLKDEV + string "block device for blkoops" + depends on PSTORE_BLKOOPS + default "" + help + This just sets block device (blkdev) for pstore/blk. Pstore/blk + will record data to this block device to avoid losing data due to + power failure. So, If it is not set, pstore/blk will drop all data + when reboot. + + It accpet 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. + + 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..22c0c84 --- /dev/null +++ b/fs/pstore/blkoops.c @@ -0,0 +1,198 @@ +// 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 total_size = -1; +module_param(total_size, long, 0400); +MODULE_PARM_DESC(total_size, "total size in kbytes"); + +#define BLKDEV_INVALID "INVALID" +static char blkdev[80] = {BLKDEV_INVALID}; +module_param_string(blkdev, blkdev, 80, 0400); +MODULE_PARM_DESC(blkdev, "the block device 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 total_size; + const char *blkdev; +}; +struct blkoops_info blkoops_info = { + .dmesg_size = CONFIG_PSTORE_BLKOOPS_DMESG_SIZE * 1024, + .total_size = CONFIG_PSTORE_BLKOOPS_TOTAL_SIZE * 1024, + .blkdev = CONFIG_PSTORE_BLKOOPS_BLKDEV, +}; + +static struct platform_device *dummy; +DEFINE_SPINLOCK(modify_blkzinfo); + +/** + * Block driver use this function to add panic read/write apis to blkoops. + * By this, block driver can do the least work that just provides panic ops. + */ +int blkoops_add_panic_ops(blkz_read_op panic_read, blkz_write_op panic_write) +{ + struct blkz_info *info = &blkz_info; + + spin_lock(&modify_blkzinfo); + if (info->panic_read || info->panic_write) { + spin_unlock(&modify_blkzinfo); + return -EBUSY; + } + + info->panic_read = panic_read; + info->panic_write = panic_write; + + spin_unlock(&modify_blkzinfo); + return 0; +} +EXPORT_SYMBOL_GPL(blkoops_add_panic_ops); + +static int blkoops_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct blkoops_info *info = dev->platform_data; + + if (info->blkdev[0] == '\0' || !strcmp(info->blkdev, BLKDEV_INVALID)) { + pr_info("no block device, use ram buffer only\n"); + } else { + pr_debug("block device: %s\n", info->blkdev); + blkz_info.blkdev = info->blkdev; + } + +#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(total_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; + total_size = blkz_info.total_size; + if (blkz_info.blkdev) + strncpy(blkdev, blkz_info.blkdev, 80 - 1); + else + blkdev[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 or kconfig value. + */ + if (total_size > 0 || strcmp(blkdev, BLKDEV_INVALID)) { + pr_info("using module parameters\n"); + if (total_size >= 0) + info->total_size = (unsigned long)total_size * 1024; + if (strcmp(blkdev, BLKDEV_INVALID)) + info->blkdev = (const char *)blkdev; + if (dmesg_size >= 0) + info->dmesg_size = (unsigned long)dmesg_size * 1024; + } else if (info->total_size > 0 || strlen(info->blkdev)) { + pr_info("using kconfig value\n"); + } else { + return; + } + + 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; +} +late_initcall(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"); diff --git a/include/linux/pstore_blk.h b/include/linux/pstore_blk.h index 4f239f0..2d2ff97 100644 --- a/include/linux/pstore_blk.h +++ b/include/linux/pstore_blk.h @@ -60,6 +60,8 @@ * @panic_write: * the write operation only used for panic. */ +typedef ssize_t (*blkz_read_op)(char *, size_t, loff_t); +typedef ssize_t (*blkz_write_op)(const char *, size_t, loff_t); struct blkz_info { struct module *owner; const char *name; @@ -68,13 +70,17 @@ struct blkz_info { unsigned long total_size; unsigned long dmesg_size; int dump_oops; - ssize_t (*read)(char *buf, size_t bytes, loff_t pos); - ssize_t (*write)(const char *buf, size_t bytes, loff_t pos); - ssize_t (*panic_read)(char *buf, size_t bytes, loff_t pos); - ssize_t (*panic_write)(const char *buf, size_t bytes, loff_t pos); + blkz_read_op read; + blkz_write_op write; + blkz_read_op panic_read; + blkz_write_op panic_write; }; extern int blkz_register(struct blkz_info *info); extern void blkz_unregister(struct blkz_info *info); +#if IS_ENABLED(CONFIG_PSTORE_BLKOOPS) +extern int blkoops_add_panic_ops(blkz_read_op, blkz_write_op); +#endif + #endif -- 1.9.1