From cc6a86b950d69cfe542ee0d0ff30790152936a00 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 1 Apr 2011 10:10:52 +0300 Subject: UBIFS: unify error path dbg_debugfs_init_fs This is just a small clean-up patch which simlifies and unifies the error path in the dbg_debugfs_init_fs(). We have common error path for all failure cases in this function except of the very first case. And this patch makes the first failure case use the same error path as the other cases by using the 'fname' and 'dent' variables. Signed-off-by: Artem Bityutskiy Acked-by: Phil Carmody --- fs/ubifs/debug.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index f25a7339f800..304cc6e1c84b 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2806,13 +2806,11 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) struct ubifs_debug_info *d = c->dbg; sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); - d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir); - if (IS_ERR(d->dfs_dir)) { - err = PTR_ERR(d->dfs_dir); - ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", - d->dfs_dir_name, err); + fname = d->dfs_dir_name; + dent = debugfs_create_dir(fname, dfs_rootdir); + if (IS_ERR(dent)) goto out; - } + d->dfs_dir = dent; fname = "dump_lprops"; dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); @@ -2835,11 +2833,11 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) return 0; out_remove: + debugfs_remove_recursive(d->dfs_dir); +out: err = PTR_ERR(dent); ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", fname, err); - debugfs_remove_recursive(d->dfs_dir); -out: return err; } -- cgit v1.2.2 From 95169535113073993a3ed97ecc21831657f42a80 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 1 Apr 2011 10:16:17 +0300 Subject: UBIFS: fix error path in dbg_debugfs_init_fs The debug interface is substandard and on error returns either NULL or an error code packed in the pointer. So using "IS_ERR" for the pointers returned by debugfs function is incorrect. Instead, we should use IS_ERR_OR_NULL. This path is an improved vestion of the original patch from Phil Carmody. Reported-by: Phil Carmody Signed-off-by: Artem Bityutskiy Acked-by: Phil Carmody --- fs/ubifs/debug.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 304cc6e1c84b..645737769c98 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2808,25 +2808,25 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); fname = d->dfs_dir_name; dent = debugfs_create_dir(fname, dfs_rootdir); - if (IS_ERR(dent)) + if (IS_ERR_OR_NULL(dent)) goto out; d->dfs_dir = dent; fname = "dump_lprops"; dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); - if (IS_ERR(dent)) + if (IS_ERR_OR_NULL(dent)) goto out_remove; d->dfs_dump_lprops = dent; fname = "dump_budg"; dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); - if (IS_ERR(dent)) + if (IS_ERR_OR_NULL(dent)) goto out_remove; d->dfs_dump_budg = dent; fname = "dump_tnc"; dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops); - if (IS_ERR(dent)) + if (IS_ERR_OR_NULL(dent)) goto out_remove; d->dfs_dump_tnc = dent; @@ -2835,7 +2835,7 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) out_remove: debugfs_remove_recursive(d->dfs_dir); out: - err = PTR_ERR(dent); + err = dent ? PTR_ERR(dent) : -ENODEV; ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", fname, err); return err; -- cgit v1.2.2 From 7da6443aca9be29c6948dcbd636ad50154d0bc0c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 4 Apr 2011 17:16:39 +0300 Subject: UBIFS: fix debugging failure in dbg_check_space_info This patch fixes a debugging failure with which looks like this: UBIFS error (pid 32313): dbg_check_space_info: free space changed from 6019344 to 6022654 The reason for this failure is described in the comment this patch adds to the code. But in short - 'c->freeable_cnt' may be different before and after re-mounting, and this is normal. So the debugging code should make sure that free space calculations do not depend on 'c->freeable_cnt'. A similar issue has been reported here: http://lists.infradead.org/pipermail/linux-mtd/2011-April/034647.html This patch should fix it. For the -stable guys: this patch is only relevant for kernels 2.6.30 onwards. Signed-off-by: Artem Bityutskiy Cc: stable@kernel.org [2.6.30+] --- fs/ubifs/debug.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'fs/ubifs/debug.c') diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 645737769c98..004d3745dc45 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -972,11 +972,39 @@ void dbg_dump_index(struct ubifs_info *c) void dbg_save_space_info(struct ubifs_info *c) { struct ubifs_debug_info *d = c->dbg; - - ubifs_get_lp_stats(c, &d->saved_lst); + int freeable_cnt; spin_lock(&c->space_lock); + memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats)); + + /* + * We use a dirty hack here and zero out @c->freeable_cnt, because it + * affects the free space calculations, and UBIFS might not know about + * all freeable eraseblocks. Indeed, we know about freeable eraseblocks + * only when we read their lprops, and we do this only lazily, upon the + * need. So at any given point of time @c->freeable_cnt might be not + * exactly accurate. + * + * Just one example about the issue we hit when we did not zero + * @c->freeable_cnt. + * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the + * amount of free space in @d->saved_free + * 2. We re-mount R/W, which makes UBIFS to read the "lsave" + * information from flash, where we cache LEBs from various + * categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()' + * -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()' + * -> 'ubifs_get_pnode()' -> 'update_cats()' + * -> 'ubifs_add_to_cat()'). + * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt + * becomes %1. + * 4. We calculate the amount of free space when the re-mount is + * finished in 'dbg_check_space_info()' and it does not match + * @d->saved_free. + */ + freeable_cnt = c->freeable_cnt; + c->freeable_cnt = 0; d->saved_free = ubifs_get_free_space_nolock(c); + c->freeable_cnt = freeable_cnt; spin_unlock(&c->space_lock); } @@ -993,12 +1021,15 @@ int dbg_check_space_info(struct ubifs_info *c) { struct ubifs_debug_info *d = c->dbg; struct ubifs_lp_stats lst; - long long avail, free; + long long free; + int freeable_cnt; spin_lock(&c->space_lock); - avail = ubifs_calc_available(c, c->min_idx_lebs); + freeable_cnt = c->freeable_cnt; + c->freeable_cnt = 0; + free = ubifs_get_free_space_nolock(c); + c->freeable_cnt = freeable_cnt; spin_unlock(&c->space_lock); - free = ubifs_get_free_space(c); if (free != d->saved_free) { ubifs_err("free space changed from %lld to %lld", -- cgit v1.2.2