summaryrefslogtreecommitdiffstats
path: root/fs/ubifs/sb.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@linux.intel.com>2012-07-14 14:33:09 +0300
committerArtem Bityutskiy <artem.bityutskiy@linux.intel.com>2012-07-20 10:13:27 +0300
commitc6727932cfdb13501108b16c38463c09d5ec7a74 (patch)
tree2f6a0d7ea467139e0008ecf7bad420ac1d081126 /fs/ubifs/sb.c
parentbd0a521e88aa7a06ae7aabaed7ae196ed4ad867a (diff)
downloadlinux-stable-c6727932cfdb13501108b16c38463c09d5ec7a74.tar.gz
linux-stable-c6727932cfdb13501108b16c38463c09d5ec7a74.tar.bz2
linux-stable-c6727932cfdb13501108b16c38463c09d5ec7a74.zip
UBIFS: fix a bug in empty space fix-up
UBIFS has a feature called "empty space fix-up" which is a quirk to work-around limitations of dumb flasher programs. Namely, of those flashers that are unable to skip NAND pages full of 0xFFs while flashing, resulting in empty space at the end of half-filled eraseblocks to be unusable for UBIFS. This feature is relatively new (introduced in v3.0). The fix-up routine (fixup_free_space()) is executed only once at the very first mount if the superblock has the 'space_fixup' flag set (can be done with -F option of mkfs.ubifs). It basically reads all the UBIFS data and metadata and writes it back to the same LEB. The routine assumes the image is pristine and does not have anything in the journal. There was a bug in 'fixup_free_space()' where it fixed up the log incorrectly. All but one LEB of the log of a pristine file-system are empty. And one contains just a commit start node. And 'fixup_free_space()' just unmapped this LEB, which resulted in wiping the commit start node. As a result, some users were unable to mount the file-system next time with the following symptom: UBIFS error (pid 1): replay_log_leb: first log node at LEB 3:0 is not CS node UBIFS error (pid 1): replay_log_leb: log error detected while replaying the log at LEB 3:0 The root-cause of this bug was that 'fixup_free_space()' wrongly assumed that the beginning of empty space in the log head (c->lhead_offs) was known on mount. However, it is not the case - it was always 0. UBIFS does not store in it the master node and finds out by scanning the log on every mount. The fix is simple - just pass commit start node size instead of 0 to 'fixup_leb()'. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@linux.intel.com> Cc: stable@vger.kernel.org [v3.0+] Reported-by: Iwo Mergler <Iwo.Mergler@netcommwireless.com> Tested-by: Iwo Mergler <Iwo.Mergler@netcommwireless.com> Reported-by: James Nute <newten82@gmail.com>
Diffstat (limited to 'fs/ubifs/sb.c')
-rw-r--r--fs/ubifs/sb.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index ef3d1ba6d992..15e2fc5aa60b 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -718,8 +718,12 @@ static int fixup_free_space(struct ubifs_info *c)
lnum = ubifs_next_log_lnum(c, lnum);
}
- /* Fixup the current log head */
- err = fixup_leb(c, c->lhead_lnum, c->lhead_offs);
+ /*
+ * Fixup the log head which contains the only a CS node at the
+ * beginning.
+ */
+ err = fixup_leb(c, c->lhead_lnum,
+ ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size));
if (err)
goto out;