Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 43759
b: refs/heads/master
c: 329409a
h: refs/heads/master
i:
  43757: 59e7157
  43755: 0ca8a41
  43751: d0f612e
  43743: 4042183
v: v3
  • Loading branch information
Akinobu Mita authored and Linus Torvalds committed Dec 8, 2006
1 parent 8816e00 commit 1ce831c
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f4f154fd920b2178382a6a24a236348e4429ebc1
refs/heads/master: 329409aeda064c4aff00c51f837fcd3bbdaeeba6
12 changes: 8 additions & 4 deletions trunk/Documentation/fault-injection/fault-injection.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,17 @@ configuration of fault-injection capabilities.
Any positive value limits failures to only processes indicated by
/proc/<pid>/make-it-fail==1.

- /debug/*/address-start:
- /debug/*/address-end:
- /debug/*/require-start:
- /debug/*/require-end:
- /debug/*/reject-start:
- /debug/*/reject-end:

specifies the range of virtual addresses tested during
stacktrace walking. Failure is injected only if some caller
in the walked stacktrace lies within this range.
Default is [0,ULONG_MAX) (whole of virtual address space).
in the walked stacktrace lies within the required range, and
none lies within the rejected range.
Default required range is [0,ULONG_MAX) (whole of virtual address space).
Default rejected range is [0,0).

