aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig4
-rw-r--r--lib/Kconfig.debug84
-rw-r--r--lib/Makefile4
-rw-r--r--lib/bitrev.c58
-rw-r--r--lib/bug.c163
-rw-r--r--lib/crc32.c28
-rw-r--r--lib/fault-inject.c336
7 files changed, 629 insertions, 48 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index 734ce95a93d1..47b172df3e31 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -4,6 +4,9 @@
4 4
5menu "Library routines" 5menu "Library routines"
6 6
7config BITREVERSE
8 tristate
9
7config CRC_CCITT 10config CRC_CCITT
8 tristate "CRC-CCITT functions" 11 tristate "CRC-CCITT functions"
9 help 12 help
@@ -23,6 +26,7 @@ config CRC16
23config CRC32 26config CRC32
24 tristate "CRC32 functions" 27 tristate "CRC32 functions"
25 default y 28 default y
29 select BITREVERSE
26 help 30 help
27 This option is provided for the case where no in-kernel-tree 31 This option is provided for the case where no in-kernel-tree
28 modules require CRC32 functions, but a module built outside the 32 modules require CRC32 functions, but a module built outside the
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index b75fed737f25..0701ddda1df8 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -47,6 +47,30 @@ config UNUSED_SYMBOLS
47 you really need it, and what the merge plan to the mainline kernel for 47 you really need it, and what the merge plan to the mainline kernel for
48 your module is. 48 your module is.
49 49
50config DEBUG_FS
51 bool "Debug Filesystem"
52 depends on SYSFS
53 help
54 debugfs is a virtual file system that kernel developers use to put
55 debugging files into. Enable this option to be able to read and
56 write to these files.
57
58 If unsure, say N.
59
60config HEADERS_CHECK
61 bool "Run 'make headers_check' when building vmlinux"
62 depends on !UML
63 help
64 This option will extract the user-visible kernel headers whenever
65 building the kernel, and will run basic sanity checks on them to
66 ensure that exported files do not attempt to include files which
67 were not exported, etc.
68
69 If you're making modifications to header files which are
70 relevant for userspace, say 'Y', and check the headers
71 exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
72 your build tree), to make sure they're suitable.
73
50config DEBUG_KERNEL 74config DEBUG_KERNEL
51 bool "Kernel debugging" 75 bool "Kernel debugging"
52 help 76 help
@@ -285,7 +309,7 @@ config DEBUG_HIGHMEM
285config DEBUG_BUGVERBOSE 309config DEBUG_BUGVERBOSE
286 bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED 310 bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
287 depends on BUG 311 depends on BUG
288 depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV || SUPERH 312 depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || FRV || SUPERH || GENERIC_BUG
289 default !EMBEDDED 313 default !EMBEDDED
290 help 314 help
291 Say Y here to make BUG() panics output the file name and line number 315 Say Y here to make BUG() panics output the file name and line number
@@ -302,16 +326,6 @@ config DEBUG_INFO
302 326
303 If unsure, say N. 327 If unsure, say N.
304 328
305config DEBUG_FS
306 bool "Debug Filesystem"
307 depends on SYSFS
308 help
309 debugfs is a virtual file system that kernel developers use to put
310 debugging files into. Enable this option to be able to read and
311 write to these files.
312
313 If unsure, say N.
314
315config DEBUG_VM 329config DEBUG_VM
316 bool "Debug VM" 330 bool "Debug VM"
317 depends on DEBUG_KERNEL 331 depends on DEBUG_KERNEL
@@ -372,20 +386,6 @@ config FORCED_INLINING
372 become the default in the future, until then this option is there to 386 become the default in the future, until then this option is there to
373 test gcc for this. 387 test gcc for this.
374 388
375config HEADERS_CHECK
376 bool "Run 'make headers_check' when building vmlinux"
377 depends on !UML
378 help
379 This option will extract the user-visible kernel headers whenever
380 building the kernel, and will run basic sanity checks on them to
381 ensure that exported files do not attempt to include files which
382 were not exported, etc.
383
384 If you're making modifications to header files which are
385 relevant for userspace, say 'Y', and check the headers
386 exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in
387 your build tree), to make sure they're suitable.
388
389config RCU_TORTURE_TEST 389config RCU_TORTURE_TEST
390 tristate "torture tests for RCU" 390 tristate "torture tests for RCU"
391 depends on DEBUG_KERNEL 391 depends on DEBUG_KERNEL
@@ -402,6 +402,7 @@ config RCU_TORTURE_TEST
402 402
403config LKDTM 403config LKDTM
404 tristate "Linux Kernel Dump Test Tool Module" 404 tristate "Linux Kernel Dump Test Tool Module"
405 depends on DEBUG_KERNEL
405 depends on KPROBES 406 depends on KPROBES
406 default n 407 default n
407 help 408 help
@@ -413,3 +414,36 @@ config LKDTM
413 414
414 Documentation on how to use the module can be found in 415 Documentation on how to use the module can be found in
415 drivers/misc/lkdtm.c 416 drivers/misc/lkdtm.c
417
418config FAULT_INJECTION
419 bool "Fault-injection framework"
420 depends on DEBUG_KERNEL
421 depends on STACKTRACE
422 select FRAME_POINTER
423 help
424 Provide fault-injection framework.
425 For more details, see Documentation/fault-injection/.
426
427config FAILSLAB
428 bool "Fault-injection capability for kmalloc"
429 depends on FAULT_INJECTION
430 help
431 Provide fault-injection capability for kmalloc.
432
433config FAIL_PAGE_ALLOC
434 bool "Fault-injection capabilitiy for alloc_pages()"
435 depends on FAULT_INJECTION
436 help
437 Provide fault-injection capability for alloc_pages().
438
439config FAIL_MAKE_REQUEST
440 bool "Fault-injection capabilitiy for disk IO"
441 depends on FAULT_INJECTION
442 help
443 Provide fault-injection capability for disk IO.
444
445config FAULT_INJECTION_DEBUG_FS
446 bool "Debugfs entries for fault-injection capabilities"
447 depends on FAULT_INJECTION && SYSFS && DEBUG_FS
448 help
449 Enable configuration of fault-injection capabilities via debugfs.
diff --git a/lib/Makefile b/lib/Makefile
index fea8f9035f07..2d6106af53cd 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,6 +35,7 @@ ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
35 lib-y += dec_and_lock.o 35 lib-y += dec_and_lock.o
36endif 36endif
37 37
38obj-$(CONFIG_BITREVERSE) += bitrev.o
38obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o 39obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
39obj-$(CONFIG_CRC16) += crc16.o 40obj-$(CONFIG_CRC16) += crc16.o
40obj-$(CONFIG_CRC32) += crc32.o 41obj-$(CONFIG_CRC32) += crc32.o
@@ -54,6 +55,9 @@ obj-$(CONFIG_SMP) += percpu_counter.o
54obj-$(CONFIG_AUDIT_GENERIC) += audit.o 55obj-$(CONFIG_AUDIT_GENERIC) += audit.o
55 56
56obj-$(CONFIG_SWIOTLB) += swiotlb.o 57obj-$(CONFIG_SWIOTLB) += swiotlb.o
58obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
59
60lib-$(CONFIG_GENERIC_BUG) += bug.o
57 61
58hostprogs-y := gen_crc32table 62hostprogs-y := gen_crc32table
59clean-files := crc32table.h 63clean-files := crc32table.h
diff --git a/lib/bitrev.c b/lib/bitrev.c
new file mode 100644
index 000000000000..989aff73f881
--- /dev/null
+++ b/lib/bitrev.c
@@ -0,0 +1,58 @@
1#include <linux/types.h>
2#include <linux/module.h>
3#include <linux/bitrev.h>
4
5MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
6MODULE_DESCRIPTION("Bit ordering reversal functions");
7MODULE_LICENSE("GPL");
8
9const u8 byte_rev_table[256] = {
10 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
11 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
12 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
13 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
14 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
15 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
16 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
17 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
18 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
19 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
20 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
21 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
22 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
23 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
24 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
25 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
26 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
27 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
28 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
29 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
30 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
31 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
32 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
33 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
34 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
35 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
36 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
37 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
38 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
39 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
40 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
41 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
42};
43EXPORT_SYMBOL_GPL(byte_rev_table);
44
45static __always_inline u16 bitrev16(u16 x)
46{
47 return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8);
48}
49
50/**
51 * bitrev32 - reverse the order of bits in a u32 value
52 * @x: value to be bit-reversed
53 */
54u32 bitrev32(u32 x)
55{
56 return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16);
57}
58EXPORT_SYMBOL(bitrev32);
diff --git a/lib/bug.c b/lib/bug.c
new file mode 100644
index 000000000000..014b582c5c4b
--- /dev/null
+++ b/lib/bug.c
@@ -0,0 +1,163 @@
1/*
2 Generic support for BUG()
3
4 This respects the following config options:
5
6 CONFIG_BUG - emit BUG traps. Nothing happens without this.
7 CONFIG_GENERIC_BUG - enable this code.
8 CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG
9
10 CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
11 (though they're generally always on).
12
13 CONFIG_GENERIC_BUG is set by each architecture using this code.
14
15 To use this, your architecture must:
16
17 1. Set up the config options:
18 - Enable CONFIG_GENERIC_BUG if CONFIG_BUG
19
20 2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON)
21 - Define HAVE_ARCH_BUG
22 - Implement BUG() to generate a faulting instruction
23 - NOTE: struct bug_entry does not have "file" or "line" entries
24 when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
25 the values accordingly.
26
27 3. Implement the trap
28 - In the illegal instruction trap handler (typically), verify
29 that the fault was in kernel mode, and call report_bug()
30 - report_bug() will return whether it was a false alarm, a warning,
31 or an actual bug.
32 - You must implement the is_valid_bugaddr(bugaddr) callback which
33 returns true if the eip is a real kernel address, and it points
34 to the expected BUG trap instruction.
35
36 Jeremy Fitzhardinge <jeremy@goop.org> 2006
37 */
38#include <linux/list.h>
39#include <linux/module.h>
40#include <linux/bug.h>
41
42extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
43
44#ifdef CONFIG_MODULES
45static LIST_HEAD(module_bug_list);
46
47static const struct bug_entry *module_find_bug(unsigned long bugaddr)
48{
49 struct module *mod;
50
51 list_for_each_entry(mod, &module_bug_list, bug_list) {
52 const struct bug_entry *bug = mod->bug_table;
53 unsigned i;
54
55 for (i = 0; i < mod->num_bugs; ++i, ++bug)
56 if (bugaddr == bug->bug_addr)
57 return bug;
58 }
59 return NULL;
60}
61
62int module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
63 struct module *mod)
64{
65 char *secstrings;
66 unsigned int i;
67
68 mod->bug_table = NULL;
69 mod->num_bugs = 0;
70
71 /* Find the __bug_table section, if present */
72 secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
73 for (i = 1; i < hdr->e_shnum; i++) {
74 if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table"))
75 continue;
76 mod->bug_table = (void *) sechdrs[i].sh_addr;
77 mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
78 break;
79 }
80
81 /*
82 * Strictly speaking this should have a spinlock to protect against
83 * traversals, but since we only traverse on BUG()s, a spinlock
84 * could potentially lead to deadlock and thus be counter-productive.
85 */
86 list_add(&mod->bug_list, &module_bug_list);
87
88 return 0;
89}
90
91void module_bug_cleanup(struct module *mod)
92{
93 list_del(&mod->bug_list);
94}
95
96#else
97
98static inline const struct bug_entry *module_find_bug(unsigned long bugaddr)
99{
100 return NULL;
101}
102#endif
103
104const struct bug_entry *find_bug(unsigned long bugaddr)
105{
106 const struct bug_entry *bug;
107
108 for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
109 if (bugaddr == bug->bug_addr)
110 return bug;
111
112 return module_find_bug(bugaddr);
113}
114
115enum bug_trap_type report_bug(unsigned long bugaddr)
116{
117 const struct bug_entry *bug;
118 const char *file;
119 unsigned line, warning;
120
121 if (!is_valid_bugaddr(bugaddr))
122 return BUG_TRAP_TYPE_NONE;
123
124 bug = find_bug(bugaddr);
125
126 printk(KERN_EMERG "------------[ cut here ]------------\n");
127
128 file = NULL;
129 line = 0;
130 warning = 0;
131
132 if (bug) {
133#ifdef CONFIG_DEBUG_BUGVERBOSE
134 file = bug->file;
135 line = bug->line;
136#endif
137 warning = (bug->flags & BUGFLAG_WARNING) != 0;
138 }
139
140 if (warning) {
141 /* this is a WARN_ON rather than BUG/BUG_ON */
142 if (file)
143 printk(KERN_ERR "Badness at %s:%u\n",
144 file, line);
145 else
146 printk(KERN_ERR "Badness at %p "
147 "[verbose debug info unavailable]\n",
148 (void *)bugaddr);
149
150 dump_stack();
151 return BUG_TRAP_TYPE_WARN;
152 }
153
154 if (file)
155 printk(KERN_CRIT "kernel BUG at %s:%u!\n",
156 file, line);
157 else
158 printk(KERN_CRIT "Kernel BUG at %p "
159 "[verbose debug info unavailable]\n",
160 (void *)bugaddr);
161
162 return BUG_TRAP_TYPE_BUG;
163}
diff --git a/lib/crc32.c b/lib/crc32.c
index 285fd9bc61be..bfc33314c720 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -235,23 +235,8 @@ u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
235} 235}
236#endif 236#endif
237 237
238/**
239 * bitreverse - reverse the order of bits in a u32 value
240 * @x: value to be bit-reversed
241 */
242u32 bitreverse(u32 x)
243{
244 x = (x >> 16) | (x << 16);
245 x = (x >> 8 & 0x00ff00ff) | (x << 8 & 0xff00ff00);
246 x = (x >> 4 & 0x0f0f0f0f) | (x << 4 & 0xf0f0f0f0);
247 x = (x >> 2 & 0x33333333) | (x << 2 & 0xcccccccc);
248 x = (x >> 1 & 0x55555555) | (x << 1 & 0xaaaaaaaa);
249 return x;
250}
251
252EXPORT_SYMBOL(crc32_le); 238EXPORT_SYMBOL(crc32_le);
253EXPORT_SYMBOL(crc32_be); 239EXPORT_SYMBOL(crc32_be);
254EXPORT_SYMBOL(bitreverse);
255 240
256/* 241/*
257 * A brief CRC tutorial. 242 * A brief CRC tutorial.
@@ -400,10 +385,7 @@ buf_dump(char const *prefix, unsigned char const *buf, size_t len)
400static void bytereverse(unsigned char *buf, size_t len) 385static void bytereverse(unsigned char *buf, size_t len)
401{ 386{
402 while (len--) { 387 while (len--) {
403 unsigned char x = *buf; 388 unsigned char x = bitrev8(*buf);
404 x = (x >> 4) | (x << 4);
405 x = (x >> 2 & 0x33) | (x << 2 & 0xcc);
406 x = (x >> 1 & 0x55) | (x << 1 & 0xaa);
407 *buf++ = x; 389 *buf++ = x;
408 } 390 }
409} 391}
@@ -460,11 +442,11 @@ static u32 test_step(u32 init, unsigned char *buf, size_t len)
460 /* Now swap it around for the other test */ 442 /* Now swap it around for the other test */
461 443
462 bytereverse(buf, len + 4); 444 bytereverse(buf, len + 4);
463 init = bitreverse(init); 445 init = bitrev32(init);
464 crc2 = bitreverse(crc1); 446 crc2 = bitrev32(crc1);
465 if (crc1 != bitreverse(crc2)) 447 if (crc1 != bitrev32(crc2))
466 printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n", 448 printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n",
467 crc1, crc2, bitreverse(crc2)); 449 crc1, crc2, bitrev32(crc2));
468 crc1 = crc32_le(init, buf, len); 450 crc1 = crc32_le(init, buf, len);
469 if (crc1 != crc2) 451 if (crc1 != crc2)
470 printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1, 452 printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1,
diff --git a/lib/fault-inject.c b/lib/fault-inject.c
new file mode 100644
index 000000000000..d143c0faf248
--- /dev/null
+++ b/lib/fault-inject.c
@@ -0,0 +1,336 @@
1#include <linux/kernel.h>
2#include <linux/init.h>
3#include <linux/random.h>
4#include <linux/stat.h>
5#include <linux/types.h>
6#include <linux/fs.h>
7#include <linux/module.h>
8#include <linux/interrupt.h>
9#include <linux/unwind.h>
10#include <linux/stacktrace.h>
11#include <linux/kallsyms.h>
12#include <linux/fault-inject.h>
13
14/*
15 * setup_fault_attr() is a helper function for various __setup handlers, so it
16 * returns 0 on error, because that is what __setup handlers do.
17 */
18int __init setup_fault_attr(struct fault_attr *attr, char *str)
19{
20 unsigned long probability;
21 unsigned long interval;
22 int times;
23 int space;
24
25 /* "<interval>,<probability>,<space>,<times>" */
26 if (sscanf(str, "%lu,%lu,%d,%d",
27 &interval, &probability, &space, &times) < 4) {
28 printk(KERN_WARNING
29 "FAULT_INJECTION: failed to parse arguments\n");
30 return 0;
31 }
32
33 attr->probability = probability;
34 attr->interval = interval;
35 atomic_set(&attr->times, times);
36 atomic_set(&attr->space, space);
37
38 return 1;
39}
40
41static void fail_dump(struct fault_attr *attr)
42{
43 if (attr->verbose > 0)
44 printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure\n");
45 if (attr->verbose > 1)
46 dump_stack();
47}
48
49#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
50
51static bool fail_task(struct fault_attr *attr, struct task_struct *task)
52{
53 return !in_interrupt() && task->make_it_fail;
54}
55
56#define MAX_STACK_TRACE_DEPTH 32
57
58#ifdef CONFIG_STACK_UNWIND
59
60static asmlinkage int fail_stacktrace_callback(struct unwind_frame_info *info,
61 void *arg)
62{
63 int depth;
64 struct fault_attr *attr = arg;
65 bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);
66
67 for (depth = 0; depth < attr->stacktrace_depth
68 && unwind(info) == 0 && UNW_PC(info); depth++) {
69 if (arch_unw_user_mode(info))
70 break;
71 if (attr->reject_start <= UNW_PC(info) &&
72 UNW_PC(info) < attr->reject_end)
73 return false;
74 if (attr->require_start <= UNW_PC(info) &&
75 UNW_PC(info) < attr->require_end)
76 found = true;
77 }
78 return found;
79}
80
81static bool fail_stacktrace(struct fault_attr *attr)
82{
83 struct unwind_frame_info info;
84
85 return unwind_init_running(&info, fail_stacktrace_callback, attr);
86}
87
88#elif defined(CONFIG_STACKTRACE)
89
90static bool fail_stacktrace(struct fault_attr *attr)
91{
92 struct stack_trace trace;
93 int depth = attr->stacktrace_depth;
94 unsigned long entries[MAX_STACK_TRACE_DEPTH];
95 int n;
96 bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX);
97
98 if (depth == 0)
99 return found;
100
101 trace.nr_entries = 0;
102 trace.entries = entries;
103 trace.max_entries = depth;
104 trace.skip = 1;
105 trace.all_contexts = 0;
106
107 save_stack_trace(&trace, NULL);
108 for (n = 0; n < trace.nr_entries; n++) {
109 if (attr->reject_start <= entries[n] &&
110 entries[n] < attr->reject_end)
111 return false;
112 if (attr->require_start <= entries[n] &&
113 entries[n] < attr->require_end)
114 found = true;
115 }
116 return found;
117}
118
119#else
120
121static inline bool fail_stacktrace(struct fault_attr *attr)
122{
123 static bool firsttime = true;
124
125 if (firsttime) {
126 printk(KERN_WARNING
127 "This architecture does not implement save_stack_trace()\n");
128 firsttime = false;
129 }
130 return false;
131}
132
133#endif
134
135/*
136 * This code is stolen from failmalloc-1.0
137 * http://www.nongnu.org/failmalloc/
138 */
139
140bool should_fail(struct fault_attr *attr, ssize_t size)
141{
142 if (attr->task_filter && !fail_task(attr, current))
143 return false;
144
145 if (atomic_read(&attr->times) == 0)
146 return false;
147
148 if (atomic_read(&attr->space) > size) {
149 atomic_sub(size, &attr->space);
150 return false;
151 }
152
153 if (attr->interval > 1) {
154 attr->count++;
155 if (attr->count % attr->interval)
156 return false;
157 }
158
159 if (attr->probability <= random32() % 100)
160 return false;
161
162 if (!fail_stacktrace(attr))
163 return false;
164
165 fail_dump(attr);
166
167 if (atomic_read(&attr->times) != -1)
168 atomic_dec_not_zero(&attr->times);
169
170 return true;
171}
172
173#ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
174
175static void debugfs_ul_set(void *data, u64 val)
176{
177 *(unsigned long *)data = val;
178}
179
180static void debugfs_ul_set_MAX_STACK_TRACE_DEPTH(void *data, u64 val)
181{
182 *(unsigned long *)data =
183 val < MAX_STACK_TRACE_DEPTH ?
184 val : MAX_STACK_TRACE_DEPTH;
185}
186
187static u64 debugfs_ul_get(void *data)
188{
189 return *(unsigned long *)data;
190}
191
192DEFINE_SIMPLE_ATTRIBUTE(fops_ul, debugfs_ul_get, debugfs_ul_set, "%llu\n");
193
194static struct dentry *debugfs_create_ul(const char *name, mode_t mode,
195 struct dentry *parent, unsigned long *value)
196{
197 return debugfs_create_file(name, mode, parent, value, &fops_ul);
198}
199
200DEFINE_SIMPLE_ATTRIBUTE(fops_ul_MAX_STACK_TRACE_DEPTH, debugfs_ul_get,
201 debugfs_ul_set_MAX_STACK_TRACE_DEPTH, "%llu\n");
202
203static struct dentry *debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
204 const char *name, mode_t mode,
205 struct dentry *parent, unsigned long *value)
206{
207 return debugfs_create_file(name, mode, parent, value,
208 &fops_ul_MAX_STACK_TRACE_DEPTH);
209}
210
211static void debugfs_atomic_t_set(void *data, u64 val)
212{
213 atomic_set((atomic_t *)data, val);
214}
215
216static u64 debugfs_atomic_t_get(void *data)
217{
218 return atomic_read((atomic_t *)data);
219}
220
221DEFINE_SIMPLE_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get,
222 debugfs_atomic_t_set, "%lld\n");
223
224static struct dentry *debugfs_create_atomic_t(const char *name, mode_t mode,
225 struct dentry *parent, atomic_t *value)
226{
227 return debugfs_create_file(name, mode, parent, value, &fops_atomic_t);
228}
229
230void cleanup_fault_attr_dentries(struct fault_attr *attr)
231{
232 debugfs_remove(attr->dentries.probability_file);
233 attr->dentries.probability_file = NULL;
234
235 debugfs_remove(attr->dentries.interval_file);
236 attr->dentries.interval_file = NULL;
237
238 debugfs_remove(attr->dentries.times_file);
239 attr->dentries.times_file = NULL;
240
241 debugfs_remove(attr->dentries.space_file);
242 attr->dentries.space_file = NULL;
243
244 debugfs_remove(attr->dentries.verbose_file);
245 attr->dentries.verbose_file = NULL;
246
247 debugfs_remove(attr->dentries.task_filter_file);
248 attr->dentries.task_filter_file = NULL;
249
250 debugfs_remove(attr->dentries.stacktrace_depth_file);
251 attr->dentries.stacktrace_depth_file = NULL;
252
253 debugfs_remove(attr->dentries.require_start_file);
254 attr->dentries.require_start_file = NULL;
255
256 debugfs_remove(attr->dentries.require_end_file);
257 attr->dentries.require_end_file = NULL;
258
259 debugfs_remove(attr->dentries.reject_start_file);
260 attr->dentries.reject_start_file = NULL;
261
262 debugfs_remove(attr->dentries.reject_end_file);
263 attr->dentries.reject_end_file = NULL;
264
265 if (attr->dentries.dir)
266 WARN_ON(!simple_empty(attr->dentries.dir));
267
268 debugfs_remove(attr->dentries.dir);
269 attr->dentries.dir = NULL;
270}
271
272int init_fault_attr_dentries(struct fault_attr *attr, const char *name)
273{
274 mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
275 struct dentry *dir;
276
277 memset(&attr->dentries, 0, sizeof(attr->dentries));
278
279 dir = debugfs_create_dir(name, NULL);
280 if (!dir)
281 goto fail;
282 attr->dentries.dir = dir;
283
284 attr->dentries.probability_file =
285 debugfs_create_ul("probability", mode, dir, &attr->probability);
286
287 attr->dentries.interval_file =
288 debugfs_create_ul("interval", mode, dir, &attr->interval);
289
290 attr->dentries.times_file =
291 debugfs_create_atomic_t("times", mode, dir, &attr->times);
292
293 attr->dentries.space_file =
294 debugfs_create_atomic_t("space", mode, dir, &attr->space);
295
296 attr->dentries.verbose_file =
297 debugfs_create_ul("verbose", mode, dir, &attr->verbose);
298
299 attr->dentries.task_filter_file = debugfs_create_bool("task-filter",
300 mode, dir, &attr->task_filter);
301
302 attr->dentries.stacktrace_depth_file =
303 debugfs_create_ul_MAX_STACK_TRACE_DEPTH(
304 "stacktrace-depth", mode, dir, &attr->stacktrace_depth);
305
306 attr->dentries.require_start_file =
307 debugfs_create_ul("require-start", mode, dir, &attr->require_start);
308
309 attr->dentries.require_end_file =
310 debugfs_create_ul("require-end", mode, dir, &attr->require_end);
311
312 attr->dentries.reject_start_file =
313 debugfs_create_ul("reject-start", mode, dir, &attr->reject_start);
314
315 attr->dentries.reject_end_file =
316 debugfs_create_ul("reject-end", mode, dir, &attr->reject_end);
317
318
319 if (!attr->dentries.probability_file || !attr->dentries.interval_file
320 || !attr->dentries.times_file || !attr->dentries.space_file
321 || !attr->dentries.verbose_file || !attr->dentries.task_filter_file
322 || !attr->dentries.stacktrace_depth_file
323 || !attr->dentries.require_start_file
324 || !attr->dentries.require_end_file
325 || !attr->dentries.reject_start_file
326 || !attr->dentries.reject_end_file
327 )
328 goto fail;
329
330 return 0;
331fail:
332 cleanup_fault_attr_dentries(attr);
333 return -ENOMEM;
334}
335
336#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */