How does WUBI handle partitions upon shutdown?

Alright, so, basically, I'm trying to boot up Gentoo in a manner similar to WUBI; I have an installation on an ext4-formatted loopback file, BURG installed under the Windows Bootloader, and the kernel/initramfs available for booting. The booting still has some issues (those I think I can work out, they're mostly because of small issues with the programs themselves) but I have the basic idea down:

  1. Set up busybox and get devices with mdev
  2. Parse command line options, determine if asking for real root or loop root
  3. If real root, mount it on /root and switch root, execute /sbin/init.
  4. If loop root, mount host partition on /host.
  5. Mount loopback (/host/${LOOP}) on /root
  6. Move the mountpoint of the host (mount -o move /host /root/host for busybox)
  7. Switch root to /root and execute /sbin/init

I've got the init script here:

#!/bin/sh

# Rescue shell in case of error.
rescue_shell() {
     echo "Something went wrong. Dropping you to a shell."
     exec /bin/sh
 }

parse_opt() {
        case "$1" in
                *\=*)
                        echo "$1" | cut -d= -f2-
                ;;
        esac
}

# Set up BusyBox...
busybox --install -s

# Mount the /proc and /sys filesystems.
mount -t proc none /proc
mount -t sysfs none /sys

# Populate /dev
echo ":: Populating /dev..."
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

# Get command line options...
for x in ${CMDLINE}
do
        case "${x}" in
                root\=*)
                        ROOT=`parse_opt "${x}"`
                ;;
                # Loadloop
                loop\=*)
                        LOOP=`parse_opt "${x}"`
                ;;
                ntfsroot)
                        NTFSROOT=1
  ;;
 esac
done


if [ "${NTFSROOT}" != 1 ]
then
 # Mount the root filesystem, plain and simple.
 echo ":: Mounting real root..."
 mount -o ro "${ROOT}" /mnt/root || rescue_shell
else
 # Load up an NTFS-based root.
 echo ":: NTFS Root mount requested. Mounting..."
 ntfs-3g "${ROOT}" /host

 if [ -f "/host/${LOOP}" ]
 then
  mount -o loop,ro  "/host/${LOOP}" /root || rescue_shell
  echo ":: Mounted. Moving host..."
  mount -o move /host /root/host || rescue_shell
  echo ":: Mounted."
 else
  "!! ERROR: Invalid/nonexistant loop given!"
  rescue_shell
 fi
fi

# Clean up.
umount /proc
umount /sys

# Boot the real thing.
echo ":: Switching to root and calling init..."
exec switch_root /root /sbin/init

Nothing complicated, really. NTFS-3G apparently doesn't agree with the busybox implementation of mount and stuff (It adds the parameter -i for some reason, and ntfs-3g craps out), so I'm considering just copying over the coreutils implementation or something. That, and I need to examine what's needed for mounting loopback partitions (it gives me an error like "File not found" when I try to mount the loopback manually). Still, I think these are easy enough to figure out on my own.

However, what I'm sort of wondering about is shutdown. Once the switch_root is completed, the system will be left with a / loopback-mounted file and /dev/sda2 (this is a Windows 7 install) on /host. Now, there is no way to unmount /host, as it is in use. However, one cannot unmount / while the root has filesystems mounted in a subdirectory. WUBI-based Ubuntu installations must face the same dilemma. How does one overcome this issue? It's a chicken and egg problem, and it's really annoying me.

I was considering something along the lines of a boot script that holds a temporary cache of files for a basic, basic root (like an initramfs, but the other way around). It would run last, copying the files over to a tmpfs, pivoting the root, perhaps having it back to the original layout of the initramfs. I'd essentially be doing this:

  1. Mount a tmpfs at /tmp/shutdown/ or something.
  2. Copy over the shutdown files (perhaps /usr/share/shutdown/ or something)
  3. pivot_root to move the root to /loop and chroot into the tmpfs.
  4. mount --move the /loop/host to /host
  5. Unmount /loop
  6. Unmount /host
  7. Shut down cleanly, since all partitions have been unmounted.

However, I've never modified Gentoo this much. Is this possible with an initscript? I don't want this to be overwritten by any updates to the baselayout or whatever ebuild, since that would leave me with broken shutdown functionality (and I really don't want to lose the host partition). There's also the problem of figuring out if Gentoo's init system even supports something like this. It seems clean enough (if a bit hackish), but I'm not too sure about it. I want to know if Ubuntu does it differently, and if so, how? Any suggestions would be helpful.

EDIT:

I got the boot working. Just a matter of using the coreutils version of mount, like I thought. I'm having the errors I expected upon shutdown, though; errors with being unable to unmount filesystems and journaling errors with the loopback FS. I've no idea how to fix this still.

EDIT 2:

Alright, well, I got something going that... Sort of works. I basically edited /etc/init.d/{halt.sh,reboot.sh,shutdown.sh} and did the following:

  • Added /host to the RC_NO_UMOUNTS variable, which stops the EXT4 module from choking up about a journaling error
  • Added -o `pidof ntfs-3g` to the opts for killall5 (to make sure it didn't kill ntfs-3g)
  • Modified the shutdown.sh and restart.sh to mount a tmpfs on /boot/shutdownfs and copy over some initramfs files there, pivot the root, then chroot into it, calling either /down or /restart.
  • These two scripts essentially do some quick and dirty /proc and /sys setup, move the /root/host to /host, then do lazy unmounting. I couldn't get regular unmounts to work (the filesystem would still be busy), but at least this appears to stop the filesystems from vomiting entirely.

This solution is still subpar, so any help would be appreciated.


Not an expert here, but after reading the umount manpage I see a flag specific to loop mounted devices:

-d     In case the unmounted device was a loop device, also free this loop device.

Also reading further into losetup (in manpages still), I would suggest you to maybe use it to debug as it can be used to see the status of loop mounted devices.

The link to the manpage I'm referring to is here. This option:

-a     Show status of all loop devices.

might give you a clue, and some other flags might help unmount the looped devices.

As I cannot replicate your situation I can only suggest to you ways to find your answer on your own, sorry that I cannot be of more help.