RPi-Distro / pi-gen

Tool used to create the official Raspberry Pi OS images
BSD 3-Clause "New" or "Revised" License
2.52k stars 1.58k forks source link

If source directory has been bind-mounted, build breaks #770

Closed pevsonic closed 2 months ago

pevsonic commented 2 months ago

On my Debian 12 workstation, the main large drive /bigssd has various subdirectories (e.g. projects, home, opt ...) that get bind mounted from the disks mount to their actual mount points on the filesystem. This has an interesting side-effect that when pi-gen mounts subdirs under $ROOTFS_DIR, mount reports them twice, for example :

proc on /workdrive/projects/pi-gen/work/raspios/export-image/rootfs/proc type proc (rw,relatime)
proc on /mnt/bigssd/workdrive/projects/pi-gen/work/raspios/export-image/rootfs/proc type proc (rw,relatime)

This would be OK, except that when you umount one, both become unmounted. In scripts/common:unmount() this will cause an error.

I think that potentially calling umount -f might bypass this, but I think it would be better to construct the lists of directories to unmount more carefully instead.

pevsonic commented 2 months ago

Fixed this with a pleasingly minimal change here at : https://github.com/pevsonic/pi-gen/commit/2fe8d477436940abaee4f010a7e0df1b3654cd75

XECDesign commented 2 months ago

Thanks!

So I understand a bit better, could you please give an example output lines of 'mount' which demonstrate the situation where the problem would occur?

pevsonic commented 2 months ago

So I understand a bit better, could you please give an example output lines of 'mount' which demonstrate the situation where the problem would occur?

Sure!

So test scenario... on this machine, physical drive (bigssd) is mounted at /mnt/bigssd. It has a top level split of directories that get bind-mounted to their actual locations :

/home
/opt
/tftpboot
/workdrive
...

For example, fstab contains :

#
# Bind-mounts
#

/mnt/bigssd/home                    /home       auto    defaults,bind   0   0
/mnt/bigssd/opt                     /opt        auto    defaults,bind   0   0
/mnt/bigssd/workdrive                   /workdrive  auto    defaults,bind   0   0
/mnt/bigssd/tftpboot                    /tftpboot   auto    defaults,bind   0   0

I create a new test project under /workdrive/projects which is part of my usual workflow :

cd /workdrive/projects
git clone  -b arm64 https://github.com/RPi-Distro/pi-gen.git
cd pi-gen

At the time of writing, git log --oneline | head -1 gives me :

64e2057 Merge branch 'master' into arm64

I then modify scripts/common to add debug in :

unmount(){
    if [ -z "$1" ]; then
        DIR=$PWD
    else
        DIR=$1
    fi

    echo "-------------------------------------------------"
    echo "Scenario C: existing unmount() logic :"
    mount | grep "$DIR" | cut -f 3 -d ' ' | sort -r
    echo "-------------------------------------------------"

    echo "-------------------------------------------------"
    echo "Scenario D: new unmount() logic :"
    mount | grep " $DIR" | cut -f 3 -d ' ' | sort -r
    echo "-------------------------------------------------"

    while mount | grep -q "$DIR"; do
        local LOCS
        LOCS=$(mount | grep "$DIR" | cut -f 3 -d ' ' | sort -r)
        for loc in $LOCS; do
            umount "$loc"
        done
    done
}

And create a trivial config as per README.md and attempt to build :

echo "IMG_NAME='raspios'" > config
touch ./stage3/SKIP ./stage4/SKIP ./stage5/SKIP
touch ./stage4/SKIP_IMAGES ./stage5/SKIP_IMAGES
sudo ./build.sh

This then crashes out with a failure containing the debug I added showing what's going on :

...
[16:08:36] End /workdrive/projects/pi-gen/stage0/02-firmware/01-packages
[16:08:36] Begin /workdrive/projects/pi-gen/stage0/02-firmware/02-run.sh
[16:08:36] End /workdrive/projects/pi-gen/stage0/02-firmware/02-run.sh
[16:08:36] End /workdrive/projects/pi-gen/stage0/02-firmware
[16:08:36] Begin /workdrive/projects/pi-gen/stage0/files
[16:08:36] End /workdrive/projects/pi-gen/stage0/files
-------------------------------------------------
Scenario C: existing unmount() logic :
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/tmp
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/sys
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/run
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/proc
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/dev/pts
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/dev
/mnt/bigssd/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/tmp
/mnt/bigssd/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/sys
/mnt/bigssd/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/run
/mnt/bigssd/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/proc
/mnt/bigssd/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/dev/pts
/mnt/bigssd/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/dev
-------------------------------------------------
-------------------------------------------------
Scenario D: new unmount() logic :
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/tmp
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/sys
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/run
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/proc
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/dev/pts
/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/dev
-------------------------------------------------
umount: /mnt/bigssd/workdrive/projects/pi-gen/work/raspios/stage0/rootfs/tmp: not mounted.
pev@thinkpad:/workdrive/projects/pi-gen$ 
pevsonic commented 2 months ago

Fixed by d790fed832188d41c1fb5d8506d833d053e4a81c thanks!