Clean up part2disk loop mappings#136
Open
SeanMooney wants to merge 5 commits into
Open
Conversation
The CirrOS build system has historically required a bare Ubuntu 22.04
host with a specific set of system packages installed via system-setup.
This makes it difficult to build CirrOS reproducibly on modern
workstations or in CI environments running a different host OS.
This change introduces a Docker-based build environment that encapsulates
all build dependencies in an ubuntu:22.04 image while preserving the
existing native build-release contract.
Dockerfile installs all packages from bin/system-setup plus the implicit
dependencies (binutils, cpio, kmod, sudo) and the CI extras
(qemu-system-*, cloud-utils, openbios-ppc) in a single layer. It also
sets USER=root so the existing `sudo chown -R $USER:$USER` ownership
handoff remains valid when bin/build-release runs inside the container.
It pre-creates /dev/loop0-7 nodes and declares /cirros/download and
/cirros/ccache as volumes so that build caches persist across runs.
docker-entrypoint.sh validates that the cirros source tree is bind-mounted
at /cirros, loads the loop kernel module (required for bin/bundle's
loopback mounts), and delegates to bin/build-release. The ARCHES
environment variable can be set to limit the build to a subset of
architectures, e.g. ARCHES=x86_64.
bin/build-release also updates the Buildroot download URL from the
defunct buildroot.uclibc.org domain to buildroot.org, which now hosts the
official release archives. The existing sudo-based bundle and chown steps
are intentionally left unchanged so native and GitHub Actions builds keep
working as before.
To build an x86_64 image:
docker build -t cirros-builder .
docker run --privileged --rm \
-e ARCHES=x86_64 \
-v "$PWD":/cirros \
-v cirros-dl:/cirros/download \
-v cirros-ccache:/cirros/ccache \
cirros-builder daily
The --privileged flag is required because bin/bundle mounts a loopback
partition image during the disk image assembly stage.
Assisted-By: pi claude-sonnet-4-6
Signed-off-by: Sean Mooney <work@seanmooney.info>
CirrOS currently ships a bootable qcow2 image with a mostly empty root filesystem partition. On first boot the initramfs detects that the labeled rootfs partition does not contain /sbin/init, mounts it read-write, and copies the initramfs contents into the partition before switching root. If that first boot is interrupted, the partition can be left only partly populated. A later boot may then find /sbin/init and switch into the partition, but fail when a required shared library or file was never copied. That presents as PID 1 exiting, followed by a kernel panic. Keep the traditional minimal qcow2 image for compatibility, but rename it from the old .img suffix to -minimal.qcow2 so its format is explicit. Add a second -full.qcow2 image whose root filesystem is pre-populated at build time from the assembled filesys tarball. The full initramfs is still copied into /boot so that the early boot environment has the kernel modules required to find and mount the root device. This removes the first-boot rootfs copy window for users that choose the full image while preserving the existing minimal image and initramfs fallback behavior. Assisted-By: pi claude-sonnet-4-6 Signed-off-by: Sean Mooney <work@seanmooney.info>
CirrOS root filesystem partition images are currently formatted as ext3. The previous change makes the partition hold the real root filesystem at build time, so use ext4 for that filesystem to get the newer ext4 layout and metadata handling while keeping compatibility with the existing resize2fs-based grow path. The initramfs mounts the root device by label without forcing a filesystem type, so no initramfs change is needed. The generated x86_64 image was also boot-tested under QEMU to confirm GRUB can load the kernel and initramfs from the ext4 partition and the system reaches the CirrOS login prompt. Tested with an x86_64 Docker build and a QEMU boot smoke test. The image boots to the CirrOS login prompt, mounts /dev/vda1 as the root filesystem, and does not copy the initramfs to the rootfs partition at boot. Assisted-By: pi claude-sonnet-4-6 Signed-off-by: Sean Mooney <work@seanmooney.info>
CirrOS has several focused docs and many small shell scripts that explain parts of the build, boot, test, and release workflow, but contributors currently need to reconstruct the full picture from scattered sources. That makes it harder to understand how Buildroot output, the CirrOS filesystem overlay, downloaded kernels, grub payloads, image bundling, runtime scripts, datasources, and release artifacts fit together. Add a CirrOS From Scratch developer guide as the primary contributor manual. The guide provides a read-first path, Buildroot primer, staged build walkthrough, filesystem and boot/runtime flow, runtime script and datasource reference, image assembly notes, architecture support details, testing and CI guidance, maintenance workflows, and troubleshooting appendices. Fold durable context from the older docs into the new guide while keeping stale commands clearly caveated. The guide maps existing docs, documents current release artifact names and semantics, describes manual release-test categories, records maintainer-only publishing context, and calls out stale examples that should not be copied blindly. Docker build support is intentionally left out of scope because it is still WIP, and riscv64 is described as experimental until maintainers decide otherwise. Assisted-By: pi gpt-5.5 Signed-off-by: Sean Mooney <work@seanmooney.info>
078101b to
1f75f60
Compare
part2disk can leave loop and device-mapper state behind after wrapping a partition image. In practice the caller may then remove the temporary raw disk image, leaving loop devices attached to deleted files and loopNp* mapper entries behind. Track the loop device returned by kpartx, unmount only paths that are still mounted, remove mapper entries by loop device, detach the loop device, and remove the temporary directory during cleanup. This makes normal exit and failure cleanup use the same guarded path. Signed-off-by: Sean Mooney <work@seanmooney.info> Generated-By: pi gpt-5.5
1f75f60 to
aca524f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
bin/part2diskcleanup guard mounted paths instead of unconditionally unmounting themkpartxand remove its device-mapper mappings on exitTesting
BOOTTEST=truepart2diskdirectly inside the Docker build container after this change and confirmed loop0-loop6 were free afterward, with no staleloopNp*mapper entries