- /debug/*/stacktrace-depth:

Expand Down
12 changes: 12 additions & 0 deletions trunk/include/linux/fault-inject.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ struct fault_attr {
atomic_t space;
unsigned long verbose;
u32 task_filter;
unsigned long stacktrace_depth;
unsigned long require_start;
unsigned long require_end;
unsigned long reject_start;
unsigned long reject_end;

unsigned long count;

Expand All @@ -32,6 +37,11 @@ struct fault_attr {
struct dentry *space_file;
struct dentry *verbose_file;
struct dentry *task_filter_file;
struct dentry *stacktrace_depth_file;
struct dentry *require_start_file;
struct dentry *require_end_file;
struct dentry *reject_start_file;
struct dentry *reject_end_file;
} dentries;

#endif
Expand All @@ -40,6 +50,8 @@ struct fault_attr {
#define FAULT_ATTR_INITIALIZER { \
.interval = 1, \
.times = ATOMIC_INIT(1), \
.require_end = ULONG_MAX, \
.stacktrace_depth = 32, \
}

#define DECLARE_FAULT_ATTR(name) struct fault_attr name = FAULT_ATTR_INITIALIZER
Expand Down
5 changes: 5 additions & 0 deletions trunk/lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ config LKDTM

config FAULT_INJECTION
bool
select STACKTRACE
select FRAME_POINTER
help
Provide fault-injection framework.
For more details, see Documentation/fault-injection/.

config FAILSLAB
bool "Fault-injection capabilitiy for kmalloc"
Expand Down
126 changes: 125 additions & 1 deletion trunk/lib/fault-inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/unwind.h>
#include <linux/stacktrace.h>
#include <linux/kallsyms.h>
#include <linux/fault-inject.h>

/*
Expand Down Expand Up @@ -50,6 +53,86 @@ static int fail_task(struct fault_attr *attr, struct task_struct *task)
return !in_interrupt() && task->make_it_fail;
}

#ifdef CONFIG_STACK_UNWIND

static asmlinkage int fail_stacktrace_callback(struct unwind_frame_info *info,
void *arg)
{
int depth;
struct fault_attr *attr = arg;
bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);

for (depth = 0; depth < attr->stacktrace_depth
&& unwind(info) == 0 && UNW_PC(info); depth++) {
if (arch_unw_user_mode(info))
break;
if (attr->reject_start <= UNW_PC(info) &&
UNW_PC(info) < attr->reject_end)
return 0;
if (attr->require_start <= UNW_PC(info) &&
UNW_PC(info) < attr->require_end)
found = 1;
}
return found;
}

static int fail_stacktrace(struct fault_attr *attr)
{
struct unwind_frame_info info;

return unwind_init_running(&info, fail_stacktrace_callback, attr);
}

#elif defined(CONFIG_STACKTRACE)

#define MAX_STACK_TRACE_DEPTH 32

static int fail_stacktrace(struct fault_attr *attr)
{
struct stack_trace trace;
int depth = attr->stacktrace_depth;
unsigned long entries[MAX_STACK_TRACE_DEPTH];
int n;
bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);

if (depth == 0)
return found;

trace.nr_entries = 0;
trace.entries = entries;
trace.max_entries = (depth < MAX_STACK_TRACE_DEPTH) ?
depth : MAX_STACK_TRACE_DEPTH;
trace.skip = 1;
trace.all_contexts = 0;

save_stack_trace(&trace, NULL);
for (n = 0; n < trace.nr_entries; n++) {
if (attr->reject_start <= entries[n] &&
entries[n] < attr->reject_end)
return 0;
if (attr->require_start <= entries[n] &&
entries[n] < attr->require_end)
found = 1;
}
return found;
}

#else

static inline int fail_stacktrace(struct fault_attr *attr)
{
static int firsttime = 1;

if (firsttime) {
printk(KERN_WARNING
"This architecture does not implement save_stack_trace()\n");
firsttime = 0;
}
return 0;
}

#endif

/*
* This code is stolen from failmalloc-1.0
* http://www.nongnu.org/failmalloc/
Expand All @@ -60,6 +143,9 @@ int should_fail(struct fault_attr *attr, ssize_t size)
if (attr->task_filter && !fail_task(attr, current))
return 0;

if (!fail_stacktrace(attr))
return 0;

if (atomic_read(&attr->times) == 0)
return 0;

Expand Down Expand Up @@ -147,6 +233,21 @@ void cleanup_fault_attr_dentries(struct fault_attr *attr)
debugfs_remove(attr->dentries.task_filter_file);
attr->dentries.task_filter_file = NULL;

debugfs_remove(attr->dentries.stacktrace_depth_file);
attr->dentries.stacktrace_depth_file = NULL;

debugfs_remove(attr->dentries.require_start_file);
attr->dentries.require_start_file = NULL;

debugfs_remove(attr->dentries.require_end_file);
attr->dentries.require_end_file = NULL;

debugfs_remove(attr->dentries.reject_start_file);
attr->dentries.reject_start_file = NULL;

debugfs_remove(attr->dentries.reject_end_file);
attr->dentries.reject_end_file = NULL;

if (attr->dentries.dir)
WARN_ON(!simple_empty(attr->dentries.dir));

Expand Down Expand Up @@ -184,9 +285,32 @@ int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
mode, dir, &attr->task_filter);

attr->dentries.stacktrace_depth_file =
debugfs_create_ul("stacktrace-depth", mode, dir,
&attr->stacktrace_depth);

attr->dentries.require_start_file =
debugfs_create_ul("require-start", mode, dir, &attr->require_start);

attr->dentries.require_end_file =
debugfs_create_ul("require-end", mode, dir, &attr->require_end);

attr->dentries.reject_start_file =
debugfs_create_ul("reject-start", mode, dir, &attr->reject_start);

attr->dentries.reject_end_file =
debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);


if (!attr->dentries.probability_file || !attr->dentries.interval_file
|| !attr->dentries.times_file || !attr->dentries.space_file
|| !attr->dentries.verbose_file || !attr->dentries.task_filter_file)
|| !attr->dentries.verbose_file || !attr->dentries.task_filter_file
|| !attr->dentries.stacktrace_depth_file
|| !attr->dentries.require_start_file
|| !attr->dentries.require_end_file
|| !attr->dentries.reject_start_file
|| !attr->dentries.reject_end_file
)
goto fail;

return 0;
Expand Down

0 comments on commit 1ce831c

Please sign in to comment.