[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 = { |