aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ubifs/debug.c52
-rw-r--r--fs/ubifs/debug.h22
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
2551static int do_fail(struct ubifs_info *c, int lnum, int write) 2551static 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}
247static inline int dbg_is_power_cut(const struct ubifs_info *c) 247static 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
252int ubifs_debugging_init(struct ubifs_info *c); 252int ubifs_debugging_init(struct ubifs_info *c);