Skip to content

sysupgrade: --rootfs on a low-memory camera (XM510) kills PID 1 mid-erase and leaves the rootfs half-written #2647

Closed

Description

@widgetii

Summary

On an XM510 (mem=18M, 15.6 MB MemTotal), sysupgrade --rootfs from a running camera kills PID 1 in the middle of the rootfs erase. The kernel panics and reboots with the rootfs partition half-written, and the camera then boot-loops (VFS: Unable to mount root fs on unknown-block(31,3)). Without a UART it is bricked. Seen in 3 of 4 runs on a lab XM510 + JX-H62, with both the current majestic and the one from widgetii/majestic#1098.

What the console shows

With dmesg -n 8 and kernel.print-fatal-signals=1 set before the run:

SQUASHFS error: xz_dec_run error, data probably corrupt
SQUASHFS error: squashfs_read_data failed to read block 0x60
SQUASHFS error: Unable to read data cache entry [60]
SQUASHFS error: Unable to read page, block 60, size cedc        (x68 in all)
init/1: potentially unexpected fatal signal 7.
Pid: 1, comm:                 init
Kernel panic - not syncing: Attempted to kill init!
Rebooting in 20 seconds..
...
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,3)

Cause

The flash phase runs from the RAM root, but PID 1 (busybox init) keeps running from the old squashfs root through the whole flash. free_resources drops the page cache, and this camera has very little RAM left once /tmp holds the image and the RAM root is staged. So init's text pages are reclaimed, and the next time init runs (to reap something, for instance) it faults a page back in from the partition being erased. squashfs can't decompress it, init gets SIGBUS, and the kernel panics.

sysupgrade already describes this failure for a gk7201v200 (check_flash_ram, "processes still running from the old rootfs are not paged out while it is erased"). Its guard doesn't help here, for two reasons:

  1. usable_ram() reads only MemAvailable, which kernels before 3.14 don't provide (XM510 3.0.101, XM530 3.10.103, hi3516cv100 3.0.8, and others). It then reports "no opinion", so check_unpack_ram and check_flash_ram never run. The log of a failed run has no RAM left to flash from: line.
  2. Even with an estimate, the check measures free plus reclaimable memory, and init's own page cache counts as reclaimable. On the XM510 that estimate is about 8 MB, well above the 2048 KB floor, while the pages it counts are exactly the ones that must not be reclaimed.

Possible fix

Get PID 1 off the flash before writing the rootfs on NOR/squashfs layouts too. That is the hand-off sysupgrade already does for UBI layouts (need_handoff / check_handoff, busybox init ::restart:/sbin/init into the RAM root). With init running from RAM there is nothing left on the old root whose death panics the kernel. Dropbear or the majestic supervisor dying of SIGBUS mid-flash is harmless.

A MemAvailable fallback for pre-3.14 kernels (MemFree + Active(file) + Inactive(file) + SReclaimable, less watermarks, as si_mem_available() computes it) would make the existing checks run on those kernels too. Alone it doesn't fix this case.

Recovery used

U-Boot over UART: tftp 0x81000000 rootfs.squashfs.xm510; sf probe 0; sf erase 0x250000 0x500000; sf write 0x81000000 0x250000 ${filesize}, then a CRC32 read-back.

Activity

  1. widgetii commented on Oct 21, 2026

    @widgetii
    MemberAuthor

    Fixed by #2648: any rootfs write now hands PID 1 to the RAM root before the first write, where the image's inittab supports it. Nothing is left running from the partition being erased.

    On the lab XM510, sysupgrade -z -f --rootfs=... went from 3 panics in 4 runs to 3 clean runs in 3:

    • no SQUASHFS errors;
    • the rootfs partition byte-identical to the image;
    • no "Attempted to kill init!".

    #2649 then made archive installs work on the same board. It added the MemAvailable estimate for pre-3.14 kernels, so the RAM guards now run there too, raised the /tmp cap when RAM can back it, and added the early majestic stop. Five more installs from /tmp, on a freshly booted camera, all flashed cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions