Patchwork UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'

login
register
mail settings
Submitter Artem Bityutskiy
Date Oct. 9, 2012, 1:30 p.m.
Message ID <1349789437.1992.116.camel@sauron.fi.intel.com>
Download mbox | patch
Permalink /patch/190303/
State New
Headers show

Comments

Artem Bityutskiy - Oct. 9, 2012, 1:30 p.m.
On Sun, 2012-09-23 at 10:48 -0500, Brent Taylor wrote:
> Ping,  I just didn't want to get lost in the e-mail shuffle.

OK, Brent, here is the fix. I am sorry for so long delay. I simply
do not have enough time for my UBIFS hobby. And thank you for sending
me the image. The fix is attached.

From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Date: Tue, 9 Oct 2012 16:20:15 +0300
Subject: [PATCH] UBIFS: fix mounting problems after power cuts

This is a bugfix for a problem with the following symptoms:

1. A power cut happens
2. After reboot, we try to mount UBIFS
3. Mount fails with "No space left on device" error message

UBIFS complains like this:

UBIFS error (pid 28225): grab_empty_leb: could not find an empty LEB

The root cause of this problem is that when we mount, not all LEBs are
categorized. Only those which were read are. However, the
'ubifs_find_free_leb_for_idx()' function assumes that all LEBs were
categorized and 'c->freeable_cnt' is valid, which is a false assumption.

This patch fixes the problem by teaching 'ubifs_find_free_leb_for_idx()'
to always fall back to LPT scanning if no freeable LEBs were found.

This problem was reported by several people in the past, but Brent Taylor
was able to reproduce it and send me a flash image which cannot be mounted,
which made it easy to hunt the bug. Kudos to Brent.

Reported-by: Brent Taylor <motobud@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: stable@vger.kernel.org
---
 fs/ubifs/find.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)
Artem Bityutskiy - Oct. 9, 2012, 5:25 p.m.
On Tue, 2012-10-09 at 12:11 -0500, Brent Taylor wrote:
> Artem,
>    Thanks so much for your time to track down this bug.  I've tested
> your patch and it does mount the filesystem that it would fail on
> before.  I'm glad I could help.  I want to thank you for all your work
> in the UBI and UBIFS subsystems and all your contributions to the
> Linux kernel.

Thanks!

I will send a better version of the patch later, and give it some more
test. I will keep you in CC.

Patch

From e8d6b0e4615ba38b0d3dd6246517b346c91e6a8d Mon Sep 17 00:00:00 2001
From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Date: Tue, 9 Oct 2012 16:20:15 +0300
Subject: [PATCH] UBIFS: fix mounting problems after power cuts

This is a bugfix for a problem with the following symptoms:

1. A power cut happens
2. After reboot, we try to mount UBIFS
3. Mount fails with "No space left on device" error message

UBIFS complains like this:

UBIFS error (pid 28225): grab_empty_leb: could not find an empty LEB

The root cause of this problem is that when we mount, not all LEBs are
categorized. Only those which were read are. However, the
'ubifs_find_free_leb_for_idx()' function assumes that all LEBs were
categorized and 'c->freeable_cnt' is valid, which is a false assumption.

This patch fixes the problem by teaching 'ubifs_find_free_leb_for_idx()'
to always fall back to LPT scanning if no freeable LEBs were found.

This problem was reported by several people in the past, but Brent Taylor
was able to reproduce it and send me a flash image which cannot be mounted,
which made it easy to hunt the bug. Kudos to Brent.

Reported-by: Brent Taylor <motobud@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: stable@vger.kernel.org
---

 fs/ubifs/find.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c

index 28ec13a..959386b 100644

--- a/fs/ubifs/find.c

+++ b/fs/ubifs/find.c

@@ -682,12 +682,10 @@  int ubifs_find_free_leb_for_idx(struct ubifs_info *c)

 		lprops = ubifs_fast_find_freeable(c);
 		if (!lprops) {
 			ubifs_assert(c->freeable_cnt == 0);
-			if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {

-				lprops = scan_for_leb_for_idx(c);

-				if (IS_ERR(lprops)) {

-					err = PTR_ERR(lprops);

-					goto out;

-				}

+			lprops = scan_for_leb_for_idx(c);

+			if (IS_ERR(lprops)) {

+				err = PTR_ERR(lprops);

+				goto out;

 			}
 		}
 	}
-- 

1.7.7.6