mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 04:48:04 +09:00
UBIFS: fix debugging failure in dbg_check_space_info
commit 7da6443aca upstream.
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 <Artem.Bityutskiy@nokia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
5cb4b85443
commit
b94738ff1c
@@ -965,11 +965,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);
|
||||
}
|
||||
|
||||
@@ -986,12 +1014,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",
|
||||
|
||||
Reference in New Issue
Block a user