diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/ubifs/debug.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/ubifs/debug.c')
-rw-r--r-- | fs/ubifs/debug.c | 413 |
1 files changed, 325 insertions, 88 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index c2a68baa782f..0bb2bcef0de9 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> |
35 | #include <linux/debugfs.h> | 35 | #include <linux/debugfs.h> |
36 | #include <linux/math64.h> | 36 | #include <linux/math64.h> |
37 | #include <linux/slab.h> | ||
38 | 37 | ||
39 | #ifdef CONFIG_UBIFS_FS_DEBUG | 38 | #ifdef CONFIG_UBIFS_FS_DEBUG |
40 | 39 | ||
@@ -43,15 +42,12 @@ DEFINE_SPINLOCK(dbg_lock); | |||
43 | static char dbg_key_buf0[128]; | 42 | static char dbg_key_buf0[128]; |
44 | static char dbg_key_buf1[128]; | 43 | static char dbg_key_buf1[128]; |
45 | 44 | ||
46 | unsigned int ubifs_msg_flags = UBIFS_MSG_FLAGS_DEFAULT; | 45 | unsigned int ubifs_chk_flags; |
47 | unsigned int ubifs_chk_flags = UBIFS_CHK_FLAGS_DEFAULT; | ||
48 | unsigned int ubifs_tst_flags; | 46 | unsigned int ubifs_tst_flags; |
49 | 47 | ||
50 | module_param_named(debug_msgs, ubifs_msg_flags, uint, S_IRUGO | S_IWUSR); | ||
51 | module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR); | 48 | module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR); |
52 | module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR); | 49 | module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR); |
53 | 50 | ||
54 | MODULE_PARM_DESC(debug_msgs, "Debug message type flags"); | ||
55 | MODULE_PARM_DESC(debug_chks, "Debug check flags"); | 51 | MODULE_PARM_DESC(debug_chks, "Debug check flags"); |
56 | MODULE_PARM_DESC(debug_tsts, "Debug special test flags"); | 52 | MODULE_PARM_DESC(debug_tsts, "Debug special test flags"); |
57 | 53 | ||
@@ -317,6 +313,8 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node) | |||
317 | printk(KERN_DEBUG "\tflags %#x\n", sup_flags); | 313 | printk(KERN_DEBUG "\tflags %#x\n", sup_flags); |
318 | printk(KERN_DEBUG "\t big_lpt %u\n", | 314 | printk(KERN_DEBUG "\t big_lpt %u\n", |
319 | !!(sup_flags & UBIFS_FLG_BIGLPT)); | 315 | !!(sup_flags & UBIFS_FLG_BIGLPT)); |
316 | printk(KERN_DEBUG "\t space_fixup %u\n", | ||
317 | !!(sup_flags & UBIFS_FLG_SPACE_FIXUP)); | ||
320 | printk(KERN_DEBUG "\tmin_io_size %u\n", | 318 | printk(KERN_DEBUG "\tmin_io_size %u\n", |
321 | le32_to_cpu(sup->min_io_size)); | 319 | le32_to_cpu(sup->min_io_size)); |
322 | printk(KERN_DEBUG "\tleb_size %u\n", | 320 | printk(KERN_DEBUG "\tleb_size %u\n", |
@@ -602,7 +600,7 @@ void dbg_dump_lstats(const struct ubifs_lp_stats *lst) | |||
602 | spin_unlock(&dbg_lock); | 600 | spin_unlock(&dbg_lock); |
603 | } | 601 | } |
604 | 602 | ||
605 | void dbg_dump_budg(struct ubifs_info *c) | 603 | void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi) |
606 | { | 604 | { |
607 | int i; | 605 | int i; |
608 | struct rb_node *rb; | 606 | struct rb_node *rb; |
@@ -610,26 +608,42 @@ void dbg_dump_budg(struct ubifs_info *c) | |||
610 | struct ubifs_gced_idx_leb *idx_gc; | 608 | struct ubifs_gced_idx_leb *idx_gc; |
611 | long long available, outstanding, free; | 609 | long long available, outstanding, free; |
612 | 610 | ||
613 | ubifs_assert(spin_is_locked(&c->space_lock)); | 611 | spin_lock(&c->space_lock); |
614 | spin_lock(&dbg_lock); | 612 | spin_lock(&dbg_lock); |
615 | printk(KERN_DEBUG "(pid %d) Budgeting info: budg_data_growth %lld, " | 613 | printk(KERN_DEBUG "(pid %d) Budgeting info: data budget sum %lld, " |
616 | "budg_dd_growth %lld, budg_idx_growth %lld\n", current->pid, | 614 | "total budget sum %lld\n", current->pid, |
617 | c->budg_data_growth, c->budg_dd_growth, c->budg_idx_growth); | 615 | bi->data_growth + bi->dd_growth, |
618 | printk(KERN_DEBUG "\tdata budget sum %lld, total budget sum %lld, " | 616 | bi->data_growth + bi->dd_growth + bi->idx_growth); |
619 | "freeable_cnt %d\n", c->budg_data_growth + c->budg_dd_growth, | 617 | printk(KERN_DEBUG "\tbudg_data_growth %lld, budg_dd_growth %lld, " |
620 | c->budg_data_growth + c->budg_dd_growth + c->budg_idx_growth, | 618 | "budg_idx_growth %lld\n", bi->data_growth, bi->dd_growth, |
621 | c->freeable_cnt); | 619 | bi->idx_growth); |
622 | printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %lld, " | 620 | printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %llu, " |
623 | "calc_idx_sz %lld, idx_gc_cnt %d\n", c->min_idx_lebs, | 621 | "uncommitted_idx %lld\n", bi->min_idx_lebs, bi->old_idx_sz, |
624 | c->old_idx_sz, c->calc_idx_sz, c->idx_gc_cnt); | 622 | bi->uncommitted_idx); |
623 | printk(KERN_DEBUG "\tpage_budget %d, inode_budget %d, dent_budget %d\n", | ||
624 | bi->page_budget, bi->inode_budget, bi->dent_budget); | ||
625 | printk(KERN_DEBUG "\tnospace %u, nospace_rp %u\n", | ||
626 | bi->nospace, bi->nospace_rp); | ||
627 | printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n", | ||
628 | c->dark_wm, c->dead_wm, c->max_idx_node_sz); | ||
629 | |||
630 | if (bi != &c->bi) | ||
631 | /* | ||
632 | * If we are dumping saved budgeting data, do not print | ||
633 | * additional information which is about the current state, not | ||
634 | * the old one which corresponded to the saved budgeting data. | ||
635 | */ | ||
636 | goto out_unlock; | ||
637 | |||
638 | printk(KERN_DEBUG "\tfreeable_cnt %d, calc_idx_sz %lld, idx_gc_cnt %d\n", | ||
639 | c->freeable_cnt, c->calc_idx_sz, c->idx_gc_cnt); | ||
625 | printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, " | 640 | printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, " |
626 | "clean_zn_cnt %ld\n", atomic_long_read(&c->dirty_pg_cnt), | 641 | "clean_zn_cnt %ld\n", atomic_long_read(&c->dirty_pg_cnt), |
627 | atomic_long_read(&c->dirty_zn_cnt), | 642 | atomic_long_read(&c->dirty_zn_cnt), |
628 | atomic_long_read(&c->clean_zn_cnt)); | 643 | atomic_long_read(&c->clean_zn_cnt)); |
629 | printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n", | ||
630 | c->dark_wm, c->dead_wm, c->max_idx_node_sz); | ||
631 | printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", | 644 | printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", |
632 | c->gc_lnum, c->ihead_lnum); | 645 | c->gc_lnum, c->ihead_lnum); |
646 | |||
633 | /* If we are in R/O mode, journal heads do not exist */ | 647 | /* If we are in R/O mode, journal heads do not exist */ |
634 | if (c->jheads) | 648 | if (c->jheads) |
635 | for (i = 0; i < c->jhead_cnt; i++) | 649 | for (i = 0; i < c->jhead_cnt; i++) |
@@ -648,13 +662,15 @@ void dbg_dump_budg(struct ubifs_info *c) | |||
648 | printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state); | 662 | printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state); |
649 | 663 | ||
650 | /* Print budgeting predictions */ | 664 | /* Print budgeting predictions */ |
651 | available = ubifs_calc_available(c, c->min_idx_lebs); | 665 | available = ubifs_calc_available(c, c->bi.min_idx_lebs); |
652 | outstanding = c->budg_data_growth + c->budg_dd_growth; | 666 | outstanding = c->bi.data_growth + c->bi.dd_growth; |
653 | free = ubifs_get_free_space_nolock(c); | 667 | free = ubifs_get_free_space_nolock(c); |
654 | printk(KERN_DEBUG "Budgeting predictions:\n"); | 668 | printk(KERN_DEBUG "Budgeting predictions:\n"); |
655 | printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n", | 669 | printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n", |
656 | available, outstanding, free); | 670 | available, outstanding, free); |
671 | out_unlock: | ||
657 | spin_unlock(&dbg_lock); | 672 | spin_unlock(&dbg_lock); |
673 | spin_unlock(&c->space_lock); | ||
658 | } | 674 | } |
659 | 675 | ||
660 | void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp) | 676 | void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp) |
@@ -729,7 +745,13 @@ void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp) | |||
729 | if (bud->lnum == lp->lnum) { | 745 | if (bud->lnum == lp->lnum) { |
730 | int head = 0; | 746 | int head = 0; |
731 | for (i = 0; i < c->jhead_cnt; i++) { | 747 | for (i = 0; i < c->jhead_cnt; i++) { |
732 | if (lp->lnum == c->jheads[i].wbuf.lnum) { | 748 | /* |
749 | * Note, if we are in R/O mode or in the middle | ||
750 | * of mounting/re-mounting, the write-buffers do | ||
751 | * not exist. | ||
752 | */ | ||
753 | if (c->jheads && | ||
754 | lp->lnum == c->jheads[i].wbuf.lnum) { | ||
733 | printk(KERN_CONT ", jhead %s", | 755 | printk(KERN_CONT ", jhead %s", |
734 | dbg_jhead(i)); | 756 | dbg_jhead(i)); |
735 | head = 1; | 757 | head = 1; |
@@ -810,16 +832,24 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) | |||
810 | { | 832 | { |
811 | struct ubifs_scan_leb *sleb; | 833 | struct ubifs_scan_leb *sleb; |
812 | struct ubifs_scan_node *snod; | 834 | struct ubifs_scan_node *snod; |
835 | void *buf; | ||
813 | 836 | ||
814 | if (dbg_failure_mode) | 837 | if (dbg_failure_mode) |
815 | return; | 838 | return; |
816 | 839 | ||
817 | printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n", | 840 | printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n", |
818 | current->pid, lnum); | 841 | current->pid, lnum); |
819 | sleb = ubifs_scan(c, lnum, 0, c->dbg->buf, 0); | 842 | |
843 | buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); | ||
844 | if (!buf) { | ||
845 | ubifs_err("cannot allocate memory for dumping LEB %d", lnum); | ||
846 | return; | ||
847 | } | ||
848 | |||
849 | sleb = ubifs_scan(c, lnum, 0, buf, 0); | ||
820 | if (IS_ERR(sleb)) { | 850 | if (IS_ERR(sleb)) { |
821 | ubifs_err("scan error %d", (int)PTR_ERR(sleb)); | 851 | ubifs_err("scan error %d", (int)PTR_ERR(sleb)); |
822 | return; | 852 | goto out; |
823 | } | 853 | } |
824 | 854 | ||
825 | printk(KERN_DEBUG "LEB %d has %d nodes ending at %d\n", lnum, | 855 | printk(KERN_DEBUG "LEB %d has %d nodes ending at %d\n", lnum, |
@@ -835,6 +865,9 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) | |||
835 | printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n", | 865 | printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n", |
836 | current->pid, lnum); | 866 | current->pid, lnum); |
837 | ubifs_scan_destroy(sleb); | 867 | ubifs_scan_destroy(sleb); |
868 | |||
869 | out: | ||
870 | vfree(buf); | ||
838 | return; | 871 | return; |
839 | } | 872 | } |
840 | 873 | ||
@@ -961,11 +994,41 @@ void dbg_dump_index(struct ubifs_info *c) | |||
961 | void dbg_save_space_info(struct ubifs_info *c) | 994 | void dbg_save_space_info(struct ubifs_info *c) |
962 | { | 995 | { |
963 | struct ubifs_debug_info *d = c->dbg; | 996 | struct ubifs_debug_info *d = c->dbg; |
964 | 997 | int freeable_cnt; | |
965 | ubifs_get_lp_stats(c, &d->saved_lst); | ||
966 | 998 | ||
967 | spin_lock(&c->space_lock); | 999 | spin_lock(&c->space_lock); |
1000 | memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats)); | ||
1001 | memcpy(&d->saved_bi, &c->bi, sizeof(struct ubifs_budg_info)); | ||
1002 | d->saved_idx_gc_cnt = c->idx_gc_cnt; | ||
1003 | |||
1004 | /* | ||
1005 | * We use a dirty hack here and zero out @c->freeable_cnt, because it | ||
1006 | * affects the free space calculations, and UBIFS might not know about | ||
1007 | * all freeable eraseblocks. Indeed, we know about freeable eraseblocks | ||
1008 | * only when we read their lprops, and we do this only lazily, upon the | ||
1009 | * need. So at any given point of time @c->freeable_cnt might be not | ||
1010 | * exactly accurate. | ||
1011 | * | ||
1012 | * Just one example about the issue we hit when we did not zero | ||
1013 | * @c->freeable_cnt. | ||
1014 | * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the | ||
1015 | * amount of free space in @d->saved_free | ||
1016 | * 2. We re-mount R/W, which makes UBIFS to read the "lsave" | ||
1017 | * information from flash, where we cache LEBs from various | ||
1018 | * categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()' | ||
1019 | * -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()' | ||
1020 | * -> 'ubifs_get_pnode()' -> 'update_cats()' | ||
1021 | * -> 'ubifs_add_to_cat()'). | ||
1022 | * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt | ||
1023 | * becomes %1. | ||
1024 | * 4. We calculate the amount of free space when the re-mount is | ||
1025 | * finished in 'dbg_check_space_info()' and it does not match | ||
1026 | * @d->saved_free. | ||
1027 | */ | ||
1028 | freeable_cnt = c->freeable_cnt; | ||
1029 | c->freeable_cnt = 0; | ||
968 | d->saved_free = ubifs_get_free_space_nolock(c); | 1030 | d->saved_free = ubifs_get_free_space_nolock(c); |
1031 | c->freeable_cnt = freeable_cnt; | ||
969 | spin_unlock(&c->space_lock); | 1032 | spin_unlock(&c->space_lock); |
970 | } | 1033 | } |
971 | 1034 | ||
@@ -982,12 +1045,15 @@ int dbg_check_space_info(struct ubifs_info *c) | |||
982 | { | 1045 | { |
983 | struct ubifs_debug_info *d = c->dbg; | 1046 | struct ubifs_debug_info *d = c->dbg; |
984 | struct ubifs_lp_stats lst; | 1047 | struct ubifs_lp_stats lst; |
985 | long long avail, free; | 1048 | long long free; |
1049 | int freeable_cnt; | ||
986 | 1050 | ||
987 | spin_lock(&c->space_lock); | 1051 | spin_lock(&c->space_lock); |
988 | avail = ubifs_calc_available(c, c->min_idx_lebs); | 1052 | freeable_cnt = c->freeable_cnt; |
1053 | c->freeable_cnt = 0; | ||
1054 | free = ubifs_get_free_space_nolock(c); | ||
1055 | c->freeable_cnt = freeable_cnt; | ||
989 | spin_unlock(&c->space_lock); | 1056 | spin_unlock(&c->space_lock); |
990 | free = ubifs_get_free_space(c); | ||
991 | 1057 | ||
992 | if (free != d->saved_free) { | 1058 | if (free != d->saved_free) { |
993 | ubifs_err("free space changed from %lld to %lld", | 1059 | ubifs_err("free space changed from %lld to %lld", |
@@ -1000,14 +1066,14 @@ int dbg_check_space_info(struct ubifs_info *c) | |||
1000 | out: | 1066 | out: |
1001 | ubifs_msg("saved lprops statistics dump"); | 1067 | ubifs_msg("saved lprops statistics dump"); |
1002 | dbg_dump_lstats(&d->saved_lst); | 1068 | dbg_dump_lstats(&d->saved_lst); |
1003 | ubifs_get_lp_stats(c, &lst); | 1069 | ubifs_msg("saved budgeting info dump"); |
1004 | 1070 | dbg_dump_budg(c, &d->saved_bi); | |
1071 | ubifs_msg("saved idx_gc_cnt %d", d->saved_idx_gc_cnt); | ||
1005 | ubifs_msg("current lprops statistics dump"); | 1072 | ubifs_msg("current lprops statistics dump"); |
1073 | ubifs_get_lp_stats(c, &lst); | ||
1006 | dbg_dump_lstats(&lst); | 1074 | dbg_dump_lstats(&lst); |
1007 | 1075 | ubifs_msg("current budgeting info dump"); | |
1008 | spin_lock(&c->space_lock); | 1076 | dbg_dump_budg(c, &c->bi); |
1009 | dbg_dump_budg(c); | ||
1010 | spin_unlock(&c->space_lock); | ||
1011 | dump_stack(); | 1077 | dump_stack(); |
1012 | return -EINVAL; | 1078 | return -EINVAL; |
1013 | } | 1079 | } |
@@ -1751,6 +1817,8 @@ static struct fsck_inode *add_inode(struct ubifs_info *c, | |||
1751 | struct rb_node **p, *parent = NULL; | 1817 | struct rb_node **p, *parent = NULL; |
1752 | struct fsck_inode *fscki; | 1818 | struct fsck_inode *fscki; |
1753 | ino_t inum = key_inum_flash(c, &ino->key); | 1819 | ino_t inum = key_inum_flash(c, &ino->key); |
1820 | struct inode *inode; | ||
1821 | struct ubifs_inode *ui; | ||
1754 | 1822 | ||
1755 | p = &fsckd->inodes.rb_node; | 1823 | p = &fsckd->inodes.rb_node; |
1756 | while (*p) { | 1824 | while (*p) { |
@@ -1774,19 +1842,46 @@ static struct fsck_inode *add_inode(struct ubifs_info *c, | |||
1774 | if (!fscki) | 1842 | if (!fscki) |
1775 | return ERR_PTR(-ENOMEM); | 1843 | return ERR_PTR(-ENOMEM); |
1776 | 1844 | ||
1845 | inode = ilookup(c->vfs_sb, inum); | ||
1846 | |||
1777 | fscki->inum = inum; | 1847 | fscki->inum = inum; |
1778 | fscki->nlink = le32_to_cpu(ino->nlink); | 1848 | /* |
1779 | fscki->size = le64_to_cpu(ino->size); | 1849 | * If the inode is present in the VFS inode cache, use it instead of |
1780 | fscki->xattr_cnt = le32_to_cpu(ino->xattr_cnt); | 1850 | * the on-flash inode which might be out-of-date. E.g., the size might |
1781 | fscki->xattr_sz = le32_to_cpu(ino->xattr_size); | 1851 | * be out-of-date. If we do not do this, the following may happen, for |
1782 | fscki->xattr_nms = le32_to_cpu(ino->xattr_names); | 1852 | * example: |
1783 | fscki->mode = le32_to_cpu(ino->mode); | 1853 | * 1. A power cut happens |
1854 | * 2. We mount the file-system R/O, the replay process fixes up the | ||
1855 | * inode size in the VFS cache, but on on-flash. | ||
1856 | * 3. 'check_leaf()' fails because it hits a data node beyond inode | ||
1857 | * size. | ||
1858 | */ | ||
1859 | if (!inode) { | ||
1860 | fscki->nlink = le32_to_cpu(ino->nlink); | ||
1861 | fscki->size = le64_to_cpu(ino->size); | ||
1862 | fscki->xattr_cnt = le32_to_cpu(ino->xattr_cnt); | ||
1863 | fscki->xattr_sz = le32_to_cpu(ino->xattr_size); | ||
1864 | fscki->xattr_nms = le32_to_cpu(ino->xattr_names); | ||
1865 | fscki->mode = le32_to_cpu(ino->mode); | ||
1866 | } else { | ||
1867 | ui = ubifs_inode(inode); | ||
1868 | fscki->nlink = inode->i_nlink; | ||
1869 | fscki->size = inode->i_size; | ||
1870 | fscki->xattr_cnt = ui->xattr_cnt; | ||
1871 | fscki->xattr_sz = ui->xattr_size; | ||
1872 | fscki->xattr_nms = ui->xattr_names; | ||
1873 | fscki->mode = inode->i_mode; | ||
1874 | iput(inode); | ||
1875 | } | ||
1876 | |||
1784 | if (S_ISDIR(fscki->mode)) { | 1877 | if (S_ISDIR(fscki->mode)) { |
1785 | fscki->calc_sz = UBIFS_INO_NODE_SZ; | 1878 | fscki->calc_sz = UBIFS_INO_NODE_SZ; |
1786 | fscki->calc_cnt = 2; | 1879 | fscki->calc_cnt = 2; |
1787 | } | 1880 | } |
1881 | |||
1788 | rb_link_node(&fscki->rb, parent, p); | 1882 | rb_link_node(&fscki->rb, parent, p); |
1789 | rb_insert_color(&fscki->rb, &fsckd->inodes); | 1883 | rb_insert_color(&fscki->rb, &fsckd->inodes); |
1884 | |||
1790 | return fscki; | 1885 | return fscki; |
1791 | } | 1886 | } |
1792 | 1887 | ||
@@ -2239,14 +2334,169 @@ out_free: | |||
2239 | return err; | 2334 | return err; |
2240 | } | 2335 | } |
2241 | 2336 | ||
2242 | static int invocation_cnt; | 2337 | /** |
2338 | * dbg_check_data_nodes_order - check that list of data nodes is sorted. | ||
2339 | * @c: UBIFS file-system description object | ||
2340 | * @head: the list of nodes ('struct ubifs_scan_node' objects) | ||
2341 | * | ||
2342 | * This function returns zero if the list of data nodes is sorted correctly, | ||
2343 | * and %-EINVAL if not. | ||
2344 | */ | ||
2345 | int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head) | ||
2346 | { | ||
2347 | struct list_head *cur; | ||
2348 | struct ubifs_scan_node *sa, *sb; | ||
2349 | |||
2350 | if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) | ||
2351 | return 0; | ||
2352 | |||
2353 | for (cur = head->next; cur->next != head; cur = cur->next) { | ||
2354 | ino_t inuma, inumb; | ||
2355 | uint32_t blka, blkb; | ||
2356 | |||
2357 | cond_resched(); | ||
2358 | sa = container_of(cur, struct ubifs_scan_node, list); | ||
2359 | sb = container_of(cur->next, struct ubifs_scan_node, list); | ||
2360 | |||
2361 | if (sa->type != UBIFS_DATA_NODE) { | ||
2362 | ubifs_err("bad node type %d", sa->type); | ||
2363 | dbg_dump_node(c, sa->node); | ||
2364 | return -EINVAL; | ||
2365 | } | ||
2366 | if (sb->type != UBIFS_DATA_NODE) { | ||
2367 | ubifs_err("bad node type %d", sb->type); | ||
2368 | dbg_dump_node(c, sb->node); | ||
2369 | return -EINVAL; | ||
2370 | } | ||
2371 | |||
2372 | inuma = key_inum(c, &sa->key); | ||
2373 | inumb = key_inum(c, &sb->key); | ||
2374 | |||
2375 | if (inuma < inumb) | ||
2376 | continue; | ||
2377 | if (inuma > inumb) { | ||
2378 | ubifs_err("larger inum %lu goes before inum %lu", | ||
2379 | (unsigned long)inuma, (unsigned long)inumb); | ||
2380 | goto error_dump; | ||
2381 | } | ||
2382 | |||
2383 | blka = key_block(c, &sa->key); | ||
2384 | blkb = key_block(c, &sb->key); | ||
2385 | |||
2386 | if (blka > blkb) { | ||
2387 | ubifs_err("larger block %u goes before %u", blka, blkb); | ||
2388 | goto error_dump; | ||
2389 | } | ||
2390 | if (blka == blkb) { | ||
2391 | ubifs_err("two data nodes for the same block"); | ||
2392 | goto error_dump; | ||
2393 | } | ||
2394 | } | ||
2395 | |||
2396 | return 0; | ||
2397 | |||
2398 | error_dump: | ||
2399 | dbg_dump_node(c, sa->node); | ||
2400 | dbg_dump_node(c, sb->node); | ||
2401 | return -EINVAL; | ||
2402 | } | ||
2403 | |||
2404 | /** | ||
2405 | * dbg_check_nondata_nodes_order - check that list of data nodes is sorted. | ||
2406 | * @c: UBIFS file-system description object | ||
2407 | * @head: the list of nodes ('struct ubifs_scan_node' objects) | ||
2408 | * | ||
2409 | * This function returns zero if the list of non-data nodes is sorted correctly, | ||
2410 | * and %-EINVAL if not. | ||
2411 | */ | ||
2412 | int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head) | ||
2413 | { | ||
2414 | struct list_head *cur; | ||
2415 | struct ubifs_scan_node *sa, *sb; | ||
2416 | |||
2417 | if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) | ||
2418 | return 0; | ||
2419 | |||
2420 | for (cur = head->next; cur->next != head; cur = cur->next) { | ||
2421 | ino_t inuma, inumb; | ||
2422 | uint32_t hasha, hashb; | ||
2423 | |||
2424 | cond_resched(); | ||
2425 | sa = container_of(cur, struct ubifs_scan_node, list); | ||
2426 | sb = container_of(cur->next, struct ubifs_scan_node, list); | ||
2427 | |||
2428 | if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && | ||
2429 | sa->type != UBIFS_XENT_NODE) { | ||
2430 | ubifs_err("bad node type %d", sa->type); | ||
2431 | dbg_dump_node(c, sa->node); | ||
2432 | return -EINVAL; | ||
2433 | } | ||
2434 | if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE && | ||
2435 | sa->type != UBIFS_XENT_NODE) { | ||
2436 | ubifs_err("bad node type %d", sb->type); | ||
2437 | dbg_dump_node(c, sb->node); | ||
2438 | return -EINVAL; | ||
2439 | } | ||
2440 | |||
2441 | if (sa->type != UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { | ||
2442 | ubifs_err("non-inode node goes before inode node"); | ||
2443 | goto error_dump; | ||
2444 | } | ||
2445 | |||
2446 | if (sa->type == UBIFS_INO_NODE && sb->type != UBIFS_INO_NODE) | ||
2447 | continue; | ||
2448 | |||
2449 | if (sa->type == UBIFS_INO_NODE && sb->type == UBIFS_INO_NODE) { | ||
2450 | /* Inode nodes are sorted in descending size order */ | ||
2451 | if (sa->len < sb->len) { | ||
2452 | ubifs_err("smaller inode node goes first"); | ||
2453 | goto error_dump; | ||
2454 | } | ||
2455 | continue; | ||
2456 | } | ||
2457 | |||
2458 | /* | ||
2459 | * This is either a dentry or xentry, which should be sorted in | ||
2460 | * ascending (parent ino, hash) order. | ||
2461 | */ | ||
2462 | inuma = key_inum(c, &sa->key); | ||
2463 | inumb = key_inum(c, &sb->key); | ||
2464 | |||
2465 | if (inuma < inumb) | ||
2466 | continue; | ||
2467 | if (inuma > inumb) { | ||
2468 | ubifs_err("larger inum %lu goes before inum %lu", | ||
2469 | (unsigned long)inuma, (unsigned long)inumb); | ||
2470 | goto error_dump; | ||
2471 | } | ||
2472 | |||
2473 | hasha = key_block(c, &sa->key); | ||
2474 | hashb = key_block(c, &sb->key); | ||
2475 | |||
2476 | if (hasha > hashb) { | ||
2477 | ubifs_err("larger hash %u goes before %u", | ||
2478 | hasha, hashb); | ||
2479 | goto error_dump; | ||
2480 | } | ||
2481 | } | ||
2482 | |||
2483 | return 0; | ||
2484 | |||
2485 | error_dump: | ||
2486 | ubifs_msg("dumping first node"); | ||
2487 | dbg_dump_node(c, sa->node); | ||
2488 | ubifs_msg("dumping second node"); | ||
2489 | dbg_dump_node(c, sb->node); | ||
2490 | return -EINVAL; | ||
2491 | return 0; | ||
2492 | } | ||
2243 | 2493 | ||
2244 | int dbg_force_in_the_gaps(void) | 2494 | int dbg_force_in_the_gaps(void) |
2245 | { | 2495 | { |
2246 | if (!dbg_force_in_the_gaps_enabled) | 2496 | if (!(ubifs_chk_flags & UBIFS_CHK_GEN)) |
2247 | return 0; | 2497 | return 0; |
2248 | /* Force in-the-gaps every 8th commit */ | 2498 | |
2249 | return !((invocation_cnt++) & 0x7); | 2499 | return !(random32() & 7); |
2250 | } | 2500 | } |
2251 | 2501 | ||
2252 | /* Failure mode for recovery testing */ | 2502 | /* Failure mode for recovery testing */ |
@@ -2434,7 +2684,7 @@ int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, | |||
2434 | int len, int check) | 2684 | int len, int check) |
2435 | { | 2685 | { |
2436 | if (in_failure_mode(desc)) | 2686 | if (in_failure_mode(desc)) |
2437 | return -EIO; | 2687 | return -EROFS; |
2438 | return ubi_leb_read(desc, lnum, buf, offset, len, check); | 2688 | return ubi_leb_read(desc, lnum, buf, offset, len, check); |
2439 | } | 2689 | } |
2440 | 2690 | ||
@@ -2444,7 +2694,7 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, | |||
2444 | int err, failing; | 2694 | int err, failing; |
2445 | 2695 | ||
2446 | if (in_failure_mode(desc)) | 2696 | if (in_failure_mode(desc)) |
2447 | return -EIO; | 2697 | return -EROFS; |
2448 | failing = do_fail(desc, lnum, 1); | 2698 | failing = do_fail(desc, lnum, 1); |
2449 | if (failing) | 2699 | if (failing) |
2450 | cut_data(buf, len); | 2700 | cut_data(buf, len); |
@@ -2452,7 +2702,7 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, | |||
2452 | if (err) | 2702 | if (err) |
2453 | return err; | 2703 | return err; |
2454 | if (failing) | 2704 | if (failing) |
2455 | return -EIO; | 2705 | return -EROFS; |
2456 | return 0; | 2706 | return 0; |
2457 | } | 2707 | } |
2458 | 2708 | ||
@@ -2462,12 +2712,12 @@ int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, | |||
2462 | int err; | 2712 | int err; |
2463 | 2713 | ||
2464 | if (do_fail(desc, lnum, 1)) | 2714 | if (do_fail(desc, lnum, 1)) |
2465 | return -EIO; | 2715 | return -EROFS; |
2466 | err = ubi_leb_change(desc, lnum, buf, len, dtype); | 2716 | err = ubi_leb_change(desc, lnum, buf, len, dtype); |
2467 | if (err) | 2717 | if (err) |
2468 | return err; | 2718 | return err; |
2469 | if (do_fail(desc, lnum, 1)) | 2719 | if (do_fail(desc, lnum, 1)) |
2470 | return -EIO; | 2720 | return -EROFS; |
2471 | return 0; | 2721 | return 0; |
2472 | } | 2722 | } |
2473 | 2723 | ||
@@ -2476,12 +2726,12 @@ int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum) | |||
2476 | int err; | 2726 | int err; |
2477 | 2727 | ||
2478 | if (do_fail(desc, lnum, 0)) | 2728 | if (do_fail(desc, lnum, 0)) |
2479 | return -EIO; | 2729 | return -EROFS; |
2480 | err = ubi_leb_erase(desc, lnum); | 2730 | err = ubi_leb_erase(desc, lnum); |
2481 | if (err) | 2731 | if (err) |
2482 | return err; | 2732 | return err; |
2483 | if (do_fail(desc, lnum, 0)) | 2733 | if (do_fail(desc, lnum, 0)) |
2484 | return -EIO; | 2734 | return -EROFS; |
2485 | return 0; | 2735 | return 0; |
2486 | } | 2736 | } |
2487 | 2737 | ||
@@ -2490,19 +2740,19 @@ int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum) | |||
2490 | int err; | 2740 | int err; |
2491 | 2741 | ||
2492 | if (do_fail(desc, lnum, 0)) | 2742 | if (do_fail(desc, lnum, 0)) |
2493 | return -EIO; | 2743 | return -EROFS; |
2494 | err = ubi_leb_unmap(desc, lnum); | 2744 | err = ubi_leb_unmap(desc, lnum); |
2495 | if (err) | 2745 | if (err) |
2496 | return err; | 2746 | return err; |
2497 | if (do_fail(desc, lnum, 0)) | 2747 | if (do_fail(desc, lnum, 0)) |
2498 | return -EIO; | 2748 | return -EROFS; |
2499 | return 0; | 2749 | return 0; |
2500 | } | 2750 | } |
2501 | 2751 | ||
2502 | int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum) | 2752 | int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum) |
2503 | { | 2753 | { |
2504 | if (in_failure_mode(desc)) | 2754 | if (in_failure_mode(desc)) |
2505 | return -EIO; | 2755 | return -EROFS; |
2506 | return ubi_is_mapped(desc, lnum); | 2756 | return ubi_is_mapped(desc, lnum); |
2507 | } | 2757 | } |
2508 | 2758 | ||
@@ -2511,12 +2761,12 @@ int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) | |||
2511 | int err; | 2761 | int err; |
2512 | 2762 | ||
2513 | if (do_fail(desc, lnum, 0)) | 2763 | if (do_fail(desc, lnum, 0)) |
2514 | return -EIO; | 2764 | return -EROFS; |
2515 | err = ubi_leb_map(desc, lnum, dtype); | 2765 | err = ubi_leb_map(desc, lnum, dtype); |
2516 | if (err) | 2766 | if (err) |
2517 | return err; | 2767 | return err; |
2518 | if (do_fail(desc, lnum, 0)) | 2768 | if (do_fail(desc, lnum, 0)) |
2519 | return -EIO; | 2769 | return -EROFS; |
2520 | return 0; | 2770 | return 0; |
2521 | } | 2771 | } |
2522 | 2772 | ||
@@ -2534,16 +2784,8 @@ int ubifs_debugging_init(struct ubifs_info *c) | |||
2534 | if (!c->dbg) | 2784 | if (!c->dbg) |
2535 | return -ENOMEM; | 2785 | return -ENOMEM; |
2536 | 2786 | ||
2537 | c->dbg->buf = vmalloc(c->leb_size); | ||
2538 | if (!c->dbg->buf) | ||
2539 | goto out; | ||
2540 | |||
2541 | failure_mode_init(c); | 2787 | failure_mode_init(c); |
2542 | return 0; | 2788 | return 0; |
2543 | |||
2544 | out: | ||
2545 | kfree(c->dbg); | ||
2546 | return -ENOMEM; | ||
2547 | } | 2789 | } |
2548 | 2790 | ||
2549 | /** | 2791 | /** |
@@ -2553,7 +2795,6 @@ out: | |||
2553 | void ubifs_debugging_exit(struct ubifs_info *c) | 2795 | void ubifs_debugging_exit(struct ubifs_info *c) |
2554 | { | 2796 | { |
2555 | failure_mode_exit(c); | 2797 | failure_mode_exit(c); |
2556 | vfree(c->dbg->buf); | ||
2557 | kfree(c->dbg); | 2798 | kfree(c->dbg); |
2558 | } | 2799 | } |
2559 | 2800 | ||
@@ -2595,7 +2836,7 @@ void dbg_debugfs_exit(void) | |||
2595 | static int open_debugfs_file(struct inode *inode, struct file *file) | 2836 | static int open_debugfs_file(struct inode *inode, struct file *file) |
2596 | { | 2837 | { |
2597 | file->private_data = inode->i_private; | 2838 | file->private_data = inode->i_private; |
2598 | return 0; | 2839 | return nonseekable_open(inode, file); |
2599 | } | 2840 | } |
2600 | 2841 | ||
2601 | static ssize_t write_debugfs_file(struct file *file, const char __user *buf, | 2842 | static ssize_t write_debugfs_file(struct file *file, const char __user *buf, |
@@ -2606,18 +2847,15 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf, | |||
2606 | 2847 | ||
2607 | if (file->f_path.dentry == d->dfs_dump_lprops) | 2848 | if (file->f_path.dentry == d->dfs_dump_lprops) |
2608 | dbg_dump_lprops(c); | 2849 | dbg_dump_lprops(c); |
2609 | else if (file->f_path.dentry == d->dfs_dump_budg) { | 2850 | else if (file->f_path.dentry == d->dfs_dump_budg) |
2610 | spin_lock(&c->space_lock); | 2851 | dbg_dump_budg(c, &c->bi); |
2611 | dbg_dump_budg(c); | 2852 | else if (file->f_path.dentry == d->dfs_dump_tnc) { |
2612 | spin_unlock(&c->space_lock); | ||
2613 | } else if (file->f_path.dentry == d->dfs_dump_tnc) { | ||
2614 | mutex_lock(&c->tnc_mutex); | 2853 | mutex_lock(&c->tnc_mutex); |
2615 | dbg_dump_tnc(c); | 2854 | dbg_dump_tnc(c); |
2616 | mutex_unlock(&c->tnc_mutex); | 2855 | mutex_unlock(&c->tnc_mutex); |
2617 | } else | 2856 | } else |
2618 | return -EINVAL; | 2857 | return -EINVAL; |
2619 | 2858 | ||
2620 | *ppos += count; | ||
2621 | return count; | 2859 | return count; |
2622 | } | 2860 | } |
2623 | 2861 | ||
@@ -2625,6 +2863,7 @@ static const struct file_operations dfs_fops = { | |||
2625 | .open = open_debugfs_file, | 2863 | .open = open_debugfs_file, |
2626 | .write = write_debugfs_file, | 2864 | .write = write_debugfs_file, |
2627 | .owner = THIS_MODULE, | 2865 | .owner = THIS_MODULE, |
2866 | .llseek = no_llseek, | ||
2628 | }; | 2867 | }; |
2629 | 2868 | ||
2630 | /** | 2869 | /** |
@@ -2647,40 +2886,38 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) | |||
2647 | struct ubifs_debug_info *d = c->dbg; | 2886 | struct ubifs_debug_info *d = c->dbg; |
2648 | 2887 | ||
2649 | sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); | 2888 | sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); |
2650 | d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir); | 2889 | fname = d->dfs_dir_name; |
2651 | if (IS_ERR(d->dfs_dir)) { | 2890 | dent = debugfs_create_dir(fname, dfs_rootdir); |
2652 | err = PTR_ERR(d->dfs_dir); | 2891 | if (IS_ERR_OR_NULL(dent)) |
2653 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2654 | d->dfs_dir_name, err); | ||
2655 | goto out; | 2892 | goto out; |
2656 | } | 2893 | d->dfs_dir = dent; |
2657 | 2894 | ||
2658 | fname = "dump_lprops"; | 2895 | fname = "dump_lprops"; |
2659 | dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); | 2896 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); |
2660 | if (IS_ERR(dent)) | 2897 | if (IS_ERR_OR_NULL(dent)) |
2661 | goto out_remove; | 2898 | goto out_remove; |
2662 | d->dfs_dump_lprops = dent; | 2899 | d->dfs_dump_lprops = dent; |
2663 | 2900 | ||
2664 | fname = "dump_budg"; | 2901 | fname = "dump_budg"; |
2665 | dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); | 2902 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); |
2666 | if (IS_ERR(dent)) | 2903 | if (IS_ERR_OR_NULL(dent)) |
2667 | goto out_remove; | 2904 | goto out_remove; |
2668 | d->dfs_dump_budg = dent; | 2905 | d->dfs_dump_budg = dent; |
2669 | 2906 | ||
2670 | fname = "dump_tnc"; | 2907 | fname = "dump_tnc"; |
2671 | dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); | 2908 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); |
2672 | if (IS_ERR(dent)) | 2909 | if (IS_ERR_OR_NULL(dent)) |
2673 | goto out_remove; | 2910 | goto out_remove; |
2674 | d->dfs_dump_tnc = dent; | 2911 | d->dfs_dump_tnc = dent; |
2675 | 2912 | ||
2676 | return 0; | 2913 | return 0; |
2677 | 2914 | ||
2678 | out_remove: | 2915 | out_remove: |
2679 | err = PTR_ERR(dent); | ||
2680 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2681 | fname, err); | ||
2682 | debugfs_remove_recursive(d->dfs_dir); | 2916 | debugfs_remove_recursive(d->dfs_dir); |
2683 | out: | 2917 | out: |
2918 | err = dent ? PTR_ERR(dent) : -ENODEV; | ||
2919 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2920 | fname, err); | ||
2684 | return err; | 2921 | return err; |
2685 | } | 2922 | } |
2686 | 2923 | ||