From: Pieter Smith Date: Wed, 29 Mar 2017 16:21:56 +0000 (+0200) Subject: libfstools: fix multiple volume_identify usages with the same volume X-Git-Url: http://git.openwrt.org/?p=project%2Ffstools.git;a=commitdiff_plain;h=45c2a6ff74d4d26a29ed2e79f0d65b13a0caee20 libfstools: fix multiple volume_identify usages with the same volume This fixes e.g. factory-flashed startup issue with jffs2 on ubi overlay Commit ba019965 ("libfstools: accept volume as argument in most calls") broke startup for factory-flashed jffs2 on ubi systems, causing substantial slowdown in factory environments. When starting up with a factory-flashed jffs2 on ubi system, the "rootfs_data" volume contains a deadcode marker. In the start phase, mount_root then mounts a tmpfs overlay, and postpones remounting of the jffs2 overlay until the done phase of the startup. The refactoring in ba019965 eliminated an unneeded call to volume_find() when done() called jffs2_switch(). Unfortunately the refactoring did not take into account that volume_identify() does not function correctly when called twice in a row on the same struct volume when using an mtd driver. mtd_volume_identify() uses mtd_volume_load() to open an fd to the mtd device and reads a potential deadcode marker from the fd. The first time this works, and FS_DEADCODE is returned. When volume_identify() is called a second time however, mtd_volume_load() notices that we already have an open fd, does nothing further and returns 0 without resetting the file offset to 0. mtd_volume_identify() now reads past the deadcode marker and now returns FS_JFFS2 if the mtd device is a UBIVOLUME. jffs2_switch() then handles the wrong case, either pulling the root out from under user-space in Chaos Calmer, or indefinitely sticking to a tmpfs overlay in later OpenWRT builds. Signed-off-by: Pieter Smith Signed-off-by: Rafał Miłecki --- diff --git a/libfstools/mtd.c b/libfstools/mtd.c index a1811c3..2603a15 100644 --- a/libfstools/mtd.c +++ b/libfstools/mtd.c @@ -76,8 +76,10 @@ static int mtd_volume_load(struct mtd_volume *p) struct mtd_info_user mtdInfo; struct erase_info_user mtdLockInfo; - if (p->fd) + if (p->fd) { + lseek(p->fd, 0, SEEK_SET); return 0; + } if (!p->chr) return -1;