diff mbox series

bcm27xx: pad image to avoid false f2fs detection

Message ID C7D8B9F5-052B-4B5C-AFEE-047A699932F8@plan44.ch
State New
Headers show
Series bcm27xx: pad image to avoid false f2fs detection | expand

Commit Message

Lukas Zeller June 14, 2023, 4:12 p.m. UTC
From: Lukas Zeller <luz@plan44.ch>

Problem:

- bcm27xx SDCard images for squashfs/f2fs only contain the squashfs part.

- sysupgrade copies the image to the SDCard, with the space in the
  partition between end of the image and end of the partition untouched.

- This is the space where the f2fs overlay lives. Depending on the
  history of the SDcard, this space can contain anything.

- At reboot after sysupgrade, mount_root tries to detect a file system
  in that space.

- Usually, during a sysupgrade enough of that space gets overwritten
  to prevent detection of an existing file system (because normally,
  firmware upgrades mean increased squashfs size).
  This leads (as is correct after sysupgrade) to creation of a new f2fs.

- With a bit of bad luck however remaining parts of previous f2fs can
  lead to false detection by mount_root, but then failure to actually
  mount the overlay, or mounting a overlay with wrong data in it,
  leaving the device in an unusable state. See [1],[2] for detail
  description of how this happened in my case, [3] for another
  problem also caused by false FS detection happening to others.

Solution:

- As suggested by Michel Lespinasse in [4], padding the image with
  zeroes following the squashfs part solves the problem in a simple way.

- Michel's version did pad the image up to the full size of the rootfs
  partition, which does not make a noticeable difference in the gzipped
  form.

- However expansion, which takes place on device for sysupgrade,
  would potentially cause writing extra gigabytes of zeroes to the
  SDCard, depending on partition size, and also cause unneeded flash
  wear.

- Therefore, this patch limits padding to 1Mbytes or the remaining
  space in the rootfs partition, whichever is less.
  The 1M zero padding has been verified sufficient to prevent false
  f2fs detection with several RPi devices.

[1] http://lists.openwrt.org/pipermail/openwrt-devel/2023-May/041062.html
[2] https://forum.openwrt.org/t/broken-f2fs-after-sysupgrade-on-rpi-config-not-restored/159703
[3] https://forum.openwrt.org/t/rpi-4-sysupgrade-21-02-1-squashfs-overlay-retained/110586?u=wulfy23
[4] https://github.com/openwrt/openwrt/issues/9113#issuecomment-1293060405

Signed-off-by: Lukas Zeller <luz@plan44.ch>
---
 .../linux/bcm27xx/image/gen_rpi_sdcard_img.sh | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)

--
2.37.5
diff mbox series

Patch

diff --git a/target/linux/bcm27xx/image/gen_rpi_sdcard_img.sh b/target/linux/bcm27xx/image/gen_rpi_sdcard_img.sh
index 5e8fb2769c..a5185003bf 100755
--- a/target/linux/bcm27xx/image/gen_rpi_sdcard_img.sh
+++ b/target/linux/bcm27xx/image/gen_rpi_sdcard_img.sh
@@ -22,7 +22,34 @@  BOOTSIZE="$(($2 / 512))"
 ROOTFSOFFSET="$(($3 / 512))"
 ROOTFSSIZE="$(($4 / 512))"

+# for sqashfs + f2fs layout, the rootfs image is only the sqashfs part, which
+# is (usually much) smaller than the rootfs partition.
+# The f2fs part (for the overlay) will be created only at first boot
+# into the new image, when mount_root does not detect a valid filesystem already
+# present. To make sure random data from previous installations are not falsely
+# detected (which could and did happen in earlier versions), we add 1 MB zero padding
+# or up to the end of the rootfs partition, whichever is less.
+# While the padding is required for the squashfs+f2fs layout only, it does not
+# interfere with other rootfs partition types such as ext4.
+
+# the image itself is usually less than the partition size (ROOTFSSIZE)
+ROOTFSBYTES="$(wc -c < $ROOTFS)"
+ROOTFSIMGSIZE="$(( ($ROOTFSBYTES+511) / 512))"
+# we start padding one block BEFORE image ends
+PADOFFSET="$(($ROOTFSOFFSET + $ROOTFSIMGSIZE - 1))"
+PADSIZE="$(($ROOTFSSIZE - ROOTFSIMGSIZE + 1))"
+# limit the padding to 1M, it needs to be just enough to prevent false fs detection by mount_root
+if (( $PADSIZE > 2048 )); then
+    PADSIZE=2048
+fi
+
+# write the boot partition
 dd bs=512 if="$BOOTFS" of="$OUTPUT" seek="$BOOTOFFSET" conv=notrunc
+# pad out some space after rootfs image, overlapping last block
+if (( $PADSIZE > 0 )); then
+    dd bs=512 if=/dev/zero of="$OUTPUT" seek="$PADOFFSET" count="$PADSIZE" conv=notrunc
+fi
+# write the rootfs image which does usually not fill the entire partition
 dd bs=512 if="$ROOTFS" of="$OUTPUT" seek="$ROOTFSOFFSET" conv=notrunc