diff options
Diffstat (limited to 'fs/ubifs/debug.c')
-rw-r--r-- | fs/ubifs/debug.c | 91 |
1 files changed, 50 insertions, 41 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index b801af7837e9..eef109a1a927 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -27,11 +27,12 @@ | |||
27 | * various local functions of those subsystems. | 27 | * various local functions of those subsystems. |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include "ubifs.h" | ||
31 | #include <linux/module.h> | 30 | #include <linux/module.h> |
32 | #include <linux/debugfs.h> | 31 | #include <linux/debugfs.h> |
33 | #include <linux/math64.h> | 32 | #include <linux/math64.h> |
34 | #include <linux/uaccess.h> | 33 | #include <linux/uaccess.h> |
34 | #include <linux/random.h> | ||
35 | #include "ubifs.h" | ||
35 | 36 | ||
36 | #ifdef CONFIG_UBIFS_FS_DEBUG | 37 | #ifdef CONFIG_UBIFS_FS_DEBUG |
37 | 38 | ||
@@ -2535,17 +2536,10 @@ error_dump: | |||
2535 | return 0; | 2536 | return 0; |
2536 | } | 2537 | } |
2537 | 2538 | ||
2538 | /* Failure mode for recovery testing */ | 2539 | static inline int chance(unsigned int n, unsigned int out_of) |
2539 | |||
2540 | #define chance(n, d) (simple_rand() <= (n) * 32768LL / (d)) | ||
2541 | |||
2542 | static unsigned int next; | ||
2543 | static int simple_rand(void) | ||
2544 | { | 2540 | { |
2545 | if (next == 0) | 2541 | return !!((random32() % out_of) + 1 <= n); |
2546 | next = current->pid; | 2542 | |
2547 | next = next * 1103515245 + 12345; | ||
2548 | return (next >> 16) & 32767; | ||
2549 | } | 2543 | } |
2550 | 2544 | ||
2551 | static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) | 2545 | static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) |
@@ -2557,33 +2551,37 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) | |||
2557 | if (!d->pc_cnt) { | 2551 | if (!d->pc_cnt) { |
2558 | /* First call - decide delay to the power cut */ | 2552 | /* First call - decide delay to the power cut */ |
2559 | if (chance(1, 2)) { | 2553 | if (chance(1, 2)) { |
2560 | unsigned int delay = 1 << (simple_rand() >> 11); | 2554 | unsigned long delay; |
2561 | 2555 | ||
2562 | if (chance(1, 2)) { | 2556 | if (chance(1, 2)) { |
2563 | d->pc_delay = 1; | 2557 | d->pc_delay = 1; |
2564 | d->pc_timeout = jiffies + | 2558 | /* Fail withing 1 minute */ |
2565 | msecs_to_jiffies(delay); | 2559 | delay = random32() % 60000; |
2566 | ubifs_warn("failing after %ums", delay); | 2560 | d->pc_timeout = jiffies; |
2561 | d->pc_timeout += msecs_to_jiffies(delay); | ||
2562 | ubifs_warn("failing after %lums", delay); | ||
2567 | } else { | 2563 | } else { |
2568 | d->pc_delay = 2; | 2564 | d->pc_delay = 2; |
2565 | delay = random32() % 10000; | ||
2566 | /* Fail within 10000 operations */ | ||
2569 | d->pc_cnt_max = delay; | 2567 | d->pc_cnt_max = delay; |
2570 | ubifs_warn("failing after %u calls", delay); | 2568 | ubifs_warn("failing after %lu calls", delay); |
2571 | } | 2569 | } |
2572 | } | 2570 | } |
2571 | |||
2573 | d->pc_cnt += 1; | 2572 | d->pc_cnt += 1; |
2574 | } | 2573 | } |
2574 | |||
2575 | /* Determine if failure delay has expired */ | 2575 | /* Determine if failure delay has expired */ |
2576 | if (d->pc_delay == 1) { | 2576 | if (d->pc_delay == 1 && time_before(jiffies, d->pc_timeout)) |
2577 | if (time_before(jiffies, d->pc_timeout)) | ||
2578 | return 0; | 2577 | return 0; |
2579 | } else if (d->pc_delay == 2) | 2578 | if (d->pc_delay == 2 && d->pc_cnt++ < d->pc_cnt_max) |
2580 | if (d->pc_cnt++ < d->pc_cnt_max) | ||
2581 | return 0; | 2579 | return 0; |
2580 | |||
2582 | if (lnum == UBIFS_SB_LNUM) { | 2581 | if (lnum == UBIFS_SB_LNUM) { |
2583 | if (write) { | 2582 | if (write && chance(1, 2)) |
2584 | if (chance(1, 2)) | 2583 | return 0; |
2585 | return 0; | 2584 | if (chance(19, 20)) |
2586 | } else if (chance(19, 20)) | ||
2587 | return 0; | 2585 | return 0; |
2588 | ubifs_warn("failing in super block LEB %d", lnum); | 2586 | ubifs_warn("failing in super block LEB %d", lnum); |
2589 | } else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) { | 2587 | } else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) { |
@@ -2591,24 +2589,21 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) | |||
2591 | return 0; | 2589 | return 0; |
2592 | ubifs_warn("failing in master LEB %d", lnum); | 2590 | ubifs_warn("failing in master LEB %d", lnum); |
2593 | } else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) { | 2591 | } else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) { |
2594 | if (write) { | 2592 | if (write && chance(99, 100)) |
2595 | if (chance(99, 100)) | 2593 | return 0; |
2596 | return 0; | 2594 | if (chance(399, 400)) |
2597 | } else if (chance(399, 400)) | ||
2598 | return 0; | 2595 | return 0; |
2599 | ubifs_warn("failing in log LEB %d", lnum); | 2596 | ubifs_warn("failing in log LEB %d", lnum); |
2600 | } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) { | 2597 | } else if (lnum >= c->lpt_first && lnum <= c->lpt_last) { |
2601 | if (write) { | 2598 | if (write && chance(7, 8)) |
2602 | if (chance(7, 8)) | 2599 | return 0; |
2603 | return 0; | 2600 | if (chance(19, 20)) |
2604 | } else if (chance(19, 20)) | ||
2605 | return 0; | 2601 | return 0; |
2606 | ubifs_warn("failing in LPT LEB %d", lnum); | 2602 | ubifs_warn("failing in LPT LEB %d", lnum); |
2607 | } else if (lnum >= c->orph_first && lnum <= c->orph_last) { | 2603 | } else if (lnum >= c->orph_first && lnum <= c->orph_last) { |
2608 | if (write) { | 2604 | if (write && chance(1, 2)) |
2609 | if (chance(1, 2)) | 2605 | return 0; |
2610 | return 0; | 2606 | if (chance(9, 10)) |
2611 | } else if (chance(9, 10)) | ||
2612 | return 0; | 2607 | return 0; |
2613 | ubifs_warn("failing in orphan LEB %d", lnum); | 2608 | ubifs_warn("failing in orphan LEB %d", lnum); |
2614 | } else if (lnum == c->ihead_lnum) { | 2609 | } else if (lnum == c->ihead_lnum) { |
@@ -2636,18 +2631,32 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) | |||
2636 | } | 2631 | } |
2637 | 2632 | ||
2638 | d->pc_happened = 1; | 2633 | d->pc_happened = 1; |
2634 | ubifs_warn("========== Power cut emulated =========="); | ||
2639 | dump_stack(); | 2635 | dump_stack(); |
2640 | return 1; | 2636 | return 1; |
2641 | } | 2637 | } |
2642 | 2638 | ||
2643 | static void cut_data(const void *buf, int len) | 2639 | static void cut_data(const void *buf, unsigned int len) |
2644 | { | 2640 | { |
2645 | int flen, i; | 2641 | unsigned int from, to, i, ffs = chance(1, 2); |
2646 | unsigned char *p = (void *)buf; | 2642 | unsigned char *p = (void *)buf; |
2647 | 2643 | ||
2648 | flen = (len * (long long)simple_rand()) >> 15; | 2644 | from = random32() % (len + 1); |
2649 | for (i = flen; i < len; i++) | 2645 | if (chance(1, 2)) |
2650 | p[i] = 0xff; | 2646 | to = random32() % (len - from + 1); |
2647 | else | ||
2648 | to = len; | ||
2649 | |||
2650 | if (from < to) | ||
2651 | ubifs_warn("filled bytes %u-%u with %s", from, to - 1, | ||
2652 | ffs ? "0xFFs" : "random data"); | ||
2653 | |||
2654 | if (ffs) | ||
2655 | for (i = from; i < to; i++) | ||
2656 | p[i] = 0xFF; | ||
2657 | else | ||
2658 | for (i = from; i < to; i++) | ||
2659 | p[i] = random32() % 0x100; | ||
2651 | } | 2660 | } |
2652 | 2661 | ||
2653 | int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, | 2662 | int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, |