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/ubiattach → ubimkvol), 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.
Follow-up to #239, which asked for
pivot_root+chrootinsysupgradeso 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_ramfsstages busybox, its loader and libraries and the script into a tmpfs, moves/dev,/procand/tmpacross, thenpivot_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_ramfsleaves it at/mnton 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_rootfsisflashcp -v $image $(get_device rootfs), which writes an MTD partition raw. A ubifs volume needsubiupdatevol(or detach →ubiformat/ubiattach→ubimkvol), not a raw partition write.3. Nothing detects a ubifs rootfs.
get_system_inforecordsflash_typeas nor/nand viaipcinfo -F, androot_on_flashfrom/proc/cmdline, but nothing distinguishesroot=ubi0:rootfsfrom a squashfs-on-MTD root and routes to a different writer.The part that needs a decision, not just code
pivot_rootmoves the mount namespace, but other processes keep their mappings on the old rootfs. dropbear, and under--webmajestic, are still executing from it, so a plainumount /mntwill return EBUSY.That collides head-on with a property #2252 relies on:
--webdeliberately keeps majestic alive so it can go on streaming the upgrade log over/ws/upgrade(itstailfd 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.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
CONFIG_UBIATTACH,UBIDETACH,UBIMKVOL,UBIRMVOL,UBIUPDATEVOL,UBIRENAMEare all=yingeneral/package/busybox/busybox.config. (They are not enabled inbusybox-initramfs.config.) There is nomtd-utilspackage in the tree.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.download_firmwarewarns "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 itspivot_rootstub 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.