diff options
| -rw-r--r-- | fs/ubifs/debug.c | 52 | ||||
| -rw-r--r-- | fs/ubifs/debug.h | 22 |
2 files changed, 39 insertions, 35 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 1e880cedefa4..b801af7837e9 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
| @@ -2548,39 +2548,36 @@ static int simple_rand(void) | |||
| 2548 | return (next >> 16) & 32767; | 2548 | return (next >> 16) & 32767; |
| 2549 | } | 2549 | } |
| 2550 | 2550 | ||
| 2551 | static int do_fail(struct ubifs_info *c, int lnum, int write) | 2551 | static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) |
| 2552 | { | 2552 | { |
| 2553 | struct ubifs_debug_info *d = c->dbg; | 2553 | struct ubifs_debug_info *d = c->dbg; |
| 2554 | 2554 | ||
| 2555 | ubifs_assert(dbg_is_tst_rcvry(c)); | 2555 | ubifs_assert(dbg_is_tst_rcvry(c)); |
| 2556 | 2556 | ||
| 2557 | if (d->failure_mode) | 2557 | if (!d->pc_cnt) { |
| 2558 | return 1; | 2558 | /* First call - decide delay to the power cut */ |
| 2559 | |||
| 2560 | if (!d->fail_cnt) { | ||
| 2561 | /* First call - decide delay to failure */ | ||
| 2562 | if (chance(1, 2)) { | 2559 | if (chance(1, 2)) { |
| 2563 | unsigned int delay = 1 << (simple_rand() >> 11); | 2560 | unsigned int delay = 1 << (simple_rand() >> 11); |
| 2564 | 2561 | ||
| 2565 | if (chance(1, 2)) { | 2562 | if (chance(1, 2)) { |
| 2566 | d->fail_delay = 1; | 2563 | d->pc_delay = 1; |
| 2567 | d->fail_timeout = jiffies + | 2564 | d->pc_timeout = jiffies + |
| 2568 | msecs_to_jiffies(delay); | 2565 | msecs_to_jiffies(delay); |
| 2569 | ubifs_warn("failing after %ums", delay); | 2566 | ubifs_warn("failing after %ums", delay); |
| 2570 | } else { | 2567 | } else { |
| 2571 | d->fail_delay = 2; | 2568 | d->pc_delay = 2; |
| 2572 | d->fail_cnt_max = delay; | 2569 | d->pc_cnt_max = delay; |
| 2573 | ubifs_warn("failing after %u calls", delay); | 2570 | ubifs_warn("failing after %u calls", delay); |
| 2574 | } | 2571 | } |
| 2575 | } | 2572 | } |
| 2576 | d->fail_cnt += 1; | 2573 | d->pc_cnt += 1; |
| 2577 | } | 2574 | } |
| 2578 | /* Determine if failure delay has expired */ | 2575 | /* Determine if failure delay has expired */ |
| 2579 | if (d->fail_delay == 1) { | 2576 | if (d->pc_delay == 1) { |
| 2580 | if (time_before(jiffies, d->fail_timeout)) | 2577 | if (time_before(jiffies, d->pc_timeout)) |
| 2581 | return 0; | 2578 | return 0; |
| 2582 | } else if (d->fail_delay == 2) | 2579 | } else if (d->pc_delay == 2) |
| 2583 | if (d->fail_cnt++ < d->fail_cnt_max) | 2580 | if (d->pc_cnt++ < d->pc_cnt_max) |
| 2584 | return 0; | 2581 | return 0; |
| 2585 | if (lnum == UBIFS_SB_LNUM) { | 2582 | if (lnum == UBIFS_SB_LNUM) { |
| 2586 | if (write) { | 2583 | if (write) { |
| @@ -2638,7 +2635,7 @@ static int do_fail(struct ubifs_info *c, int lnum, int write) | |||
| 2638 | ubifs_warn("failing in bud LEB %d commit not running", lnum); | 2635 | ubifs_warn("failing in bud LEB %d commit not running", lnum); |
| 2639 | } | 2636 | } |
| 2640 | 2637 | ||
| 2641 | d->failure_mode = 1; | 2638 | d->pc_happened = 1; |
| 2642 | dump_stack(); | 2639 | dump_stack(); |
| 2643 | return 1; | 2640 | return 1; |
| 2644 | } | 2641 | } |
| @@ -2658,9 +2655,10 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, | |||
| 2658 | { | 2655 | { |
| 2659 | int err, failing; | 2656 | int err, failing; |
| 2660 | 2657 | ||
| 2661 | if (c->dbg->failure_mode) | 2658 | if (c->dbg->pc_happened) |
| 2662 | return -EROFS; | 2659 | return -EROFS; |
| 2663 | failing = do_fail(c, lnum, 1); | 2660 | |
| 2661 | failing = power_cut_emulated(c, lnum, 1); | ||
| 2664 | if (failing) | 2662 | if (failing) |
| 2665 | cut_data(buf, len); | 2663 | cut_data(buf, len); |
| 2666 | err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); | 2664 | err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); |
| @@ -2676,12 +2674,14 @@ int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, | |||
| 2676 | { | 2674 | { |
| 2677 | int err; | 2675 | int err; |
| 2678 | 2676 | ||
| 2679 | if (do_fail(c, lnum, 1)) | 2677 | if (c->dbg->pc_happened) |
| 2678 | return -EROFS; | ||
| 2679 | if (power_cut_emulated(c, lnum, 1)) | ||
| 2680 | return -EROFS; | 2680 | return -EROFS; |
| 2681 | err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); | 2681 | err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); |
| 2682 | if (err) | 2682 | if (err) |
| 2683 | return err; | 2683 | return err; |
| 2684 | if (do_fail(c, lnum, 1)) | 2684 | if (power_cut_emulated(c, lnum, 1)) |
| 2685 | return -EROFS; | 2685 | return -EROFS; |
| 2686 | return 0; | 2686 | return 0; |
| 2687 | } | 2687 | } |
| @@ -2690,12 +2690,14 @@ int dbg_leb_unmap(struct ubifs_info *c, int lnum) | |||
| 2690 | { | 2690 | { |
| 2691 | int err; | 2691 | int err; |
| 2692 | 2692 | ||
| 2693 | if (do_fail(c, lnum, 0)) | 2693 | if (c->dbg->pc_happened) |
| 2694 | return -EROFS; | ||
| 2695 | if (power_cut_emulated(c, lnum, 0)) | ||
| 2694 | return -EROFS; | 2696 | return -EROFS; |
| 2695 | err = ubi_leb_unmap(c->ubi, lnum); | 2697 | err = ubi_leb_unmap(c->ubi, lnum); |
| 2696 | if (err) | 2698 | if (err) |
| 2697 | return err; | 2699 | return err; |
| 2698 | if (do_fail(c, lnum, 0)) | 2700 | if (power_cut_emulated(c, lnum, 0)) |
| 2699 | return -EROFS; | 2701 | return -EROFS; |
| 2700 | return 0; | 2702 | return 0; |
| 2701 | } | 2703 | } |
| @@ -2704,12 +2706,14 @@ int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype) | |||
| 2704 | { | 2706 | { |
| 2705 | int err; | 2707 | int err; |
| 2706 | 2708 | ||
| 2707 | if (do_fail(c, lnum, 0)) | 2709 | if (c->dbg->pc_happened) |
| 2710 | return -EROFS; | ||
| 2711 | if (power_cut_emulated(c, lnum, 0)) | ||
| 2708 | return -EROFS; | 2712 | return -EROFS; |
| 2709 | err = ubi_leb_map(c->ubi, lnum, dtype); | 2713 | err = ubi_leb_map(c->ubi, lnum, dtype); |
| 2710 | if (err) | 2714 | if (err) |
| 2711 | return err; | 2715 | return err; |
| 2712 | if (do_fail(c, lnum, 0)) | 2716 | if (power_cut_emulated(c, lnum, 0)) |
| 2713 | return -EROFS; | 2717 | return -EROFS; |
| 2714 | return 0; | 2718 | return 0; |
| 2715 | } | 2719 | } |
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 0ab3757ef0e3..45174b534377 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h | |||
| @@ -44,11 +44,11 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c, | |||
| 44 | * @old_zroot_level: old index root level - used by 'dbg_check_old_index()' | 44 | * @old_zroot_level: old index root level - used by 'dbg_check_old_index()' |
| 45 | * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()' | 45 | * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()' |
| 46 | * | 46 | * |
| 47 | * @failure_mode: failure mode for recovery testing | 47 | * @pc_happened: non-zero if an emulated power cut happened |
| 48 | * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls | 48 | * @pc_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls |
| 49 | * @fail_timeout: time in jiffies when delay of failure mode expires | 49 | * @pc_timeout: time in jiffies when delay of failure mode expires |
| 50 | * @fail_cnt: current number of calls to failure mode I/O functions | 50 | * @pc_cnt: current number of calls to failure mode I/O functions |
| 51 | * @fail_cnt_max: number of calls by which to delay failure mode | 51 | * @pc_cnt_max: number of calls by which to delay failure mode |
| 52 | * | 52 | * |
| 53 | * @chk_lpt_sz: used by LPT tree size checker | 53 | * @chk_lpt_sz: used by LPT tree size checker |
| 54 | * @chk_lpt_sz2: used by LPT tree size checker | 54 | * @chk_lpt_sz2: used by LPT tree size checker |
| @@ -87,11 +87,11 @@ struct ubifs_debug_info { | |||
| 87 | int old_zroot_level; | 87 | int old_zroot_level; |
| 88 | unsigned long long old_zroot_sqnum; | 88 | unsigned long long old_zroot_sqnum; |
| 89 | 89 | ||
| 90 | int failure_mode; | 90 | int pc_happened; |
| 91 | int fail_delay; | 91 | int pc_delay; |
| 92 | unsigned long fail_timeout; | 92 | unsigned long pc_timeout; |
| 93 | unsigned int fail_cnt; | 93 | unsigned int pc_cnt; |
| 94 | unsigned int fail_cnt_max; | 94 | unsigned int pc_cnt_max; |
| 95 | 95 | ||
| 96 | long long chk_lpt_sz; | 96 | long long chk_lpt_sz; |
| 97 | long long chk_lpt_sz2; | 97 | long long chk_lpt_sz2; |
| @@ -246,7 +246,7 @@ static inline int dbg_is_tst_rcvry(const struct ubifs_info *c) | |||
| 246 | } | 246 | } |
| 247 | static inline int dbg_is_power_cut(const struct ubifs_info *c) | 247 | static inline int dbg_is_power_cut(const struct ubifs_info *c) |
| 248 | { | 248 | { |
| 249 | return !!c->dbg->failure_mode; | 249 | return !!c->dbg->pc_happened; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | int ubifs_debugging_init(struct ubifs_info *c); | 252 | int ubifs_debugging_init(struct ubifs_info *c); |
