Ubuntu RAM-Linux その4:overlayfsで

URLにあるoverlayの実装は古く、そのままではうまくいかない。以下、aufs側のスクリプトをベースにoverlayfs向けに調整した。
[2018年1月]手元のホビーマシンではUbuntu17.10でも通用している。

#!/bin/sh
# ルート「/」をoverlayfsでマウントするinitrd向けスクリプトです。
# リブートすると、「/」は元の状態に戻ります。
#
# 【準備】
# 1. このスクリプトは、下記ファイルへ保存して下さい。
# /etc/initramfs-tools/scripts/init-bottom/rootoverlay
# また、実行権限を与えて下さい。
# chmod 0755 rootoverlay
#
# 2. initrdにoverlayモジュールを入れる指示をします。
# echo overlay >> /etc/initramfs-tools/modules
#
# 3. initrdを更新して下さい。
# update-initramfs -u
#
# 4. grub.cfgを更新して下さい。
# vi /boot/grub/grub.cfg
# overlay=tmpfs をエントリに追加して下さい。
# do not add this line to single user mode.
# boot to single user mode in order to install software. 
# または、/etc/grub.d/ にoverlayfs用のエントリを作成し、
# update-grubを実行して下さい。

case $1 in
prereqs)
    exit 0
    ;;
esac

#export overlay
for x in $(cat /proc/cmdline); do 
    case $x in 
    root=*)
        ROOTNAME=${x#root=}
        ;;
    overlay=*)
        overlay=${x#overlay=}
        case $overlay in
        tmpfs-debug)
            overlay=tmpfs
            overlaydebug=1
            ;;
        esac    
        ;;
    esac
done

if [ "$overlay" != "tmpfs" ]; then
    #not set in boot loader 
    #I'm not loved. good bye
    exit 0
fi

echo 
echo "       root-overlay:  Setting up overlay on ${rootmnt} as root file system "
echo 

modprobe -q --use-blacklist overlay
if [ $? -ne 0 ]; then
    echo    root-overlay error:      Failed to load overlay.ko
    exit 0
fi

#make the mount points on the init root file system
mkdir /overlay /rw /ro

# mount the temp file system and move real root out of the way
mount -t tmpfs tmpfs /rw

# リアルルート(/root)を/roへ移動する。
# (/rootには/dev/sda1などがマウントされているはず。)
mount --move ${rootmnt} /ro 
if [ $? -ne 0 ]; then
    echo    root-overlay error:    ${rootmnt}  failed to move to /ro
    exit 0
fi

# overlay向けにupperdirとworkdirに分ける。overlayではworkdirが必要。
mkdir /rw/rw
mkdir /rw/wk

# リアルルート(/ro)とtmpfs(/rw)を重ね、/overlayにマウントする。
mount -t overlay overlay -o lowerdir=/ro,upperdir=/rw/rw,workdir=/rw/wk /overlay
if [ $? -ne 0 ]; then
    echo    root-overlay error:      Failed to mount /overlay files system
    exit 0
fi

# test for mount points on overlay file system
[  -d /overlay/ro ] || mkdir /overlay/ro

# リアルルートが隠れないよう、/overlay/roに移動する。 
mount --move /ro /overlay/ro
if [ $? -ne 0 ]; then
    echo    root-overlay error:      Failed to move /ro /overlay/ro 
    exit 0
fi

#*********** fix fstab on tmpfs ******************
# test for /dev/sdx 
# this is not on the real file system.  This is created on the tmpfs each time the system boots.
# The init process will try to mount the root filesystem listed in fstab. / and swap must be removed.  
# the root file system must be mounted on /ro not on /

if [ "0$overlaydebug" -eq 1 ]; then
    echo  "   root-overlay debug:    Remove the root file system and swap from fstab "
    echo 
    echo 
    echo  "         ROOTNAME $ROOTNAME "
    echo  "         resume   $resume   "
    echo 
    echo  '     BlaYO pointed out that grep can be used to quickly remove '
    echo  '      the root file system from fstab. '
    echo 
    echo  '     Thank you BlaYO for the debug info.'
    echo

