From patchwork Sat Jun 30 05:59:25 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akinobu Mita X-Patchwork-Id: 168289 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [IPv6:::1]) by ozlabs.org (Postfix) with ESMTP id A94992C0582 for ; Sat, 30 Jun 2012 17:50:56 +1000 (EST) Received: from mail-pz0-f51.google.com (mail-pz0-f51.google.com [209.85.210.51]) (using TLSv1 with cipher ECDHE-RSA-RC4-SHA (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 9A1C92C042B for ; Sat, 30 Jun 2012 17:50:23 +1000 (EST) Received: by dajt11 with SMTP id t11so6157157daj.38 for ; Sat, 30 Jun 2012 00:50:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=SyiHXq3cNmp2qirrEOBcEoERCT/ESXtOu6vrab0quPQ=; b=WPw4gx3h9IYWHqwHYZ0vSwEg4R6cGCGrooz1tUcndlZyToK66PbvMs6a9IATxXMx6g v6lGGRcQLtw7A7vRMVnRsA41C7FsLGPhS5w0z8ZTz/fF2dj7AyOwkAK87mTX75o7GyZ+ TNz1XyIPpZpzvWhlZJWgfYXDESzQQXCFWiIeahS8RddABhRQo7471KZ2pdoYJHJeJVdS NUD40Q+uYAx4GkisHRxPdmTxPLNPu90lVKJ2IiInrA1qKxzKLnauCjbgvoEbeAtEnJDT 4In5zhALQKSwS+DyBuFrdvpAwEjS+e4rVYeI3e8O0/XuOzzT8/tCbAngvHbBYbrpifmq npEg== Received: by 10.68.228.39 with SMTP id sf7mr13129339pbc.45.1341035999472; Fri, 29 Jun 2012 22:59:59 -0700 (PDT) Received: from localhost.localdomain (p15173-ipngn1601hodogaya.kanagawa.ocn.ne.jp. [180.0.44.173]) by mx.google.com with ESMTPS id oy8sm7469427pbc.52.2012.06.29.22.59.56 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 29 Jun 2012 22:59:58 -0700 (PDT) From: Akinobu Mita To: linux-kernel@vger.kernel.org, akpm@linux-foundation.org Subject: [PATCH -v5 1/6] fault-injection: notifier error injection Date: Sat, 30 Jun 2012 14:59:25 +0900 Message-Id: <1341035970-20490-2-git-send-email-akinobu.mita@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1341035970-20490-1-git-send-email-akinobu.mita@gmail.com> References: <1341035970-20490-1-git-send-email-akinobu.mita@gmail.com> Cc: Greg KH , Akinobu Mita , "Rafael J. Wysocki" , linux-mm@kvack.org, Paul Mackerras , Pavel Machek , linux-pm@lists.linux-foundation.org, linuxppc-dev@lists.ozlabs.org X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.15rc1 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" The notifier error injection provides the ability to inject artifical errors to specified notifier chain callbacks. It is useful to test the error handling of notifier call chain failures. This adds common basic functions to define which type of events can be fail and to initialize the debugfs interface to control what error code should be returned and which event should be failed. Signed-off-by: Akinobu Mita Cc: Pavel Machek Cc: "Rafael J. Wysocki" Cc: linux-pm@lists.linux-foundation.org Cc: Greg KH Cc: linux-mm@kvack.org Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Cc: Michael Ellerman --- No changes since v4 lib/Kconfig.debug | 11 +++++ lib/Makefile | 1 + lib/notifier-error-inject.c | 112 +++++++++++++++++++++++++++++++++++++++++++ lib/notifier-error-inject.h | 24 ++++++++++ 4 files changed, 148 insertions(+) create mode 100644 lib/notifier-error-inject.c create mode 100644 lib/notifier-error-inject.h diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index ff5bdee..c848758 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1084,6 +1084,17 @@ config LKDTM Documentation on how to use the module can be found in Documentation/fault-injection/provoke-crashes.txt +config NOTIFIER_ERROR_INJECTION + tristate "Notifier error injection" + depends on DEBUG_KERNEL + select DEBUG_FS + help + This option provides the ability to inject artifical errors to + specified notifier chain callbacks. It is useful to test the error + handling of notifier call chain failures. + + Say N if unsure. + config CPU_NOTIFIER_ERROR_INJECT tristate "CPU notifier error injection module" depends on HOTPLUG_CPU && DEBUG_KERNEL diff --git a/lib/Makefile b/lib/Makefile index 8c31a0c..23fba9e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -90,6 +90,7 @@ obj-$(CONFIG_AUDIT_GENERIC) += audit.o obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o +obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o obj-$(CONFIG_CPU_NOTIFIER_ERROR_INJECT) += cpu-notifier-error-inject.o lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/lib/notifier-error-inject.c b/lib/notifier-error-inject.c new file mode 100644 index 0000000..44b92cb --- /dev/null +++ b/lib/notifier-error-inject.c @@ -0,0 +1,112 @@ +#include + +#include "notifier-error-inject.h" + +static int debugfs_errno_set(void *data, u64 val) +{ + *(int *)data = clamp_t(int, val, -MAX_ERRNO, 0); + return 0; +} + +static int debugfs_errno_get(void *data, u64 *val) +{ + *val = *(int *)data; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set, + "%lld\n"); + +static struct dentry *debugfs_create_errno(const char *name, mode_t mode, + struct dentry *parent, int *value) +{ + return debugfs_create_file(name, mode, parent, value, &fops_errno); +} + +static int notifier_err_inject_callback(struct notifier_block *nb, + unsigned long val, void *p) +{ + int err = 0; + struct notifier_err_inject *err_inject = + container_of(nb, struct notifier_err_inject, nb); + struct notifier_err_inject_action *action; + + for (action = err_inject->actions; action->name; action++) { + if (action->val == val) { + err = action->error; + break; + } + } + if (err) + pr_info("Injecting error (%d) to %s\n", err, action->name); + + return notifier_from_errno(err); +} + +struct dentry *notifier_err_inject_dir; +EXPORT_SYMBOL_GPL(notifier_err_inject_dir); + +struct dentry *notifier_err_inject_init(const char *name, struct dentry *parent, + struct notifier_err_inject *err_inject, int priority) +{ + struct notifier_err_inject_action *action; + mode_t mode = S_IFREG | S_IRUSR | S_IWUSR; + struct dentry *dir; + struct dentry *actions_dir; + + err_inject->nb.notifier_call = notifier_err_inject_callback; + err_inject->nb.priority = priority; + + dir = debugfs_create_dir(name, parent); + if (!dir) + return ERR_PTR(-ENOMEM); + + actions_dir = debugfs_create_dir("actions", dir); + if (!actions_dir) + goto fail; + + for (action = err_inject->actions; action->name; action++) { + struct dentry *action_dir; + + action_dir = debugfs_create_dir(action->name, actions_dir); + if (!action_dir) + goto fail; + + /* + * Create debugfs r/w file containing action->error. If + * notifier call chain is called with action->val, it will + * fail with the error code + */ + if (!debugfs_create_errno("error", mode, action_dir, + &action->error)) + goto fail; + } + return dir; +fail: + debugfs_remove_recursive(dir); + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL_GPL(notifier_err_inject_init); + +static int __init err_inject_init(void) +{ + notifier_err_inject_dir = + debugfs_create_dir("notifier-error-inject", NULL); + + if (!notifier_err_inject_dir) + return -ENOMEM; + + return 0; +} + +static void __exit err_inject_exit(void) +{ + debugfs_remove_recursive(notifier_err_inject_dir); +} + +module_init(err_inject_init); +module_exit(err_inject_exit); + +MODULE_DESCRIPTION("Notifier error injection module"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Akinobu Mita "); diff --git a/lib/notifier-error-inject.h b/lib/notifier-error-inject.h new file mode 100644 index 0000000..99b3b6f --- /dev/null +++ b/lib/notifier-error-inject.h @@ -0,0 +1,24 @@ +#include +#include +#include + +struct notifier_err_inject_action { + unsigned long val; + int error; + const char *name; +}; + +#define NOTIFIER_ERR_INJECT_ACTION(action) \ + .name = #action, .val = (action), + +struct notifier_err_inject { + struct notifier_block nb; + struct notifier_err_inject_action actions[]; + /* The last slot must be terminated with zero sentinel */ +}; + +extern struct dentry *notifier_err_inject_dir; + +extern struct dentry *notifier_err_inject_init(const char *name, + struct dentry *parent, struct notifier_err_inject *err_inject, + int priority);