[Fault-injection-developer] [PATCH]New Mock Interceptor
Status: Alpha
Brought to you by:
rustyl
|
From: Rusty L. <ru...@li...> - 2002-12-21 01:59:37
|
I added a new "mock" interceptor to aid in testing fi_core.c, but
it could also be viewed as a near minimal interceptor implementation.
If you build drivers/char/fi_mock_interceptor.c as a module you can
then control what type of interceptor it will register as with a
'mock_type' parameter.
Once the module is loaded and a new trigger is added that uses the
interceptor, then mock will create a 'trip' file in the trigger's
sysfs directory. Writing anything to the 'trip' file will cause
fi_execute_trigger() to be called for that trigger.
All functions print tracing information to the log, so you should be
able to trace proper interceptor/core interactions.
In implementing this I moved the definitions for trigger and interceptor
attributes to the header file, and added the missing logic to fi_core.c
to allow any interceptor to:
* add files to the trigger directories for the triggers that arm the
interceptor
* add files to an interceptors own interceptor directory
Have a good holidays.
-rustyl
# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.908 -> 1.910
# arch/i386/Kconfig 1.24 -> 1.25
# kernel/fi_core.c 1.15 -> 1.17
# include/linux/fi.h 1.3 -> 1.4
# drivers/char/Makefile 1.54 -> 1.55
# (new) -> 1.1 drivers/char/fi_mock_interceptor.c
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/12/20 rusty@penguin.(none) 1.885.7.1
# * Added a new interceptor just for the purpose of testing fi_core.c
# * Added support for interceptor attributes
# * Added a new interceptor unregistration function to fi_core
# --------------------------------------------
# 02/12/20 rusty@penguin.(none) 1.909
# Fixed merge conflict
# --------------------------------------------
# 02/12/20 rusty@penguin.(none) 1.910
# fixed a mistake in last merge
# --------------------------------------------
#
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig Fri Dec 20 17:43:51 2002
+++ b/arch/i386/Kconfig Fri Dec 20 17:43:51 2002
@@ -1585,6 +1585,17 @@
Unless you are intending to experiment with fault injection testing,
just say N.
+config FI_MOCK_INTERCEPTOR
+ tristate "Fault Injection Mock Interceptor (EXPERIMENTAL)"
+ depends on FI
+ help
+ This is a mock or fake fault injection interceptor created for the
+ sole purpose of exercising the fault injection core code. The
+ only reason a person would want to build this component is to
+ hack fault injection.
+
+ If in doubt say N.
+
config DEBUG_STACKOVERFLOW
bool "Check for stack overflows"
depends on DEBUG_KERNEL
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile Fri Dec 20 17:43:51 2002
+++ b/drivers/char/Makefile Fri Dec 20 17:43:51 2002
@@ -77,6 +77,7 @@
obj-$(CONFIG_NWFLASH) += nwflash.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
obj-$(CONFIG_FI_TEST) += fi_test.o
+obj-$(CONFIG_FI_MOCK_INTERCEPTOR) += fi_mock_interceptor.o
obj-$(CONFIG_WATCHDOG) += watchdog/
obj-$(CONFIG_MWAVE) += mwave/
diff -Nru a/drivers/char/fi_mock_interceptor.c b/drivers/char/fi_mock_interceptor.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/char/fi_mock_interceptor.c Fri Dec 20 17:43:51 2002
@@ -0,0 +1,148 @@
+/*
+ * Fault Injection Mock Interceptor Driver
+ * ---------------------------------------
+ *
+ * This is a fault injection interceptor interceptor created
+ * for the sole purpose of testing the core fault injection code.
+ * By loading this driver a new interceptor named 'mock_interceptor'
+ * will appear in the list of available interceptors.
+ *
+ * When a trigger is loaded that utilizes this interceptor:
+ * - you should be able to trace of the interceptor <==> core
+ * by looking at dmesg
+ * - a new file called 'trip' will created in the trigger directory
+ * that when written to will trip the trigger
+ *
+ * In addition to this, the type of intercepor (interceptor_type_t)
+ * that this moc implementation claims to be when it registers
+ * with the fault injection core can be controled with the
+ * 'mock_type' parameter.
+ *
+ * For example, to pretend to be a a INTERCEPTOR_TYPE_PIO
+ * interceptor (which is really just the number '2' as defined
+ * in the fi.h enum declaration), you would load:
+ * $ insmod fi_mock_interceptor mod_type=2
+ *
+ * You can find out what the current type is by reading the
+ * 'type' file in the mock_interceptor directory.
+ * (i.e. 'cat fault_injection/interceptors/mock_interceptor/type')
+ *
+ * Copyright (C) 2002 Rusty Lynch <ru...@li...>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/kobject.h>
+#include <linux/fi.h>
+
+#define DRIVER_AUTHOR "Rusty Lynch <ru...@li...>"
+#define DRIVER_DESC "Fault Injection Mock Interceptor"
+
+#define dbg(format, arg...) \
+ printk (KERN_DEBUG "%s: " format "\n",__FUNCTION__, ## arg);
+#define trace(format, arg...) \
+ printk(KERN_INFO "%s(" format ")\n", __FUNCTION__ , ## arg)
+
+extern int fi_register_interceptor(struct interceptor *);
+extern int fi_unregister_interceptor(struct interceptor *);
+extern void fi_execute_trigger(struct trigger*,struct interceptor*,
+ __u32,int,int,void*);
+
+static struct interceptor mock_interceptor;
+
+/* local variables */
+static int mock_type = INTERCEPTOR_TYPE_MMIO;
+
+static ssize_t trip_store(struct trigger * p, const char * page,
+ size_t count, loff_t off)
+{
+ trace("%s, %p, %i, %i", p ? p->kobj.name:"NULL",page,count,(int)off);
+ fi_execute_trigger(p, &mock_interceptor, 0, 0, 0, 0);
+ return count;
+}
+static struct trigger_attribute attr_trip = {
+ .attr = { .name = "trip", .mode = 0644 },
+ .store = &trip_store,
+};
+
+static ssize_t type_show(struct interceptor * p, char * page,
+ size_t count, loff_t off)
+{
+ trace("%s, %p, %i, %i", p ? p->kobj.name:"NULL",page,count,(int)off);
+ return off ? 0 : snprintf(page,count,"%i\n",mock_type);
+}
+static struct interceptor_attribute attr_type = {
+ .attr = { .name = "type", .mode = 0644 },
+ .show = &type_show,
+};
+
+static int arm(struct trigger *t)
+{
+ trace("%s", t ? t->kobj.name : "NULL");
+ if (!t) {
+ dbg("Null trigger passed into arming function!");
+ return -EINVAL;
+ }
+
+ sysfs_create_file(&t->kobj, &attr_trip.attr);
+ return 0;
+};
+
+static void disarm(struct trigger *t)
+{
+ trace("%s", t ? t->kobj.name : "NULL");
+ if (!t) {
+ dbg("Null trigger passed into disarming function!");
+ return;
+ }
+
+ sysfs_remove_file(&t->kobj, &attr_trip.attr);
+ return;
+};
+
+static void corrupt(__u32 dirty, void *data)
+{
+ trace("%ul, %p", dirty, data);
+ return;
+};
+
+static struct interceptor mock_interceptor = {
+ .kobj = {.name = "mock"},
+ .arm = &arm,
+ .disarm = &disarm,
+ .corrupt = &corrupt
+};
+
+static int __init mock_init(void)
+{
+ trace();
+
+ mock_interceptor.type = mock_type;
+ kobject_init(&mock_interceptor.kobj);
+ if (!fi_register_interceptor(&mock_interceptor)) {
+ dbg("Failed to register Mock Interceptor");
+
+ /* FIXME!! For some reason kobject_register */
+ /* is returning an error when none occured */
+ /*return -EINVAL;*/
+ }
+
+ sysfs_create_file(&mock_interceptor.kobj, &attr_type.attr);
+ return 0;
+}
+
+static void __exit mock_exit (void)
+{
+ trace();
+ fi_unregister_interceptor(&mock_interceptor);
+}
+
+module_init(mock_init);
+module_exit(mock_exit);
+
+MODULE_PARM(mock_type, "i");
+MODULE_PARM_DESC(mock_type, "(interceptor_type_t) Type of interceptor");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff -Nru a/include/linux/fi.h b/include/linux/fi.h
--- a/include/linux/fi.h Fri Dec 20 17:43:51 2002
+++ b/include/linux/fi.h Fri Dec 20 17:43:51 2002
@@ -25,7 +25,8 @@
typedef enum
{
INTERCEPTOR_TYPE_UNKNOWN=0,
- INTERCEPTOR_TYPE_MMIO=1
+ INTERCEPTOR_TYPE_MMIO=1,
+ INTERCEPTOR_TYPE_PIO=2,
} interceptor_type_t;
struct trigger {
@@ -54,6 +55,18 @@
void (*disarm) (struct trigger *);
void (*corrupt)(__u32, void *);
struct kobject kobj;
+};
+
+struct interceptor_attribute {
+ struct attribute attr;
+ ssize_t (*show) (struct interceptor *,char *,size_t,loff_t);
+ ssize_t (*store)(struct interceptor *,const char *,size_t, loff_t);
+};
+
+struct trigger_attribute {
+ struct attribute attr;
+ ssize_t (*show) (struct trigger *,char *,size_t,loff_t);
+ ssize_t (*store)(struct trigger *,const char *,size_t,loff_t);
};
#endif /* __KERNEL__ */
diff -Nru a/kernel/fi_core.c b/kernel/fi_core.c
--- a/kernel/fi_core.c Fri Dec 20 17:43:51 2002
+++ b/kernel/fi_core.c Fri Dec 20 17:43:51 2002
@@ -51,16 +51,10 @@
static struct subsystem interceptor_subsys;
static int is_initialized = 0;
-
int fi_debug = 1;
int fi_register_interceptor(struct interceptor *);
-struct trigger_attribute {
- struct attribute attr;
- ssize_t (*show)(struct trigger *,char *,size_t,loff_t);
-};
-
static struct trigger_attribute trigger_attr_wp;
static struct trigger_attribute trigger_attr_bitmask;
static struct trigger_attribute trigger_attr_min;
@@ -247,9 +241,42 @@
* ---------------------------------------------------------------
*/
+static ssize_t interceptor_attr_show(struct kobject * kobj,
+ struct attribute * attr,
+ char * page, size_t count,
+ loff_t off)
+{
+ struct interceptor * i = container_of(kobj,struct interceptor,kobj);
+ struct interceptor_attribute * a =
+ container_of(attr,struct interceptor_attribute,attr);
+
+ dbg("about to call show function for %s", a->attr.name);
+ return a->show ? a->show(i,page,count,off) : 0;
+}
+
+static ssize_t interceptor_attr_store(struct kobject * kobj,
+ struct attribute * attr,
+ const char * page,
+ size_t count,
+ loff_t off)
+{
+ struct interceptor * i = container_of(kobj,struct interceptor,kobj);
+ struct interceptor_attribute * a =
+ container_of(attr,struct interceptor_attribute,attr);
+
+ dbg("about to call store function for %s", a->attr.name);
+ return a->store ? a->store(i,page,count,off) : 0;
+};
+
+static struct sysfs_ops interceptor_sysfs_ops = {
+ .show = interceptor_attr_show,
+ .store = interceptor_attr_store,
+};
+
static struct subsystem interceptor_subsys = {
- .kobj = { .name = "interceptors" },
- .parent = &fi_subsys,
+ .kobj = { .name = "interceptors" },
+ .sysfs_ops = &interceptor_sysfs_ops,
+ .parent = &fi_subsys,
};
/*
@@ -271,6 +298,19 @@
return trigger_attr->show ? trigger_attr->show(n,page,count,off) : 0;
}
+static ssize_t trigger_attr_store(struct kobject * kobj,
+ struct attribute * attr,
+ const char * page, size_t count,
+ loff_t off)
+{
+ struct trigger * n = container_of(kobj,struct trigger,kobj);
+ struct trigger_attribute * trigger_attr =
+ container_of(attr,struct trigger_attribute,attr);
+
+ dbg("about to call store function for %s", trigger_attr->attr.name);
+ return trigger_attr->store ? trigger_attr->store(n,page,count,off) : 0;
+}
+
static ssize_t trigger_wp_read(struct trigger * p, char * page,
size_t count, loff_t off)
{
@@ -497,6 +537,7 @@
static struct sysfs_ops trigger_sysfs_ops = {
.show = trigger_attr_show,
+ .store = trigger_attr_store,
};
static struct subsystem trigger_subsys = {
|