fi
# old code
# I'm sure that sed can do this in one step but I want to correct on the rootname  not matching the root in fstab.
#cat /overlay/ro/etc/fstab|sed -e s/$ROOTNAME/\#$ROOTNAME/ -e s/$resume/\#$resume/ >/overlay/etc/fstab  

# /etc/fstab_overlayをあらかじめ準備している場合は、そちらを利用する。
if [ -f /overlay/ro/etc/fstab_overlay ]; then
    cp -f /overlay/ro/etc/fstab_overlay /overlay/etc/fstab
else
    #Add the comment block to fstab
    cat <<EOF >/overlay/etc/fstab
#
#   Rootoverlay has mounted the root file system in ram
#
#  This fstab is in ram and the real fstab can be found /ro/etc/fstab
#  the root file system ' / ' has been removed.
#  All Swap files have been removed. 
#

EOF

    #remove root and swap from fstab
    cat /overlay/ro/etc/fstab|grep -v ' / ' | grep -v swap >>/overlay/etc/fstab  
    if [ $? -ne 0 ]; then
        echo    root-overlay error:      Failed to create /overlay/etc/fstab 
        #exit 0
    fi
fi

# add the read only file system to fstab
#ROOTTYPE=$(/lib/udev/vol_id -t ${ROOT})
ROOTTYPE=$(cat /proc/mounts|grep ${ROOT}|cut -d' ' -f3)
ROOTOPTIONS=$(cat /proc/mounts|grep ${ROOT}|cut -d' ' -f4)
echo ${ROOT} /ro $ROOTTYPE $ROOTOPTIONS 0 0 >>/overlay/etc/fstab

# S22mount on debian systems is not mounting  /ro correctly after boot
# add to rc.local to correct what you see from df
#replace last case of exit with #exit
cat /overlay/ro/etc/rc.local|sed 's/\(.*\)exit/\1\#exit/' >/overlay/etc/rc.local  
echo mount -f  /ro >>/overlay/etc/rc.local 

# add back the root file system. mtab seems to be created by one of the init proceses. 
# 不要と思われコメントアウトした。
#echo "echo overlay / overlay lowerdir=/ro,upperdir=/rw/rw,workdir=/rw/wk 0 0 >>/etc/mtab" >>/overlay/etc/rc.local
#echo "echo tmpfs /rw tmpfs rw 0 0 >>/etc/mtab" >>/overlay/etc/rc.local 
#echo exit 0 >>/overlay/etc/rc.local 

#  Copyright 2008 Joaqu&#237;n I. Bogado Garc&#237;a
#fix para apparmor, se desactiva y listo ( From the lethe project. )
[ -e /scripts/init-bottom/_apparmor ] && rm /scripts/init-bottom/_apparmor
[ -e /overlay/etc/init.d/apparmor ] && rm /overlay/etc/init.d/apparmor

# リマウントコマンドは不要なのでコメントアウトする。
#build remountrw
#echo \#!/bin/sh >/overlay/bin/remountrw
#echo mount -o remount,rw ${ROOT} >>/overlay/bin/remountrw
#chmod 0700 /overlay/bin/remountrw

#build remountro
#echo \#!/bin/sh >/overlay/bin/remountro
#echo mount -o remount,ro ${ROOT} >>/overlay/bin/remountro
#chmod 0700 /overlay/bin/remountro

# This should drop to a shell. (rewrite)
if [ "0$overlaydebug" -eq 1 ]; then
    echo
    echo "   root-overlay debug:    mount --move /overlay ${rootmnt} "
    echo 
    echo '   root-overlay debug:   init will stop here.   '
    echo  
    exit 0
fi

# overlayで重ねたユーザランドをリアルルート(/root)に戻しておく。
# (init最後のrun-initでリアルルートにchrootされるので/roや/rwは隠蔽される。)
mount --move /overlay ${rootmnt}

exit 0