diff options
Diffstat (limited to 'fs/ubifs/debug.c')
-rw-r--r-- | fs/ubifs/debug.c | 65 |
1 files changed, 47 insertions, 18 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 01c2b028e525..004d3745dc45 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -818,7 +818,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum) | |||
818 | printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n", | 818 | printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n", |
819 | current->pid, lnum); | 819 | current->pid, lnum); |
820 | 820 | ||
821 | buf = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); | 821 | buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); |
822 | if (!buf) { | 822 | if (!buf) { |
823 | ubifs_err("cannot allocate memory for dumping LEB %d", lnum); | 823 | ubifs_err("cannot allocate memory for dumping LEB %d", lnum); |
824 | return; | 824 | return; |
@@ -972,11 +972,39 @@ void dbg_dump_index(struct ubifs_info *c) | |||
972 | void dbg_save_space_info(struct ubifs_info *c) | 972 | void dbg_save_space_info(struct ubifs_info *c) |
973 | { | 973 | { |
974 | struct ubifs_debug_info *d = c->dbg; | 974 | struct ubifs_debug_info *d = c->dbg; |
975 | 975 | int freeable_cnt; | |
976 | ubifs_get_lp_stats(c, &d->saved_lst); | ||
977 | 976 | ||
978 | spin_lock(&c->space_lock); | 977 | spin_lock(&c->space_lock); |
978 | memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats)); | ||
979 | |||
980 | /* | ||
981 | * We use a dirty hack here and zero out @c->freeable_cnt, because it | ||
982 | * affects the free space calculations, and UBIFS might not know about | ||
983 | * all freeable eraseblocks. Indeed, we know about freeable eraseblocks | ||
984 | * only when we read their lprops, and we do this only lazily, upon the | ||
985 | * need. So at any given point of time @c->freeable_cnt might be not | ||
986 | * exactly accurate. | ||
987 | * | ||
988 | * Just one example about the issue we hit when we did not zero | ||
989 | * @c->freeable_cnt. | ||
990 | * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the | ||
991 | * amount of free space in @d->saved_free | ||
992 | * 2. We re-mount R/W, which makes UBIFS to read the "lsave" | ||
993 | * information from flash, where we cache LEBs from various | ||
994 | * categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()' | ||
995 | * -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()' | ||
996 | * -> 'ubifs_get_pnode()' -> 'update_cats()' | ||
997 | * -> 'ubifs_add_to_cat()'). | ||
998 | * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt | ||
999 | * becomes %1. | ||
1000 | * 4. We calculate the amount of free space when the re-mount is | ||
1001 | * finished in 'dbg_check_space_info()' and it does not match | ||
1002 | * @d->saved_free. | ||
1003 | */ | ||
1004 | freeable_cnt = c->freeable_cnt; | ||
1005 | c->freeable_cnt = 0; | ||
979 | d->saved_free = ubifs_get_free_space_nolock(c); | 1006 | d->saved_free = ubifs_get_free_space_nolock(c); |
1007 | c->freeable_cnt = freeable_cnt; | ||
980 | spin_unlock(&c->space_lock); | 1008 | spin_unlock(&c->space_lock); |
981 | } | 1009 | } |
982 | 1010 | ||
@@ -993,12 +1021,15 @@ int dbg_check_space_info(struct ubifs_info *c) | |||
993 | { | 1021 | { |
994 | struct ubifs_debug_info *d = c->dbg; | 1022 | struct ubifs_debug_info *d = c->dbg; |
995 | struct ubifs_lp_stats lst; | 1023 | struct ubifs_lp_stats lst; |
996 | long long avail, free; | 1024 | long long free; |
1025 | int freeable_cnt; | ||
997 | 1026 | ||
998 | spin_lock(&c->space_lock); | 1027 | spin_lock(&c->space_lock); |
999 | avail = ubifs_calc_available(c, c->min_idx_lebs); | 1028 | freeable_cnt = c->freeable_cnt; |
1029 | c->freeable_cnt = 0; | ||
1030 | free = ubifs_get_free_space_nolock(c); | ||
1031 | c->freeable_cnt = freeable_cnt; | ||
1000 | spin_unlock(&c->space_lock); | 1032 | spin_unlock(&c->space_lock); |
1001 | free = ubifs_get_free_space(c); | ||
1002 | 1033 | ||
1003 | if (free != d->saved_free) { | 1034 | if (free != d->saved_free) { |
1004 | ubifs_err("free space changed from %lld to %lld", | 1035 | ubifs_err("free space changed from %lld to %lld", |
@@ -2806,40 +2837,38 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) | |||
2806 | struct ubifs_debug_info *d = c->dbg; | 2837 | struct ubifs_debug_info *d = c->dbg; |
2807 | 2838 | ||
2808 | sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); | 2839 | sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); |
2809 | d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir); | 2840 | fname = d->dfs_dir_name; |
2810 | if (IS_ERR(d->dfs_dir)) { | 2841 | dent = debugfs_create_dir(fname, dfs_rootdir); |
2811 | err = PTR_ERR(d->dfs_dir); | 2842 | if (IS_ERR_OR_NULL(dent)) |
2812 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2813 | d->dfs_dir_name, err); | ||
2814 | goto out; | 2843 | goto out; |
2815 | } | 2844 | d->dfs_dir = dent; |
2816 | 2845 | ||
2817 | fname = "dump_lprops"; | 2846 | fname = "dump_lprops"; |
2818 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); | 2847 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); |
2819 | if (IS_ERR(dent)) | 2848 | if (IS_ERR_OR_NULL(dent)) |
2820 | goto out_remove; | 2849 | goto out_remove; |
2821 | d->dfs_dump_lprops = dent; | 2850 | d->dfs_dump_lprops = dent; |
2822 | 2851 | ||
2823 | fname = "dump_budg"; | 2852 | fname = "dump_budg"; |
2824 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); | 2853 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); |
2825 | if (IS_ERR(dent)) | 2854 | if (IS_ERR_OR_NULL(dent)) |
2826 | goto out_remove; | 2855 | goto out_remove; |
2827 | d->dfs_dump_budg = dent; | 2856 | d->dfs_dump_budg = dent; |
2828 | 2857 | ||
2829 | fname = "dump_tnc"; | 2858 | fname = "dump_tnc"; |
2830 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); | 2859 | dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); |
2831 | if (IS_ERR(dent)) | 2860 | if (IS_ERR_OR_NULL(dent)) |
2832 | goto out_remove; | 2861 | goto out_remove; |
2833 | d->dfs_dump_tnc = dent; | 2862 | d->dfs_dump_tnc = dent; |
2834 | 2863 | ||
2835 | return 0; | 2864 | return 0; |
2836 | 2865 | ||
2837 | out_remove: | 2866 | out_remove: |
2838 | err = PTR_ERR(dent); | ||
2839 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2840 | fname, err); | ||
2841 | debugfs_remove_recursive(d->dfs_dir); | 2867 | debugfs_remove_recursive(d->dfs_dir); |
2842 | out: | 2868 | out: |
2869 | err = dent ? PTR_ERR(dent) : -ENODEV; | ||
2870 | ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", | ||
2871 | fname, err); | ||
2843 | return err; | 2872 | return err; |
2844 | } | 2873 | } |
2845 | 2874 | ||