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 | ||
