diff options
Diffstat (limited to 'fs/ubifs/debug.c')
-rw-r--r-- | fs/ubifs/debug.c | 265 |
1 files changed, 233 insertions, 32 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 510ffa0bbda4..792c5a16c182 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, |
@@ -629,6 +633,17 @@ void dbg_dump_budg(struct ubifs_info *c) | |||
629 | printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n", | 633 | printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n", |
630 | idx_gc->lnum, idx_gc->unmap); | 634 | idx_gc->lnum, idx_gc->unmap); |
631 | printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state); | 635 | printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state); |
636 | |||
637 | /* Print budgeting predictions */ | ||
638 | available = ubifs_calc_available(c, c->min_idx_lebs); | ||
639 | outstanding = c->budg_data_growth + c->budg_dd_growth; | ||
640 | if (available > outstanding) | ||
641 | free = ubifs_reported_space(c, available - outstanding); | ||
642 | else | ||
643 | free = 0; | ||
644 | printk(KERN_DEBUG "Budgeting predictions:\n"); | ||
645 | printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n", | ||
646 | available, outstanding, free); | ||
632 | spin_unlock(&dbg_lock); | 647 | spin_unlock(&dbg_lock); |
633 | } | 648 | } |
634 | 649 | ||
@@ -645,7 +660,8 @@ void dbg_dump_lprops(struct ubifs_info *c) | |||
645 | struct ubifs_lprops lp; | 660 | struct ubifs_lprops lp; |
646 | struct ubifs_lp_stats lst; | 661 | struct ubifs_lp_stats lst; |
647 | 662 | ||
648 | printk(KERN_DEBUG "(pid %d) Dumping LEB properties\n", current->pid); | 663 | printk(KERN_DEBUG "(pid %d) start dumping LEB properties\n", |
664 | current->pid); | ||
649 | ubifs_get_lp_stats(c, &lst); | 665 | ubifs_get_lp_stats(c, &lst); |
650 | dbg_dump_lstats(&lst); | 666 | dbg_dump_lstats(&lst); |
651 | 667 | ||
@@ -656,6 +672,8 @@ void dbg_dump_lprops(struct ubifs_info *c) | |||
656 | 672 | ||
657 | dbg_dump_lprop(c, &lp); | 673 | dbg_dump_lprop(c, &lp); |
658 | } | 674 | } |
675 | printk(KERN_DEBUG "(pid %d) finish dumping LEB properties\n", | ||
676 | current->pid); | ||
659 | } | 677 | } |
660 | 678 | ||
661 | void dbg_dump_lpt_info(struct ubifs_info *c) | 679 | void dbg_dump_lpt_info(struct ubifs_info *c) |
@@ -663,6 +681,7 @@ void dbg_dump_lpt_info(struct ubifs_info *c) | |||
663 | int i; | 681 | int i; |
664 | 682 | ||
665 | spin_lock(&dbg_lock); | 683 | spin_lock(&dbg_lock); |
684 | printk(KERN_DEBUG "(pid %d) dumping LPT information\n", current->pid); | ||
666 | printk(KERN_DEBUG "\tlpt_sz: %lld\n", c->lpt_sz); | 685 | printk(KERN_DEBUG "\tlpt_sz: %lld\n", c->lpt_sz); |
667 | printk(KERN_DEBUG "\tpnode_sz: %d\n", c->pnode_sz); | 686 | printk(KERN_DEBUG "\tpnode_sz: %d\n", c->pnode_sz); |
668 | printk(KERN_DEBUG "\tnnode_sz: %d\n", c->nnode_sz); | 687 | printk(KERN_DEBUG "\tnnode_sz: %d\n", c->nnode_sz); |
@@ -684,7 +703,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); | 703 | 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", | 704 | printk(KERN_DEBUG "\tLPT head is at %d:%d\n", |
686 | c->nhead_lnum, c->nhead_offs); | 705 | c->nhead_lnum, c->nhead_offs); |
687 | printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n", c->ltab_lnum, c->ltab_offs); | 706 | printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n", |
707 | c->ltab_lnum, c->ltab_offs); | ||
688 | if (c->big_lpt) | 708 | if (c->big_lpt) |
689 | printk(KERN_DEBUG "\tLPT lsave is at %d:%d\n", | 709 | printk(KERN_DEBUG "\tLPT lsave is at %d:%d\n", |
690 | c->lsave_lnum, c->lsave_offs); | 710 | c->lsave_lnum, c->lsave_offs); |
@@ -703,9 +723,9 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) | |||
703 | if (dbg_failure_mode) | 723 | if (dbg_failure_mode) |
704 | return; | 724 | return; |
705 | 725 | ||
706 | printk(KERN_DEBUG "(pid %d) Dumping LEB %d\n", current->pid, lnum); | 726 | printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n", |
707 | 727 | current->pid, lnum); | |
708 | sleb = ubifs_scan(c, lnum, 0, c->dbg_buf); | 728 | sleb = ubifs_scan(c, lnum, 0, c->dbg->buf); |
709 | if (IS_ERR(sleb)) { | 729 | if (IS_ERR(sleb)) { |
710 | ubifs_err("scan error %d", (int)PTR_ERR(sleb)); | 730 | ubifs_err("scan error %d", (int)PTR_ERR(sleb)); |
711 | return; | 731 | return; |
@@ -721,6 +741,8 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) | |||
721 | dbg_dump_node(c, snod->node); | 741 | dbg_dump_node(c, snod->node); |
722 | } | 742 | } |
723 | 743 | ||
744 | printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n", | ||
745 | current->pid, lnum); | ||
724 | ubifs_scan_destroy(sleb); | 746 | ubifs_scan_destroy(sleb); |
725 | return; | 747 | return; |
726 | } | 748 | } |
@@ -768,7 +790,7 @@ void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat) | |||
768 | { | 790 | { |
769 | int i; | 791 | int i; |
770 | 792 | ||
771 | printk(KERN_DEBUG "(pid %d) Dumping heap cat %d (%d elements)\n", | 793 | printk(KERN_DEBUG "(pid %d) start dumping heap cat %d (%d elements)\n", |
772 | current->pid, cat, heap->cnt); | 794 | current->pid, cat, heap->cnt); |
773 | for (i = 0; i < heap->cnt; i++) { | 795 | for (i = 0; i < heap->cnt; i++) { |
774 | struct ubifs_lprops *lprops = heap->arr[i]; | 796 | struct ubifs_lprops *lprops = heap->arr[i]; |
@@ -777,6 +799,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, | 799 | "flags %d\n", i, lprops->lnum, lprops->hpos, |
778 | lprops->free, lprops->dirty, lprops->flags); | 800 | lprops->free, lprops->dirty, lprops->flags); |
779 | } | 801 | } |
802 | printk(KERN_DEBUG "(pid %d) finish dumping heap\n", current->pid); | ||
780 | } | 803 | } |
781 | 804 | ||
782 | void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, | 805 | void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, |
@@ -784,7 +807,7 @@ void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode, | |||
784 | { | 807 | { |
785 | int i; | 808 | int i; |
786 | 809 | ||
787 | printk(KERN_DEBUG "(pid %d) Dumping pnode:\n", current->pid); | 810 | printk(KERN_DEBUG "(pid %d) dumping pnode:\n", current->pid); |
788 | printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n", | 811 | printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n", |
789 | (size_t)pnode, (size_t)parent, (size_t)pnode->cnext); | 812 | (size_t)pnode, (size_t)parent, (size_t)pnode->cnext); |
790 | printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n", | 813 | printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n", |
@@ -803,7 +826,7 @@ void dbg_dump_tnc(struct ubifs_info *c) | |||
803 | int level; | 826 | int level; |
804 | 827 | ||
805 | printk(KERN_DEBUG "\n"); | 828 | printk(KERN_DEBUG "\n"); |
806 | printk(KERN_DEBUG "(pid %d) Dumping the TNC tree\n", current->pid); | 829 | printk(KERN_DEBUG "(pid %d) start dumping TNC tree\n", current->pid); |
807 | znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL); | 830 | znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL); |
808 | level = znode->level; | 831 | level = znode->level; |
809 | printk(KERN_DEBUG "== Level %d ==\n", level); | 832 | printk(KERN_DEBUG "== Level %d ==\n", level); |
@@ -815,8 +838,7 @@ void dbg_dump_tnc(struct ubifs_info *c) | |||
815 | dbg_dump_znode(c, znode); | 838 | dbg_dump_znode(c, znode); |
816 | znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode); | 839 | znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode); |
817 | } | 840 | } |
818 | 841 | printk(KERN_DEBUG "(pid %d) finish dumping TNC tree\n", current->pid); | |
819 | printk(KERN_DEBUG "\n"); | ||
820 | } | 842 | } |
821 | 843 | ||
822 | static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode, | 844 | static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode, |
@@ -992,8 +1014,8 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, | |||
992 | zbr1->offs, DBGKEY(&key)); | 1014 | zbr1->offs, DBGKEY(&key)); |
993 | dbg_err("but it should have key %s according to tnc", | 1015 | dbg_err("but it should have key %s according to tnc", |
994 | DBGKEY(&zbr1->key)); | 1016 | DBGKEY(&zbr1->key)); |
995 | dbg_dump_node(c, dent1); | 1017 | dbg_dump_node(c, dent1); |
996 | goto out_free; | 1018 | goto out_free; |
997 | } | 1019 | } |
998 | 1020 | ||
999 | key_read(c, &dent2->key, &key); | 1021 | key_read(c, &dent2->key, &key); |
@@ -1002,8 +1024,8 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, | |||
1002 | zbr1->offs, DBGKEY(&key)); | 1024 | zbr1->offs, DBGKEY(&key)); |
1003 | dbg_err("but it should have key %s according to tnc", | 1025 | dbg_err("but it should have key %s according to tnc", |
1004 | DBGKEY(&zbr2->key)); | 1026 | DBGKEY(&zbr2->key)); |
1005 | dbg_dump_node(c, dent2); | 1027 | dbg_dump_node(c, dent2); |
1006 | goto out_free; | 1028 | goto out_free; |
1007 | } | 1029 | } |
1008 | 1030 | ||
1009 | nlen1 = le16_to_cpu(dent1->nlen); | 1031 | nlen1 = le16_to_cpu(dent1->nlen); |
@@ -1020,9 +1042,9 @@ static int dbg_check_key_order(struct ubifs_info *c, struct ubifs_zbranch *zbr1, | |||
1020 | dbg_err("bad order of colliding key %s", | 1042 | dbg_err("bad order of colliding key %s", |
1021 | DBGKEY(&key)); | 1043 | DBGKEY(&key)); |
1022 | 1044 | ||
1023 | dbg_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs); | 1045 | ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs); |
1024 | dbg_dump_node(c, dent1); | 1046 | dbg_dump_node(c, dent1); |
1025 | dbg_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs); | 1047 | ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs); |
1026 | dbg_dump_node(c, dent2); | 1048 | dbg_dump_node(c, dent2); |
1027 | 1049 | ||
1028 | out_free: | 1050 | out_free: |
@@ -2097,13 +2119,13 @@ static int simple_rand(void) | |||
2097 | return (next >> 16) & 32767; | 2119 | return (next >> 16) & 32767; |
2098 | } | 2120 | } |
2099 | 2121 | ||
2100 | void dbg_failure_mode_registration(struct ubifs_info *c) | 2122 | static void failure_mode_init(struct ubifs_info *c) |
2101 | { | 2123 | { |
2102 | struct failure_mode_info *fmi; | 2124 | struct failure_mode_info *fmi; |
2103 | 2125 | ||
2104 | fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS); | 2126 | fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS); |
2105 | if (!fmi) { | 2127 | if (!fmi) { |
2106 | dbg_err("Failed to register failure mode - no memory"); | 2128 | ubifs_err("Failed to register failure mode - no memory"); |
2107 | return; | 2129 | return; |
2108 | } | 2130 | } |
2109 | fmi->c = c; | 2131 | fmi->c = c; |
@@ -2112,7 +2134,7 @@ void dbg_failure_mode_registration(struct ubifs_info *c) | |||
2112 | spin_unlock(&fmi_lock); | 2134 | spin_unlock(&fmi_lock); |
2113 | } | 2135 | } |
2114 | 2136 | ||
2115 | void dbg_failure_mode_deregistration(struct ubifs_info *c) | 2137 | static void failure_mode_exit(struct ubifs_info *c) |
2116 | { | 2138 | { |
2117 | struct failure_mode_info *fmi, *tmp; | 2139 | struct failure_mode_info *fmi, *tmp; |
2118 | 2140 | ||
@@ -2146,42 +2168,44 @@ static int in_failure_mode(struct ubi_volume_desc *desc) | |||
2146 | struct ubifs_info *c = dbg_find_info(desc); | 2168 | struct ubifs_info *c = dbg_find_info(desc); |
2147 | 2169 | ||
2148 | if (c && dbg_failure_mode) | 2170 | if (c && dbg_failure_mode) |
2149 | return c->failure_mode; | 2171 | return c->dbg->failure_mode; |
2150 | return 0; | 2172 | return 0; |
2151 | } | 2173 | } |
2152 | 2174 | ||
2153 | static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) | 2175 | static int do_fail(struct ubi_volume_desc *desc, int lnum, int write) |
2154 | { | 2176 | { |
2155 | struct ubifs_info *c = dbg_find_info(desc); | 2177 | struct ubifs_info *c = dbg_find_info(desc); |
2178 | struct ubifs_debug_info *d; | ||
2156 | 2179 | ||
2157 | if (!c || !dbg_failure_mode) | 2180 | if (!c || !dbg_failure_mode) |
2158 | return 0; | 2181 | return 0; |
2159 | if (c->failure_mode) | 2182 | d = c->dbg; |
2183 | if (d->failure_mode) | ||
2160 | return 1; | 2184 | return 1; |
2161 | if (!c->fail_cnt) { | 2185 | if (!d->fail_cnt) { |
2162 | /* First call - decide delay to failure */ | 2186 | /* First call - decide delay to failure */ |
2163 | if (chance(1, 2)) { | 2187 | if (chance(1, 2)) { |
2164 | unsigned int delay = 1 << (simple_rand() >> 11); | 2188 | unsigned int delay = 1 << (simple_rand() >> 11); |
2165 | 2189 | ||
2166 | if (chance(1, 2)) { | 2190 | if (chance(1, 2)) { |
2167 | c->fail_delay = 1; | 2191 | d->fail_delay = 1; |
2168 | c->fail_timeout = jiffies + | 2192 | d->fail_timeout = jiffies + |
2169 | msecs_to_jiffies(delay); | 2193 | msecs_to_jiffies(delay); |
2170 | dbg_rcvry("failing after %ums", delay); | 2194 | dbg_rcvry("failing after %ums", delay); |
2171 | } else { | 2195 | } else { |
2172 | c->fail_delay = 2; | 2196 | d->fail_delay = 2; |
2173 | c->fail_cnt_max = delay; | 2197 | d->fail_cnt_max = delay; |
2174 | dbg_rcvry("failing after %u calls", delay); | 2198 | dbg_rcvry("failing after %u calls", delay); |
2175 | } | 2199 | } |
2176 | } | 2200 | } |
2177 | c->fail_cnt += 1; | 2201 | d->fail_cnt += 1; |
2178 | } | 2202 | } |
2179 | /* Determine if failure delay has expired */ | 2203 | /* Determine if failure delay has expired */ |
2180 | if (c->fail_delay == 1) { | 2204 | if (d->fail_delay == 1) { |
2181 | if (time_before(jiffies, c->fail_timeout)) | 2205 | if (time_before(jiffies, d->fail_timeout)) |
2182 | return 0; | 2206 | return 0; |
2183 | } else if (c->fail_delay == 2) | 2207 | } else if (d->fail_delay == 2) |
2184 | if (c->fail_cnt++ < c->fail_cnt_max) | 2208 | if (d->fail_cnt++ < d->fail_cnt_max) |
2185 | return 0; | 2209 | return 0; |
2186 | if (lnum == UBIFS_SB_LNUM) { | 2210 | if (lnum == UBIFS_SB_LNUM) { |
2187 | if (write) { | 2211 | if (write) { |
@@ -2239,7 +2263,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); | 2263 | dbg_rcvry("failing in bud LEB %d commit not running", lnum); |
2240 | } | 2264 | } |
2241 | ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum); | 2265 | ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum); |
2242 | c->failure_mode = 1; | 2266 | d->failure_mode = 1; |
2243 | dump_stack(); | 2267 | dump_stack(); |
2244 | return 1; | 2268 | return 1; |
2245 | } | 2269 | } |
@@ -2344,4 +2368,181 @@ int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) | |||
2344 | return 0; | 2368 | return 0; |
2345 | } | 2369 | } |
2346 | 2370 | ||
2371 | /** | ||
2372 | * ubifs_debugging_init - initialize UBIFS debugging. | ||
2373 | * @c: UBIFS file-system description object | ||
2374 | * | ||
2375 | * This function initializes debugging-related data for the file system. | ||
2376 | * Returns zero in case of success and a negative error code in case of | ||
2377 | * failure. | ||
2378 | */ | ||
2379 | int ubifs_debugging_init(struct ubifs_info *c) | ||
2380 | { | ||
2381 | c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL); | ||
2382 | if (!c->dbg) | ||
2383 | return -ENOMEM; | ||
2384 | |||
2385 | c->dbg->buf = vmalloc(c->leb_size); | ||
2386 | if (!c->dbg->buf) | ||
2387 | goto out; | ||
2388 | |||
2389 | failure_mode_init(c); | ||
2390 | return 0; | ||
2391 | |||
2392 | out: | ||
2393 | kfree(c->dbg); | ||
2394 | return -ENOMEM; | ||
2395 | } | ||
2396 | |||
2397 | /** | ||
2398 | * ubifs_debugging_exit - free debugging data. | ||
2399 | * @c: UBIFS file-system description object | ||
2400 | */ | ||
2401 | void ubifs_debugging_exit(struct ubifs_info *c) | ||
2402 | { | ||
2403 | failure_mode_exit(c); | ||
2404 | vfree(c->dbg->buf); | ||
2405 | kfree(c->dbg); | ||
2406 | } | ||
2407 | |||
2408 | /* | ||
2409 | * Root directory for UBIFS stuff in debugfs. Contains sub-directories which | ||
2410 | * contain the stuff specific to particular file-system mounts. | ||
2411 | */ | ||
2412 | static struct dentry *debugfs_rootdir; | ||
2413 | |||
2414 | /** | ||
2415 | * dbg_debugfs_init - initialize debugfs file-system. | ||
2416 | * | ||
2417 | * UBIFS uses debugfs file-system to expose various debugging knobs to | ||
2418 | * user-space. This function creates "ubifs" directory in the debugfs | ||
2419 | * file-system. Returns zero in case of success and a negative error code in | ||
2420 | * case of failure. | ||
2421 | */ | ||
2422 | int dbg_debugfs_init(void) | ||
2423 | { | ||
2424 | debugfs_rootdir = debugfs_create_dir("ubifs", NULL); | ||
2425 | if (IS_ERR(debugfs_rootdir)) { | ||
2426 | int err = PTR_ERR(debugfs_rootdir); | ||
2427 | ubifs_err("cannot create \"ubifs\" debugfs directory, " | ||
2428 | "error %d\n", err); | ||
2429 | return err; | ||
2430 | } | ||
2431 | |||
2432 | return 0; | ||
2433 | } | ||
2434 | |||
2435 | /** | ||
2436 | * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system. | ||
2437 | */ | ||
2438 | void dbg_debugfs_exit(void) | ||
2439 | { | ||
2440 | debugfs_remove(debugfs_rootdir); | ||
2441 | } | ||
2442 | |||
2443 | static int open_debugfs_file(struct inode *inode, struct file *file) | ||
2444 | { | ||
2445 | file->private_data = inode->i_private; | ||
2446 | return 0; | ||
2447 | } | ||
2448 | |||
2449 | static ssize_t write_debugfs_file(struct file *file, const char __user *buf, | ||
2450 | size_t count, loff_t *ppos) | ||
2451 | { | ||
2452 | struct ubifs_info *c = file->private_data; | ||
2453 | struct ubifs_debug_info *d = c->dbg; | ||
2454 | |||
2455 | if (file->f_path.dentry == d->dump_lprops) | ||
2456 | dbg_dump_lprops(c); | ||
2457 | else if (file->f_path.dentry == d->dump_budg) { | ||
2458 | spin_lock(&c->space_lock); | ||
2459 | dbg_dump_budg(c); | ||
2460 | spin_unlock(&c->space_lock); | ||
2461 | } else if (file->f_path.dentry == d->dump_tnc) { | ||
2462 | mutex_lock(&c->tnc_mutex); | ||
2463 | dbg_dump_tnc(c); | ||
2464 | mutex_unlock(&c->tnc_mutex); | ||
2465 | } else | ||
2466 | return -EINVAL; | ||
2467 | |||
2468 | *ppos += count; | ||
2469 | return count; | ||
2470 | } | ||
2471 | |||
2472 | static const struct file_operations debugfs_fops = { | ||
2473 | .open = open_debugfs_file, | ||
2474 | .write = write_debugfs_file, | ||
2475 | .owner = THIS_MODULE, | ||
2476 | }; | ||
2477 | |||
2478 | /** | ||
2479 | * dbg_debugfs_init_fs - initialize debugfs for UBIFS instance. | ||
2480 | * @c: UBIFS file-system description object | ||
2481 | * | ||
2482 | * This function creates all debugfs files for this instance of UBIFS. Returns | ||
2483 | * zero in case of success and a negative error code in case of failure. | ||
2484 | * | ||
2485 | * Note, the only reason we have not merged this function with the | ||
2486 | * 'ubifs_debugging_init()' function is because it is better to initialize | ||
2487 | * debugfs interfaces at the very end of the mount process, and remove them at | ||
2488 | * the very beginning of the mount process. | ||
2489 | */ | ||
2490 | int dbg_debugfs_init_fs(struct ubifs_info *c) | ||
2491 | { | ||
2492 | int err; | ||
2493 | const char *fname; | ||
2494 | struct dentry *dent; | ||
2495 | struct ubifs_debug_info *d = c->dbg; | ||
2496 | |||
2497 | sprintf(d->debugfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); | ||
2498 | d->debugfs_dir = debugfs_create_dir(d->debugfs_dir_name, | ||
2499 | debugfs_rootdir); | ||
2500 | if (IS_ERR(d->debugfs_dir)) { | ||
2501 | err = PTR_ERR(d->debugfs_dir); | ||
2502 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2503 | d->debugfs_dir_name, err); | ||
2504 | goto out; | ||
2505 | } | ||
2506 | |||
2507 | fname = "dump_lprops"; | ||
2508 | dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, | ||
2509 | &debugfs_fops); | ||
2510 | if (IS_ERR(dent)) | ||
2511 | goto out_remove; | ||
2512 | d->dump_lprops = dent; | ||
2513 | |||
2514 | fname = "dump_budg"; | ||
2515 | dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, | ||
2516 | &debugfs_fops); | ||
2517 | if (IS_ERR(dent)) | ||
2518 | goto out_remove; | ||
2519 | d->dump_budg = dent; | ||
2520 | |||
2521 | fname = "dump_tnc"; | ||
2522 | dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, | ||
2523 | &debugfs_fops); | ||
2524 | if (IS_ERR(dent)) | ||
2525 | goto out_remove; | ||
2526 | d->dump_tnc = dent; | ||
2527 | |||
2528 | return 0; | ||
2529 | |||
2530 | out_remove: | ||
2531 | err = PTR_ERR(dent); | ||
2532 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2533 | fname, err); | ||
2534 | debugfs_remove_recursive(d->debugfs_dir); | ||
2535 | out: | ||
2536 | return err; | ||
2537 | } | ||
2538 | |||
2539 | /** | ||
2540 | * dbg_debugfs_exit_fs - remove all debugfs files. | ||
2541 | * @c: UBIFS file-system description object | ||
2542 | */ | ||
2543 | void dbg_debugfs_exit_fs(struct ubifs_info *c) | ||
2544 | { | ||
2545 | debugfs_remove_recursive(c->dbg->debugfs_dir); | ||
2546 | } | ||
2547 | |||
2347 | #endif /* CONFIG_UBIFS_FS_DEBUG */ | 2548 | #endif /* CONFIG_UBIFS_FS_DEBUG */ |