diff options
Diffstat (limited to 'fs/ubifs')
-rw-r--r-- | fs/ubifs/debug.c | 105 | ||||
-rw-r--r-- | fs/ubifs/debug.h | 31 | ||||
-rw-r--r-- | fs/ubifs/io.c | 8 |
3 files changed, 39 insertions, 105 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 3a7344124f30..1e880cedefa4 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -2539,16 +2539,7 @@ error_dump: | |||
2539 | 2539 | ||
2540 | #define chance(n, d) (simple_rand() <= (n) * 32768LL / (d)) | 2540 | #define chance(n, d) (simple_rand() <= (n) * 32768LL / (d)) |
2541 | 2541 | ||
2542 | struct failure_mode_info { | ||
2543 | struct list_head list; | ||
2544 | struct ubifs_info *c; | ||
2545 | }; | ||
2546 | |||
2547 | static LIST_HEAD(fmi_list); | ||
2548 | static DEFINE_SPINLOCK(fmi_lock); | ||
2549 | |||
2550 | static unsigned int next; | 2542 | static unsigned int next; |
2551 | |||
2552 | static int simple_rand(void) | 2543 | static int simple_rand(void) |
2553 | { | 2544 | { |
2554 | if (next == 0) | 2545 | if (next == 0) |
@@ -2557,69 +2548,15 @@ static int simple_rand(void) | |||
2557 | return (next >> 16) & 32767; | 2548 | return (next >> 16) & 32767; |
2558 | } | 2549 | } |
2559 | 2550 | ||
2560 | static void failure_mode_init(struct ubifs_info *c) | 2551 | static int do_fail(struct ubifs_info *c, int lnum, int write) |
2561 | { | ||
2562 | struct failure_mode_info *fmi; | ||
2563 | |||
2564 | fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS); | ||
2565 | if (!fmi) { | ||
2566 | ubifs_err("Failed to register failure mode - no memory"); | ||
2567 | return; | ||
2568 | } | ||
2569 | fmi->c = c; | ||
2570 | spin_lock(&fmi_lock); | ||
2571 | list_add_tail(&fmi->list, &fmi_list); | ||
2572 | spin_unlock(&fmi_lock); | ||
2573 | } | ||
2574 | |||
2575 | static void failure_mode_exit(struct ubifs_info *c) | ||
2576 | { | ||
2577 | struct failure_mode_info *fmi, *tmp; | ||
2578 | |||
2579 | spin_lock(&fmi_lock); | ||
2580 | list_for_each_entry_safe(fmi, tmp, &fmi_list, list) | ||
2581 | if (fmi->c == c) { | ||
2582 | list_del(&fmi->list); | ||
2583 | kfree(fmi); | ||
2584 | } | ||
2585 | spin_unlock(&fmi_lock); | ||
2586 | } | ||
2587 | |||
2588 | static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc) | ||
2589 | { | 2552 | { |
2590 | struct failure_mode_info *fmi; | 2553 | struct ubifs_debug_info *d = c->dbg; |
2591 | |||
2592 | spin_lock(&fmi_lock); | ||
2593 | list_for_each_entry(fmi, &fmi_list, list) | ||
2594 | if (fmi->c->ubi == desc) { | ||
2595 | struct ubifs_info *c = fmi->c; | ||
2596 | |||
2597 | spin_unlock(&fmi_lock); | ||
2598 | return c; | ||
2599 | } | ||
2600 | spin_unlock(&fmi_lock); | ||
2601 | return NULL; | ||
2602 | } | ||
2603 | |||
2604 | static int in_failure_mode(struct ubi_volume_desc *desc) | ||
2605 | { | ||
2606 | struct ubifs_info *c = dbg_find_info(desc); | ||
2607 | 2554 | ||
2608 | if (c && dbg_is_tst_rcvry(c)) | 2555 | ubifs_assert(dbg_is_tst_rcvry(c)); |
2609 | return c->dbg->failure_mode; | ||
2610 | return 0; | ||
2611 | } | ||
2612 | 2556 | ||
2613 | static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) | ||
2614 | { | ||
2615 | struct ubifs_info *c = dbg_find_info(desc); | ||
2616 | struct ubifs_debug_info *d; | ||
2617 | |||
2618 | if (!c || !dbg_is_tst_rcvry(c)) | ||
2619 | return 0; | ||
2620 | d = c->dbg; | ||
2621 | if (d->failure_mode) | 2557 | if (d->failure_mode) |
2622 | return 1; | 2558 | return 1; |
2559 | |||
2623 | if (!d->fail_cnt) { | 2560 | if (!d->fail_cnt) { |
2624 | /* First call - decide delay to failure */ | 2561 | /* First call - decide delay to failure */ |
2625 | if (chance(1, 2)) { | 2562 | if (chance(1, 2)) { |
@@ -2716,17 +2653,17 @@ static void cut_data(const void *buf, int len) | |||
2716 | p[i] = 0xff; | 2653 | p[i] = 0xff; |
2717 | } | 2654 | } |
2718 | 2655 | ||
2719 | int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, | 2656 | int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, |
2720 | int offs, int len, int dtype) | 2657 | int offs, int len, int dtype) |
2721 | { | 2658 | { |
2722 | int err, failing; | 2659 | int err, failing; |
2723 | 2660 | ||
2724 | if (in_failure_mode(desc)) | 2661 | if (c->dbg->failure_mode) |
2725 | return -EROFS; | 2662 | return -EROFS; |
2726 | failing = do_fail(desc, lnum, 1); | 2663 | failing = do_fail(c, lnum, 1); |
2727 | if (failing) | 2664 | if (failing) |
2728 | cut_data(buf, len); | 2665 | cut_data(buf, len); |
2729 | err = ubi_leb_write(desc, lnum, buf, offs, len, dtype); | 2666 | err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); |
2730 | if (err) | 2667 | if (err) |
2731 | return err; | 2668 | return err; |
2732 | if (failing) | 2669 | if (failing) |
@@ -2734,45 +2671,45 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, | |||
2734 | return 0; | 2671 | return 0; |
2735 | } | 2672 | } |
2736 | 2673 | ||
2737 | int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, | 2674 | int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, |
2738 | int len, int dtype) | 2675 | int len, int dtype) |
2739 | { | 2676 | { |
2740 | int err; | 2677 | int err; |
2741 | 2678 | ||
2742 | if (do_fail(desc, lnum, 1)) | 2679 | if (do_fail(c, lnum, 1)) |
2743 | return -EROFS; | 2680 | return -EROFS; |
2744 | err = ubi_leb_change(desc, lnum, buf, len, dtype); | 2681 | err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); |
2745 | if (err) | 2682 | if (err) |
2746 | return err; | 2683 | return err; |
2747 | if (do_fail(desc, lnum, 1)) | 2684 | if (do_fail(c, lnum, 1)) |
2748 | return -EROFS; | 2685 | return -EROFS; |
2749 | return 0; | 2686 | return 0; |
2750 | } | 2687 | } |
2751 | 2688 | ||
2752 | int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum) | 2689 | int dbg_leb_unmap(struct ubifs_info *c, int lnum) |
2753 | { | 2690 | { |
2754 | int err; | 2691 | int err; |
2755 | 2692 | ||
2756 | if (do_fail(desc, lnum, 0)) | 2693 | if (do_fail(c, lnum, 0)) |
2757 | return -EROFS; | 2694 | return -EROFS; |
2758 | err = ubi_leb_unmap(desc, lnum); | 2695 | err = ubi_leb_unmap(c->ubi, lnum); |
2759 | if (err) | 2696 | if (err) |
2760 | return err; | 2697 | return err; |
2761 | if (do_fail(desc, lnum, 0)) | 2698 | if (do_fail(c, lnum, 0)) |
2762 | return -EROFS; | 2699 | return -EROFS; |
2763 | return 0; | 2700 | return 0; |
2764 | } | 2701 | } |
2765 | 2702 | ||
2766 | int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) | 2703 | int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype) |
2767 | { | 2704 | { |
2768 | int err; | 2705 | int err; |
2769 | 2706 | ||
2770 | if (do_fail(desc, lnum, 0)) | 2707 | if (do_fail(c, lnum, 0)) |
2771 | return -EROFS; | 2708 | return -EROFS; |
2772 | err = ubi_leb_map(desc, lnum, dtype); | 2709 | err = ubi_leb_map(c->ubi, lnum, dtype); |
2773 | if (err) | 2710 | if (err) |
2774 | return err; | 2711 | return err; |
2775 | if (do_fail(desc, lnum, 0)) | 2712 | if (do_fail(c, lnum, 0)) |
2776 | return -EROFS; | 2713 | return -EROFS; |
2777 | return 0; | 2714 | return 0; |
2778 | } | 2715 | } |
@@ -3210,7 +3147,6 @@ int ubifs_debugging_init(struct ubifs_info *c) | |||
3210 | if (!c->dbg) | 3147 | if (!c->dbg) |
3211 | return -ENOMEM; | 3148 | return -ENOMEM; |
3212 | 3149 | ||
3213 | failure_mode_init(c); | ||
3214 | return 0; | 3150 | return 0; |
3215 | } | 3151 | } |
3216 | 3152 | ||
@@ -3220,7 +3156,6 @@ int ubifs_debugging_init(struct ubifs_info *c) | |||
3220 | */ | 3156 | */ |
3221 | void ubifs_debugging_exit(struct ubifs_info *c) | 3157 | void ubifs_debugging_exit(struct ubifs_info *c) |
3222 | { | 3158 | { |
3223 | failure_mode_exit(c); | ||
3224 | kfree(c->dbg); | 3159 | kfree(c->dbg); |
3225 | } | 3160 | } |
3226 | 3161 | ||
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index b5bc09deeb32..0ab3757ef0e3 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h | |||
@@ -305,12 +305,12 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode, | |||
305 | int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head); | 305 | int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head); |
306 | int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head); | 306 | int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head); |
307 | 307 | ||
308 | int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, | 308 | int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs, |
309 | int offs, int len, int dtype); | 309 | int len, int dtype); |
310 | int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, | 310 | int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len, |
311 | int len, int dtype); | 311 | int dtype); |
312 | int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum); | 312 | int dbg_leb_unmap(struct ubifs_info *c, int lnum); |
313 | int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype); | 313 | int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype); |
314 | 314 | ||
315 | /* Debugfs-related stuff */ | 315 | /* Debugfs-related stuff */ |
316 | int dbg_debugfs_init(void); | 316 | int dbg_debugfs_init(void); |
@@ -442,16 +442,15 @@ static inline int | |||
442 | dbg_check_nondata_nodes_order(struct ubifs_info *c, | 442 | dbg_check_nondata_nodes_order(struct ubifs_info *c, |
443 | struct list_head *head) { return 0; } | 443 | struct list_head *head) { return 0; } |
444 | 444 | ||
445 | static inline int dbg_leb_write(struct ubi_volume_desc *desc, | 445 | static inline int dbg_leb_write(struct ubifs_info *c, int lnum, |
446 | int lnum, const void *buf, | 446 | const void *buf, int offset, |
447 | int offset, int len, int dtype) { return 0; } | 447 | int len, int dtype) { return 0; } |
448 | static inline int dbg_leb_change(struct ubi_volume_desc *desc, | 448 | static inline int dbg_leb_change(struct ubifs_info *c, int lnum, |
449 | int lnum, const void *buf, | 449 | const void *buf, int len, |
450 | int len, int dtype) { return 0; } | 450 | int dtype) { return 0; } |
451 | static inline int dbg_leb_unmap(struct ubi_volume_desc *desc, | 451 | static inline int dbg_leb_unmap(struct ubifs_info *c, int lnum) { return 0; } |
452 | int lnum) { return 0; } | 452 | static inline int dbg_leb_map(struct ubifs_info *c, int lnum, |
453 | static inline int dbg_leb_map(struct ubi_volume_desc *desc, | 453 | int dtype) { return 0; } |
454 | int lnum, int dtype) { return 0; } | ||
455 | 454 | ||
456 | static inline int dbg_is_chk_gen(const struct ubifs_info *c) { return 0; } | 455 | static inline int dbg_is_chk_gen(const struct ubifs_info *c) { return 0; } |
457 | static inline int dbg_is_chk_index(const struct ubifs_info *c) { return 0; } | 456 | static inline int dbg_is_chk_index(const struct ubifs_info *c) { return 0; } |
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index a0c5fb4b6fa8..9228950a658f 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
@@ -125,7 +125,7 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs, | |||
125 | if (!dbg_is_tst_rcvry(c)) | 125 | if (!dbg_is_tst_rcvry(c)) |
126 | err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); | 126 | err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype); |
127 | else | 127 | else |
128 | err = dbg_leb_write(c->ubi, lnum, buf, offs, len, dtype); | 128 | err = dbg_leb_write(c, lnum, buf, offs, len, dtype); |
129 | if (err) { | 129 | if (err) { |
130 | ubifs_err("writing %d bytes to LEB %d:%d failed, error %d", | 130 | ubifs_err("writing %d bytes to LEB %d:%d failed, error %d", |
131 | len, lnum, offs, err); | 131 | len, lnum, offs, err); |
@@ -146,7 +146,7 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len, | |||
146 | if (!dbg_is_tst_rcvry(c)) | 146 | if (!dbg_is_tst_rcvry(c)) |
147 | err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); | 147 | err = ubi_leb_change(c->ubi, lnum, buf, len, dtype); |
148 | else | 148 | else |
149 | err = dbg_leb_change(c->ubi, lnum, buf, len, dtype); | 149 | err = dbg_leb_change(c, lnum, buf, len, dtype); |
150 | if (err) { | 150 | if (err) { |
151 | ubifs_err("changing %d bytes in LEB %d failed, error %d", | 151 | ubifs_err("changing %d bytes in LEB %d failed, error %d", |
152 | len, lnum, err); | 152 | len, lnum, err); |
@@ -166,7 +166,7 @@ int ubifs_leb_unmap(struct ubifs_info *c, int lnum) | |||
166 | if (!dbg_is_tst_rcvry(c)) | 166 | if (!dbg_is_tst_rcvry(c)) |
167 | err = ubi_leb_unmap(c->ubi, lnum); | 167 | err = ubi_leb_unmap(c->ubi, lnum); |
168 | else | 168 | else |
169 | err = dbg_leb_unmap(c->ubi, lnum); | 169 | err = dbg_leb_unmap(c, lnum); |
170 | if (err) { | 170 | if (err) { |
171 | ubifs_err("unmap LEB %d failed, error %d", lnum, err); | 171 | ubifs_err("unmap LEB %d failed, error %d", lnum, err); |
172 | ubifs_ro_mode(c, err); | 172 | ubifs_ro_mode(c, err); |
@@ -185,7 +185,7 @@ int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype) | |||
185 | if (!dbg_is_tst_rcvry(c)) | 185 | if (!dbg_is_tst_rcvry(c)) |
186 | err = ubi_leb_map(c->ubi, lnum, dtype); | 186 | err = ubi_leb_map(c->ubi, lnum, dtype); |
187 | else | 187 | else |
188 | err = dbg_leb_map(c->ubi, lnum, dtype); | 188 | err = dbg_leb_map(c, lnum, dtype); |
189 | if (err) { | 189 | if (err) { |
190 | ubifs_err("mapping LEB %d failed, error %d", lnum, err); | 190 | ubifs_err("mapping LEB %d failed, error %d", lnum, err); |
191 | ubifs_ro_mode(c, err); | 191 | ubifs_ro_mode(c, err); |