diff options
Diffstat (limited to 'fs/ubifs/debug.c')
-rw-r--r-- | fs/ubifs/debug.c | 327 |
1 files changed, 291 insertions, 36 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 510ffa0bbda4..e975bd82f38b 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include "ubifs.h" | 32 | #include "ubifs.h" |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
35 | #include <linux/debugfs.h> | ||
36 | #include <linux/math64.h> | ||
35 | 37 | ||
36 | #ifdef CONFIG_UBIFS_FS_DEBUG | 38 | #ifdef CONFIG_UBIFS_FS_DEBUG |
37 | 39 | ||
@@ -596,7 +598,9 @@ void dbg_dump_budg(struct ubifs_info *c) | |||
596 | struct rb_node *rb; | 598 | struct rb_node *rb; |
597 | struct ubifs_bud *bud; | 599 | struct ubifs_bud *bud; |
598 | struct ubifs_gced_idx_leb *idx_gc; | 600 | struct ubifs_gced_idx_leb *idx_gc; |
601 | long long available, outstanding, free; | ||
599 | 602 | ||
603 | ubifs_assert(spin_is_locked(&c->space_lock)); | ||
600 | spin_lock(&dbg_lock); | 604 | spin_lock(&dbg_lock); |
601 | printk(KERN_DEBUG "(pid %d) Budgeting info: budg_data_growth %lld, " | 605 | printk(KERN_DEBUG "(pid %d) Budgeting info: budg_data_growth %lld, " |
602 | "budg_dd_growth %lld, budg_idx_growth %lld\n", current->pid, | 606 | "budg_dd_growth %lld, budg_idx_growth %lld\n", current->pid, |
@@ -616,9 +620,11 @@ void dbg_dump_budg(struct ubifs_info *c) | |||
616 | c->dark_wm, c->dead_wm, c->max_idx_node_sz); | 620 | c->dark_wm, c->dead_wm, c->max_idx_node_sz); |
617 | printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", | 621 | printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", |
618 | c->gc_lnum, c->ihead_lnum); | 622 | c->gc_lnum, c->ihead_lnum); |
619 | for (i = 0; i < c->jhead_cnt; i++) | 623 | /* If we are in R/O mode, journal heads do not exist */ |
620 | printk(KERN_DEBUG "\tjhead %d\t LEB %d\n", | 624 | if (c->jheads) |
621 | c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum); | 625 | for (i = 0; i < c->jhead_cnt; i++) |
626 | printk(KERN_DEBUG "\tjhead %d\t LEB %d\n", | ||
627 | c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum); | ||
622 | for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) { | 628 | for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) { |
623 | bud = rb_entry(rb, struct ubifs_bud, rb); | 629 | bud = rb_entry(rb, struct ubifs_bud, rb); |
624 | printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum); | 630 | printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum); |
@@ -629,6 +635,14 @@ void dbg_dump_budg(struct ubifs_info *c) | |||
629 | printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n", | 635 | printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n", |
630 | idx_gc->lnum, idx_gc->unmap); | 636 | idx_gc->lnum, idx_gc->unmap); |
631 | printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state); | 637 | printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state); |
638 | |||
639 | /* Print budgeting predictions */ | ||
640 | available = ubifs_calc_available(c, c->min_idx_lebs); | ||
641 | outstanding = c->budg_data_growth + c->budg_dd_growth; | ||
642 | free = ubifs_get_free_space_nolock(c); | ||
643 | printk(KERN_DEBUG "Budgeting predictions:\n"); | ||
644 | printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n", | ||
645 | available, outstanding, free); | ||
632 | spin_unlock(&dbg_lock); | 646 | spin_unlock(&dbg_lock); |
633 | } | 647 | } |
634 | 648 | ||
@@ -645,7 +659,8 @@ void dbg_dump_lprops(struct ubifs_info *c) | |||
645 | struct ubifs_lprops lp; | 659 | struct ubifs_lprops lp; |
646 | struct ubifs_lp_stats lst; | 660 | struct ubifs_lp_stats lst; |
647 | 661 | ||
648 | printk(KERN_DEBUG "(pid %d) Dumping LEB properties\n", current->pid); | 662 | printk(KERN_DEBUG "(pid %d) start dumping LEB properties\n", |
663 | current->pid); | ||
649 | ubifs_get_lp_stats(c, &lst); | 664 | ubifs_get_lp_stats(c, &lst); |
650 | dbg_dump_lstats(&lst); | 665 | dbg_dump_lstats(&lst); |
651 | 666 | ||
@@ -656,6 +671,8 @@ void dbg_dump_lprops(struct ubifs_info *c) | |||
656 | 671 | ||
657 | dbg_dump_lprop(c, &lp); | 672 | dbg_dump_lprop(c, &lp); |
658 | } | 673 | } |
674 | printk(KERN_DEBUG "(pid %d) finish dumping LEB properties\n", | ||
675 | current->pid); | ||
659 | } | 676 | } |
660 | 677 | ||
661 | void dbg_dump_lpt_info(struct ubifs_info *c) | 678 | void dbg_dump_lpt_info(struct ubifs_info *c) |
@@ -663,6 +680,7 @@ void dbg_dump_lpt_info(struct ubifs_info *c) | |||
663 | int i; | 680 | int i; |
664 | 681 | ||
665 | spin_lock(&dbg_lock); | 682 | spin_lock(&dbg_lock); |
683 | printk(KERN_DEBUG "(pid %d) dumping LPT information\n", current->pid); | ||
666 | printk(KERN_DEBUG "\tlpt_sz: %lld\n", c->lpt_sz); | 684 | printk(KERN_DEBUG "\tlpt_sz: %lld\n", c->lpt_sz); |
667 | printk(KERN_DEBUG "\tpnode_sz: %d\n", c->pnode_sz); | 685 | printk(KERN_DEBUG "\tpnode_sz: %d\n", c->pnode_sz); |
668 | printk(KERN_DEBUG "\tnnode_sz: %d\n", c->nnode_sz); | 686 | printk(KERN_DEBUG "\tnnode_sz: %d\n", c->nnode_sz); |
@@ -684,7 +702,8 @@ void dbg_dump_lpt_info(struct ubifs_info *c) | |||
684 | printk(KERN_DEBUG "\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs); | 702 | printk(KERN_DEBUG "\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs); |
685 | printk(KERN_DEBUG "\tLPT head is at %d:%d\n", | 703 | printk(KERN_DEBUG "\tLPT head is at %d:%d\n", |
686 | c->nhead_lnum, c->nhead_offs); | 704 | c->nhead_lnum, c->nhead_offs); |
687 | printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n", c->ltab_lnum, c->ltab_offs); | 705 | printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n", |
706 | c->ltab_lnum, c->ltab_offs); | ||
688 | if (c->big_lpt) | 707 | if (c->big_lpt) |
689 | printk(KERN_DEBUG "\tLPT lsave is at %d:%d\n", | 708 | printk(KERN_DEBUG "\tLPT lsave is at %d:%d\n", |
690 | c->lsave_lnum, c->lsave_offs); | 709 | c->lsave_lnum, c->lsave_offs); |
@@ -703,9 +722,9 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) | |||
703 | if (dbg_failure_mode) | 722 | if (dbg_failure_mode) |
704 | return; | 723 | return; |
705 | 724 | ||
706 | printk(KERN_DEBUG "(pid %d) Dumping LEB %d\n", current->pid, lnum); | 725 | printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n", |
707 | 726 | current->pid, lnum); | |
708 | sleb = ubifs_scan(c, lnum, 0, c->dbg_buf); | 727 | sleb = ubifs_scan(c, lnum, 0, c->dbg->buf); |
709 | if (IS_ERR(sleb)) { | 728 | if (IS_ERR(sleb)) { |
710 | ubifs_err("scan error %d", (int)PTR_ERR(sleb)); | 729 | ubifs_err("scan error %d", (int)PTR_ERR(sleb)); |
711 | return; | 730 | return; |
@@ -721,6 +740,8 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) | |||
721 | dbg_dump_node(c, snod->node); | 740 | dbg_dump_node(c, snod->node); |
722 | } | 741 | } |
723 | 742 | ||
743 | printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n", | ||
744 | current->pid, lnum); | ||
724 | ubifs_scan_destroy(sleb); | 745 | ubifs_scan_destroy(sleb); |
725 | return; | 746 | return; |
726 | } | 747 | } |
@@ -768,7 +789,7 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat) | |||
768 | { | 789 | { |
769 | int i; | 790 | int i; |
770 | 791 | ||
771 | printk(KERN_DEBUG "(pid %d) Dumping heap cat %d (%d elements)\n", | 792 | printk(KERN_DEBUG "(pid %d) start dumping heap cat %d (%d elements)\n", |
772 | current->pid, cat, heap->cnt); | 793 | current->pid, cat, heap->cnt); |
773 | for (i = 0; i < heap->cnt; i++) { | 794 | for (i = 0; i < heap->cnt; i++) { |
774 | struct ubifs_lprops *lprops = heap->arr[i]; | 795 | struct ubifs_lprops *lprops = heap->arr[i]; |
@@ -777,6 +798,7 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat) | |||
777 | "flags %d\n", i, lprops->lnum, lprops->hpos, | 798 | "flags %d\n", i, lprops->lnum, lprops->hpos, |
778 | lprops->free, lprops->dirty, lprops->flags); | 799 | lprops->free, lprops->dirty, lprops->flags); |
779 | } | 800 | } |
801 | printk(KERN_DEBUG "(pid %d) finish dumping heap\n", current->pid); | ||
780 | } | 802 | } |
781 | 803 | ||
782 | void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, | 804 | void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, |
@@ -784,7 +806,7 @@ void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, | |||
784 | { | 806 | { |
785 | int i; | 807 | int i; |
786 | 808 | ||
787 | printk(KERN_DEBUG "(pid %d) Dumping pnode:\n", current->pid); | 809 | printk(KERN_DEBUG "(pid %d) dumping pnode:\n", current->pid); |
788 | printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n", | 810 | printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n", |
789 | (size_t)pnode, (size_t)parent, (size_t)pnode->cnext); | 811 | (size_t)pnode, (size_t)parent, (size_t)pnode->cnext); |
790 | printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n", | 812 | printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n", |
@@ -803,7 +825,7 @@ void dbg_dump_tnc(struct ubifs_info *c) | |||
803 | int level; | 825 | int level; |
804 | 826 | ||
805 | printk(KERN_DEBUG "\n"); | 827 | printk(KERN_DEBUG "\n"); |
806 | printk(KERN_DEBUG "(pid %d) Dumping the TNC tree\n", current->pid); | 828 | printk(KERN_DEBUG "(pid %d) start dumping TNC tree\n", current->pid); |
807 | znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL); | 829 | znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL); |
808 | level = znode->level; | 830 | level = znode->level; |
809 | printk(KERN_DEBUG "== Level %d ==\n", level); | 831 | printk(KERN_DEBUG "== Level %d ==\n", level); |
@@ -815,8 +837,7 @@ void dbg_dump_tnc(struct ubifs_info *c) | |||
815 | dbg_dump_znode(c, znode); | 837 | dbg_dump_znode(c, znode); |
816 | znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode); | 838 | znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode); |
817 | } | 839 | } |
818 | 840 | printk(KERN_DEBUG "(pid %d) finish dumping TNC tree\n", current->pid); | |
819 | printk(KERN_DEBUG "\n"); | ||
820 | } | 841 | } |
821 | 842 | ||
822 | static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode, | 843 | static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode, |
@@ -839,6 +860,65 @@ void dbg_dump_index(struct ubifs_info *c) | |||
839 | } | 860 | } |
840 | 861 | ||
841 | /** | 862 | /** |
863 | * dbg_save_space_info - save information about flash space. | ||
864 | * @c: UBIFS file-system description object | ||
865 | * | ||
866 | * This function saves information about UBIFS free space, dirty space, etc, in | ||
867 | * order to check it later. | ||
868 | */ | ||
869 | void dbg_save_space_info(struct ubifs_info *c) | ||
870 | { | ||
871 | struct ubifs_debug_info *d = c->dbg; | ||
872 | |||
873 | ubifs_get_lp_stats(c, &d->saved_lst); | ||
874 | |||
875 | spin_lock(&c->space_lock); | ||
876 | d->saved_free = ubifs_get_free_space_nolock(c); | ||
877 | spin_unlock(&c->space_lock); | ||
878 | } | ||
879 | |||
880 | /** | ||
881 | * dbg_check_space_info - check flash space information. | ||
882 | * @c: UBIFS file-system description object | ||
883 | * | ||
884 | * This function compares current flash space information with the information | ||
885 | * which was saved when the 'dbg_save_space_info()' function was called. | ||
886 | * Returns zero if the information has not changed, and %-EINVAL it it has | ||
887 | * changed. | ||
888 | */ | ||
889 | int dbg_check_space_info(struct ubifs_info *c) | ||
890 | { | ||
891 | struct ubifs_debug_info *d = c->dbg; | ||
892 | struct ubifs_lp_stats lst; | ||
893 | long long avail, free; | ||
894 | |||
895 | spin_lock(&c->space_lock); | ||
896 | avail = ubifs_calc_available(c, c->min_idx_lebs); | ||
897 | spin_unlock(&c->space_lock); | ||
898 | free = ubifs_get_free_space(c); | ||
899 | |||
900 | if (free != d->saved_free) { | ||
901 | ubifs_err("free space changed from %lld to %lld", | ||
902 | d->saved_free, free); | ||
903 | goto out; | ||
904 | } | ||
905 | |||
906 | return 0; | ||
907 | |||
908 | out: | ||
909 | ubifs_msg("saved lprops statistics dump"); | ||
910 | dbg_dump_lstats(&d->saved_lst); | ||
911 | ubifs_get_lp_stats(c, &lst); | ||
912 | ubifs_msg("current lprops statistics dump"); | ||
913 | dbg_dump_lstats(&d->saved_lst); | ||
914 | spin_lock(&c->space_lock); | ||
915 | dbg_dump_budg(c); | ||
916 | spin_unlock(&c->space_lock); | ||
917 | dump_stack(); | ||
918 | return -EINVAL; | ||
919 | } | ||
920 | |||
921 | /** | ||
842 | * dbg_check_synced_i_size - check synchronized inode size. | 922 | * dbg_check_synced_i_size - check synchronized inode size. |
843 | * @inode: inode to check | 923 | * @inode: inode to check |
844 | * | 924 | * |
@@ -992,8 +1072,8 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, | |||
992 | zbr1->offs, DBGKEY(&key)); | 1072 | zbr1->offs, DBGKEY(&key)); |
993 | dbg_err("but it should have key %s according to tnc", | 1073 | dbg_err("but it should have key %s according to tnc", |
994 | DBGKEY(&zbr1->key)); | 1074 | DBGKEY(&zbr1->key)); |
995 | dbg_dump_node(c, dent1); | 1075 | dbg_dump_node(c, dent1); |
996 | goto out_free; | 1076 | goto out_free; |
997 | } | 1077 | } |
998 | 1078 | ||
999 | key_read(c, &dent2->key, &key); | 1079 | key_read(c, &dent2->key, &key); |
@@ -1002,8 +1082,8 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, | |||
1002 | zbr1->offs, DBGKEY(&key)); | 1082 | zbr1->offs, DBGKEY(&key)); |
1003 | dbg_err("but it should have key %s according to tnc", | 1083 | dbg_err("but it should have key %s according to tnc", |
1004 | DBGKEY(&zbr2->key)); | 1084 | DBGKEY(&zbr2->key)); |
1005 | dbg_dump_node(c, dent2); | 1085 | dbg_dump_node(c, dent2); |
1006 | goto out_free; | 1086 | goto out_free; |
1007 | } | 1087 | } |
1008 | 1088 | ||
1009 | nlen1 = le16_to_cpu(dent1->nlen); | 1089 | nlen1 = le16_to_cpu(dent1->nlen); |
@@ -1020,9 +1100,9 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, | |||
1020 | dbg_err("bad order of colliding key %s", | 1100 | dbg_err("bad order of colliding key %s", |
1021 | DBGKEY(&key)); | 1101 | DBGKEY(&key)); |
1022 | 1102 | ||
1023 | dbg_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs); | 1103 | ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs); |
1024 | dbg_dump_node(c, dent1); | 1104 | dbg_dump_node(c, dent1); |
1025 | dbg_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs); | 1105 | ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs); |
1026 | dbg_dump_node(c, dent2); | 1106 | dbg_dump_node(c, dent2); |
1027 | 1107 | ||
1028 | out_free: | 1108 | out_free: |
@@ -1327,7 +1407,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra) | |||
1327 | * @c: UBIFS file-system description object | 1407 | * @c: UBIFS file-system description object |
1328 | * @leaf_cb: called for each leaf node | 1408 | * @leaf_cb: called for each leaf node |
1329 | * @znode_cb: called for each indexing node | 1409 | * @znode_cb: called for each indexing node |
1330 | * @priv: private date which is passed to callbacks | 1410 | * @priv: private data which is passed to callbacks |
1331 | * | 1411 | * |
1332 | * This function walks the UBIFS index and calls the @leaf_cb for each leaf | 1412 | * This function walks the UBIFS index and calls the @leaf_cb for each leaf |
1333 | * node and @znode_cb for each indexing node. Returns zero in case of success | 1413 | * node and @znode_cb for each indexing node. Returns zero in case of success |
@@ -2097,13 +2177,13 @@ static int simple_rand(void) | |||
2097 | return (next >> 16) & 32767; | 2177 | return (next >> 16) & 32767; |
2098 | } | 2178 | } |
2099 | 2179 | ||
2100 | void dbg_failure_mode_registration(struct ubifs_info *c) | 2180 | static void failure_mode_init(struct ubifs_info *c) |
2101 | { | 2181 | { |
2102 | struct failure_mode_info *fmi; | 2182 | struct failure_mode_info *fmi; |
2103 | 2183 | ||
2104 | fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS); | 2184 | fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS); |
2105 | if (!fmi) { | 2185 | if (!fmi) { |
2106 | dbg_err("Failed to register failure mode - no memory"); | 2186 | ubifs_err("Failed to register failure mode - no memory"); |
2107 | return; | 2187 | return; |
2108 | } | 2188 | } |
2109 | fmi->c = c; | 2189 | fmi->c = c; |
@@ -2112,7 +2192,7 @@ void dbg_failure_mode_registration(struct ubifs_info *c) | |||
2112 | spin_unlock(&fmi_lock); | 2192 | spin_unlock(&fmi_lock); |
2113 | } | 2193 | } |
2114 | 2194 | ||
2115 | void dbg_failure_mode_deregistration(struct ubifs_info *c) | 2195 | static void failure_mode_exit(struct ubifs_info *c) |
2116 | { | 2196 | { |
2117 | struct failure_mode_info *fmi, *tmp; | 2197 | struct failure_mode_info *fmi, *tmp; |
2118 | 2198 | ||
@@ -2146,42 +2226,44 @@ static int in_failure_mode(struct ubi_volume_desc *desc) | |||
2146 | struct ubifs_info *c = dbg_find_info(desc); | 2226 | struct ubifs_info *c = dbg_find_info(desc); |
2147 | 2227 | ||
2148 | if (c && dbg_failure_mode) | 2228 | if (c && dbg_failure_mode) |
2149 | return c->failure_mode; | 2229 | return c->dbg->failure_mode; |
2150 | return 0; | 2230 | return 0; |
2151 | } | 2231 | } |
2152 | 2232 | ||
2153 | static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) | 2233 | static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) |
2154 | { | 2234 | { |
2155 | struct ubifs_info *c = dbg_find_info(desc); | 2235 | struct ubifs_info *c = dbg_find_info(desc); |
2236 | struct ubifs_debug_info *d; | ||
2156 | 2237 | ||
2157 | if (!c || !dbg_failure_mode) | 2238 | if (!c || !dbg_failure_mode) |
2158 | return 0; | 2239 | return 0; |
2159 | if (c->failure_mode) | 2240 | d = c->dbg; |
2241 | if (d->failure_mode) | ||
2160 | return 1; | 2242 | return 1; |
2161 | if (!c->fail_cnt) { | 2243 | if (!d->fail_cnt) { |
2162 | /* First call - decide delay to failure */ | 2244 | /* First call - decide delay to failure */ |
2163 | if (chance(1, 2)) { | 2245 | if (chance(1, 2)) { |
2164 | unsigned int delay = 1 << (simple_rand() >> 11); | 2246 | unsigned int delay = 1 << (simple_rand() >> 11); |
2165 | 2247 | ||
2166 | if (chance(1, 2)) { | 2248 | if (chance(1, 2)) { |
2167 | c->fail_delay = 1; | 2249 | d->fail_delay = 1; |
2168 | c->fail_timeout = jiffies + | 2250 | d->fail_timeout = jiffies + |
2169 | msecs_to_jiffies(delay); | 2251 | msecs_to_jiffies(delay); |
2170 | dbg_rcvry("failing after %ums", delay); | 2252 | dbg_rcvry("failing after %ums", delay); |
2171 | } else { | 2253 | } else { |
2172 | c->fail_delay = 2; | 2254 | d->fail_delay = 2; |
2173 | c->fail_cnt_max = delay; | 2255 | d->fail_cnt_max = delay; |
2174 | dbg_rcvry("failing after %u calls", delay); | 2256 | dbg_rcvry("failing after %u calls", delay); |
2175 | } | 2257 | } |
2176 | } | 2258 | } |
2177 | c->fail_cnt += 1; | 2259 | d->fail_cnt += 1; |
2178 | } | 2260 | } |
2179 | /* Determine if failure delay has expired */ | 2261 | /* Determine if failure delay has expired */ |
2180 | if (c->fail_delay == 1) { | 2262 | if (d->fail_delay == 1) { |
2181 | if (time_before(jiffies, c->fail_timeout)) | 2263 | if (time_before(jiffies, d->fail_timeout)) |
2182 | return 0; | 2264 | return 0; |
2183 | } else if (c->fail_delay == 2) | 2265 | } else if (d->fail_delay == 2) |
2184 | if (c->fail_cnt++ < c->fail_cnt_max) | 2266 | if (d->fail_cnt++ < d->fail_cnt_max) |
2185 | return 0; | 2267 | return 0; |
2186 | if (lnum == UBIFS_SB_LNUM) { | 2268 | if (lnum == UBIFS_SB_LNUM) { |
2187 | if (write) { | 2269 | if (write) { |
@@ -2239,7 +2321,7 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) | |||
2239 | dbg_rcvry("failing in bud LEB %d commit not running", lnum); | 2321 | dbg_rcvry("failing in bud LEB %d commit not running", lnum); |
2240 | } | 2322 | } |
2241 | ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum); | 2323 | ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum); |
2242 | c->failure_mode = 1; | 2324 | d->failure_mode = 1; |
2243 | dump_stack(); | 2325 | dump_stack(); |
2244 | return 1; | 2326 | return 1; |
2245 | } | 2327 | } |
@@ -2344,4 +2426,177 @@ int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) | |||
2344 | return 0; | 2426 | return 0; |
2345 | } | 2427 | } |
2346 | 2428 | ||
2429 | /** | ||
2430 | * ubifs_debugging_init - initialize UBIFS debugging. | ||
2431 | * @c: UBIFS file-system description object | ||
2432 | * | ||
2433 | * This function initializes debugging-related data for the file system. | ||
2434 | * Returns zero in case of success and a negative error code in case of | ||
2435 | * failure. | ||
2436 | */ | ||
2437 | int ubifs_debugging_init(struct ubifs_info *c) | ||
2438 | { | ||
2439 | c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL); | ||
2440 | if (!c->dbg) | ||
2441 | return -ENOMEM; | ||
2442 | |||
2443 | c->dbg->buf = vmalloc(c->leb_size); | ||
2444 | if (!c->dbg->buf) | ||
2445 | goto out; | ||
2446 | |||
2447 | failure_mode_init(c); | ||
2448 | return 0; | ||
2449 | |||
2450 | out: | ||
2451 | kfree(c->dbg); | ||
2452 | return -ENOMEM; | ||
2453 | } | ||
2454 | |||
2455 | /** | ||
2456 | * ubifs_debugging_exit - free debugging data. | ||
2457 | * @c: UBIFS file-system description object | ||
2458 | */ | ||
2459 | void ubifs_debugging_exit(struct ubifs_info *c) | ||
2460 | { | ||
2461 | failure_mode_exit(c); | ||
2462 | vfree(c->dbg->buf); | ||
2463 | kfree(c->dbg); | ||
2464 | } | ||
2465 | |||
2466 | /* | ||
2467 | * Root directory for UBIFS stuff in debugfs. Contains sub-directories which | ||
2468 | * contain the stuff specific to particular file-system mounts. | ||
2469 | */ | ||
2470 | static struct dentry *dfs_rootdir; | ||
2471 | |||
2472 | /** | ||
2473 | * dbg_debugfs_init - initialize debugfs file-system. | ||
2474 | * | ||
2475 | * UBIFS uses debugfs file-system to expose various debugging knobs to | ||
2476 | * user-space. This function creates "ubifs" directory in the debugfs | ||
2477 | * file-system. Returns zero in case of success and a negative error code in | ||
2478 | * case of failure. | ||
2479 | */ | ||
2480 | int dbg_debugfs_init(void) | ||
2481 | { | ||
2482 | dfs_rootdir = debugfs_create_dir("ubifs", NULL); | ||
2483 | if (IS_ERR(dfs_rootdir)) { | ||
2484 | int err = PTR_ERR(dfs_rootdir); | ||
2485 | ubifs_err("cannot create \"ubifs\" debugfs directory, " | ||
2486 | "error %d\n", err); | ||
2487 | return err; | ||
2488 | } | ||
2489 | |||
2490 | return 0; | ||
2491 | } | ||
2492 | |||
2493 | /** | ||
2494 | * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system. | ||
2495 | */ | ||
2496 | void dbg_debugfs_exit(void) | ||
2497 | { | ||
2498 | debugfs_remove(dfs_rootdir); | ||
2499 | } | ||
2500 | |||
2501 | static int open_debugfs_file(struct inode *inode, struct file *file) | ||
2502 | { | ||
2503 | file->private_data = inode->i_private; | ||
2504 | return 0; | ||
2505 | } | ||
2506 | |||
2507 | static ssize_t write_debugfs_file(struct file *file, const char __user *buf, | ||
2508 | size_t count, loff_t *ppos) | ||
2509 | { | ||
2510 | struct ubifs_info *c = file->private_data; | ||
2511 | struct ubifs_debug_info *d = c->dbg; | ||
2512 | |||
2513 | if (file->f_path.dentry == d->dfs_dump_lprops) | ||
2514 | dbg_dump_lprops(c); | ||
2515 | else if (file->f_path.dentry == d->dfs_dump_budg) { | ||
2516 | spin_lock(&c->space_lock); | ||
2517 | dbg_dump_budg(c); | ||
2518 | spin_unlock(&c->space_lock); | ||
2519 | } else if (file->f_path.dentry == d->dfs_dump_tnc) { | ||
2520 | mutex_lock(&c->tnc_mutex); | ||
2521 | dbg_dump_tnc(c); | ||
2522 | mutex_unlock(&c->tnc_mutex); | ||
2523 | } else | ||
2524 | return -EINVAL; | ||
2525 | |||
2526 | *ppos += count; | ||
2527 | return count; | ||
2528 | } | ||
2529 | |||
2530 | static const struct file_operations dfs_fops = { | ||
2531 | .open = open_debugfs_file, | ||
2532 | .write = write_debugfs_file, | ||
2533 | .owner = THIS_MODULE, | ||
2534 | }; | ||
2535 | |||
2536 | /** | ||
2537 | * dbg_debugfs_init_fs - initialize debugfs for UBIFS instance. | ||
2538 | * @c: UBIFS file-system description object | ||
2539 | * | ||
2540 | * This function creates all debugfs files for this instance of UBIFS. Returns | ||
2541 | * zero in case of success and a negative error code in case of failure. | ||
2542 | * | ||
2543 | * Note, the only reason we have not merged this function with the | ||
2544 | * 'ubifs_debugging_init()' function is because it is better to initialize | ||
2545 | * debugfs interfaces at the very end of the mount process, and remove them at | ||
2546 | * the very beginning of the mount process. | ||
2547 | */ | ||
2548 | int dbg_debugfs_init_fs(struct ubifs_info *c) | ||
2549 | { | ||
2550 | int err; | ||
2551 | const char *fname; | ||
2552 | struct dentry *dent; | ||
2553 | struct ubifs_debug_info *d = c->dbg; | ||
2554 | |||
2555 | sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); | ||
2556 | d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir); | ||
2557 | if (IS_ERR(d->dfs_dir)) { | ||
2558 | err = PTR_ERR(d->dfs_dir); | ||
2559 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2560 | d->dfs_dir_name, err); | ||
2561 | goto out; | ||
2562 | } | ||
2563 | |||
2564 | fname = "dump_lprops"; | ||
2565 | dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); | ||
2566 | if (IS_ERR(dent)) | ||
2567 | goto out_remove; | ||
2568 | d->dfs_dump_lprops = dent; | ||
2569 | |||
2570 | fname = "dump_budg"; | ||
2571 | dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); | ||
2572 | if (IS_ERR(dent)) | ||
2573 | goto out_remove; | ||
2574 | d->dfs_dump_budg = dent; | ||
2575 | |||
2576 | fname = "dump_tnc"; | ||
2577 | dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); | ||
2578 | if (IS_ERR(dent)) | ||
2579 | goto out_remove; | ||
2580 | d->dfs_dump_tnc = dent; | ||
2581 | |||
2582 | return 0; | ||
2583 | |||
2584 | out_remove: | ||
2585 | err = PTR_ERR(dent); | ||
2586 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2587 | fname, err); | ||
2588 | debugfs_remove_recursive(d->dfs_dir); | ||
2589 | out: | ||
2590 | return err; | ||
2591 | } | ||
2592 | |||
2593 | /** | ||
2594 | * dbg_debugfs_exit_fs - remove all debugfs files. | ||
2595 | * @c: UBIFS file-system description object | ||
2596 | */ | ||
2597 | void dbg_debugfs_exit_fs(struct ubifs_info *c) | ||
2598 | { | ||
2599 | debugfs_remove_recursive(c->dbg->dfs_dir); | ||
2600 | } | ||
2601 | |||
2347 | #endif /* CONFIG_UBIFS_FS_DEBUG */ | 2602 | #endif /* CONFIG_UBIFS_FS_DEBUG */ |