Skip to content

sysupgrade: unmount the old root and add a ubi-aware write path so ubifs devices can be upgraded #2253

Description

@widgetii

Follow-up to #239, which asked for pivot_root + chroot in sysupgrade so that ubifs devices could be updated. The mechanism landed in #2252; the ubifs half did not. Splitting the remainder out so it is stated precisely rather than sitting inside a four-year-old issue that is now mostly done.

What #2252 already gives you

enter_ramfs stages busybox, its loader and libraries and the script into a tmpfs, moves /dev, /proc and /tmp across, then pivot_root + chroot + re-exec. After that, nothing the flash phase runs depends on the old rootfs — which is the hard prerequisite for touching the volume it lives on.

Verified on gk7205v200 (34 MB, musl) and hi3516av300 (754 MB, glibc): after the pivot / is tmpfs, busybox is on tmpfs, and every tool the flash phase uses resolves and runs with the page cache dropped.

What is still missing

1. The old root is deliberately still mounted. enter_ramfs leaves it at /mnt on purpose — the MTD partitions are reached through /dev, so nothing needed it unmounted, and keeping it costs nothing today. For ubifs it is the whole problem: you cannot rewrite a mounted volume.

2. There is no ubi-aware write path. do_update_rootfs is flashcp -v $image $(get_device rootfs), which writes an MTD partition raw. A ubifs volume needs ubiupdatevol (or detach → ubiformat/ubiattachubimkvol), not a raw partition write.

3. Nothing detects a ubifs rootfs. get_system_info records flash_type as nor/nand via ipcinfo -F, and root_on_flash from /proc/cmdline, but nothing distinguishes root=ubi0:rootfs from a squashfs-on-MTD root and routes to a different writer.

The part that needs a decision, not just code

pivot_root moves the mount namespace, but other processes keep their mappings on the old rootfs. dropbear, and under --web majestic, are still executing from it, so a plain umount /mnt will return EBUSY.

That collides head-on with a property #2252 relies on: --web deliberately keeps majestic alive so it can go on streaming the upgrade log over /ws/upgrade (its tail fd and the websocket survive the pivot, since moving a mount does not disturb open fds). Unmounting the old root means killing it, and with it the user's only view of the flash.

Options, roughly:

  • umount -l /mnt (lazy) — detaches the tree so ubi operations can proceed while existing mappings drain. Least disruptive; needs checking that it actually frees the ubi volume rather than just hiding the mount.
  • Kill everything holding the old root before unmounting, and accept that the WebUI log stops at that point (the browser already handles the socket closing).
  • Only unmount on the ubifs path, leaving the MTD path exactly as it is now.

The third is probably the right default: it keeps a working, tested path working, and confines the risk to devices that cannot be upgraded at all today.

Grounding

  • busybox already ships the tooling: CONFIG_UBIATTACH, UBIDETACH, UBIMKVOL, UBIRMVOL, UBIUPDATEVOL, UBIRENAME are all =y in general/package/busybox/busybox.config. (They are not enabled in busybox-initramfs.config.) There is no mtd-utils package in the tree.
  • No in-tree board currently boots root=ubi — the only occurrence of that string is sysupgrade's own comment. So this is enabling work for NAND/ubifs devices rather than a fix for a broken flow anyone is hitting today, which is worth weighing against the risk of touching the flash path again.
  • NAND is presently approximated: download_firmware warns "the updater uses the NOR package for updating NAND" and proceeds.

Testing note

The offline suite (.github/scripts/test_sysupgrade.sh, 82 checks) cannot exercise a real pivot or real mounts — it runs unprivileged, and its pivot_root stub fails by default so that every existing case exercises the in-place fallback. Anything added here will need the same treatment: source invariants plus a real board. A ubifs change in particular cannot be validated on the NOR cameras used for #2252.

Refs #239, #2252.

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