Save session by pivot_root for overlayfs
Yesterday, posted about problems with saving the session for overlayfs:
- Fix for shutdown using overlayfs — September 11, 2025
Which implemented saving at shutdown by an indirect method, where the session save is completed at next bootup.
However, I have figured out a direct save at shutdown, by pivot_root. What this involves is to pivot to a new filesystem, thus rendering the original overlay filesystem inoperable. Direct writes can then be done to the save-folders -- they are multiple, because the main desktop and containers each have their own save-folders, named ".session".
The sequence at shutdown is you choose poweroff or reboot from the menu on the main desktop. This runs scripts 'wmpoweroff' or 'wmreboot', which in turn call scripts 'poweroff' or 'reboot', which run /etc/rc.d/rc.shutdown and finally run 'busybox poweroff' or 'busybox reboot'. This may seem rather a lot of steps, but was worked out this way right back in the early Puppy days.
Latest change to rc.shutdown:
if [ "${EOS_LAYERFS}" == "aufs" ];then #20250911
/etc/rc.d/rw-merge 2>/dev/console
else #overlay...
#indirect method works, but trying pivot_root direct save...
#mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.session-transit
#/etc/rc.d/rw-merge '.session-transit'
##...initrd will complete saving the session (including containers).
exec /etc/rc.d/shutdown-pivot-root ${PARAM1}
#...will not return.
fi
...where $PARAM1 is "reboot" or "poweroff'. Here is shutdown-pivot-root:
#!/bin/ash
#20250911 called from rc.shutdown
#passed in "reboot" or "poweroff"
. /etc/rc.d/PUPSTATE
. /etc/DISTRO_SPECS
#EXE1="$(cat /tmp/wmexitmode.txt)" #poweroff or reboot
EXE1="${1}"
[ -z "${EXE1}" ] && EXE1=poweroff
[ -d /mnt/${WKG_DEV}/${WKG_DIR}.shutdown/rw1 ] && rm -rf /mnt/${WKG_DEV}/${WKG_DIR}.shutdown/rw1
[ -d /mnt/${WKG_DEV}/${WKG_DIR}.shutdown/wkg11 ] && rm -rf /mnt/${WKG_DEV}/${WKG_DIR}.shutdown/wkg1
mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.shutdown/rw1
mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.shutdown/ro1
mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.shutdown/wkg1
mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.shutdown/top1
cd /mnt/${WKG_DEV}/${WKG_DIR}.shutdown
busybox mount -t squashfs ../sfs/easyos/${DISTRO_BINARY_COMPAT}/${DISTRO_COMPAT_VERSION}/easy_${DISTRO_VERSION}_amd64.sfs ro1
busybox mount -t overlay -o xino=on,nfs_export=off,index=off,uuid=null,verity=off,redirect_dir=off,metacopy=off,lowerdir=ro1,upperdir=rw1,workdir=wkg1 overlay top1
#busybox mount -t aufs -o udba=none,br=rw1=rw:ro1=ro aufs top1
mkdir -p top1/old_root
cd top1
busybox pivot_root . old_root
if [ ! -e /old_root/etc/DISTRO_SPECS ];then
cd /
echo -e "\\033[1;31m" >/dev/console #red
echo "ERROR: unable to pivot_root" >/dev/console
echo "Fallback to indrect save (completed at next bootup)..." >/dev/console
echo -e "\\033[0;39m" >/dev/console #restore default color.
busybox umount top1 2>/dev/null
busybox umount ro1 2>/dev/null
sleep 0.5
mkdir -p /mnt/${WKG_DEV}/${WKG_DIR}.session-transit
/etc/rc.d/rw-merge '.session-transit'
else
#busybox mount -t proc proc /proc
#20250913 in rw-merge will write direct to ro layer of old overlayfs
# this will upset it, docs say cause "undefined behaviour" but it won't crash.
# the following line works, but just in case "undefined behaviour" causes changes
# on the rw layer, copy it instead of symlink...
#busybox ln -snf /old_root/mnt/.easy_rw /mnt/.easy_rw
busybox cp -a /old_root/mnt/.easy_rw /mnt/
busybox ln -snf /old_root/mnt/.easy_ro /mnt/.easy_ro
busybox mkdir -p /mnt
busybox ln -snf /old_root/mnt/${WKG_DEV} /mnt/${WKG_DEV}
busybox ln -snf /old_root/mnt/${WKG_DEV}/${WKG_DIR} /mnt/wkg
busybox cp -a -f /old_root/etc/rc.d/PUPSTATE /etc/rc.d/
busybox cp -a -f /old_root/etc/rc.d/rw-merge /etc/rc.d/
echo "Saving sessions (main desktop and containers)..." >/dev/console
/etc/rc.d/rw-merge >/dev/console 2>&1
fi
sync
busybox umount /mnt/${WKG_DEV} 2>/dev/null
if [ $? -ne 0 ];then
busybox umount -r /mnt/${WKG_DEV} 2>/dev/null
fi
busybox umount -ar > /dev/null 2>&1
#poweroff or reboot...
busybox ${EXE1}
###end###
...it works!
What it does is create another overlay filesystem, with easy.sfs
as the ro layer, then pivot_root into it. It is quite simple. I
put in some just-in-case code, fallback to indirect-save in case
the pivot_root fails. Note, 'pivot-root' is a busybox applet; it
is also in util-linux package, but I have kept the busybox one in
EasyOS.
Tags: easy