Orange pi R1のSPIフラッシュにOSのせるためにrootfsを圧縮ファイルシステムのsquashfsにした上で書き込みできるようにoverlayfsを使うつもりだったが、
難しくて断念して/etcと/homeだけ書き換えできるようにした。
まずrootfsをoverlayfsにするつもりだったが、
overlayfsは2つ以上のディレクトリを重ねるシステムなので、片方にリードオンリーなsquashfsを使って書き換えできるようにするには2つのファイルシステムを先にマウントする必要がある。
なのでkernel起動パラメータroot=の部分で指定することはできない。
squashfsで起動したあとでoverlayfsをマウントして/を変更する手段として、chroot pivot_root switch_rootを考えたが、
chroot : 現在のプロセスのみ/を変更する。
pivot_root : 元の/には別のファイルシステムがマウントされていてはいけない。元の/と新/は別のファイルシステムでなければいけない。
switch_root : 元の/にあるファイルは全削除される。
らしい。
システム全体を変更したいのでchrootはナシ。
switch_rootは、元の/のファイルが削除されるというのはなんでだろ?マウントポイントがなくなるだけではないの?initramfsで使われることが多いみたいだが一時的なramディスクでないと問題あり?
pivot_rootはなんか制約が多い。新/が別のファイルシステムだと/の下にマウントしなきゃいけないから2つのファイルシステムは必ず存在することになるのでわかりにくい。
まあとりあえず実際にpivot_rootとかswitch_rootを試してみようかと思ったが、起動中のシステムでやろうとしてもエラーでうまく行かなかった。
initrdとinitramfsも試そうとしたが、どうもkernelパラメータからroot=を外すとkernel panicしちゃうんでなにか間違えてる・・・
miZyとかopenWRTは/がoverlayfsだったりするので方法はあるはずだが・・・
というわけでうまく行かなかったのだが、
書き換えが必要なのは /etc と /home だけだよね。
そこをどうにかしようと考えて、rwなパーティションを/mnt/rwにマウントして、その下のディレクトリを/etcと/homeにマウントすることにした。
ディレクトリ作ったりしてる作業中に、rootfsの/etcをrw/etcに全コピーしてして/etcを消すときに気づいたが、
linux起動時は/sbin/initが実行されて、/etc/inittabが処理され、/etc/fstabに記載されたデバイスがマウントされる。
/etc/inittabが別デバイス上じゃ読めないじゃん!
ということで再度悩んだが、
kernel起動パラメータのinit=で/sbin/init以外を指定すればinitプログラムを代えることができる!
と気づいた。
/init.sh
#!/bin/sh
/bin/mount -t proc proc /proc
/bin/mount /dev/mmcblk0p3 /mnt/rw
/bin/mount -o bind /mnt/rw/etc /etc
/bin/mount -o bind /mnt/rw/home /home
exec /sbin/init
kernel起動パラメータで最初に実行するinit。
rwデバイスをマウントして、下にあるetcとhomeを/etcと/homeにbindする。
最初procをマウントしなかったらデバイスのmountができなかった。
マウントしたら本来の/sbin/initを実行。
/etc/inittab (の起動処理の部分)
# Startup the system
::sysinit:/bin/mount -t proc proc /proc
::sysinit:/bin/mount -o remount,rw /
::sysinit:/bin/mkdir -p /dev/pts /dev/shm
::sysinit:/bin/mount -a
#::sysinit:/sbin/swapon -a
rootfsの/etcは空にしてるんでrwデバイス側。先に/init.shでbindされるんで/etc/inittabとして扱える。
procのマウントは/init.sh側に移したのでコメントアウト。
メモリは256MBも積んでるがストレージ(SPIフラッシュ)は16MBしかないのでswap要らん。というわけでkernelビルド時に無効にしてるんでswaponもコメントアウトしといた。
/dev/ptsと/dev/shmは最初からあるからmkdirする必要あるのか?思って一旦コメントアウトしたが、/devにdevtmpfsがkernelにマウントされるから無くなるんだね。mkdirしないとエラー出た。
mkdirするには/をrwでremountする必要があるってことみたい。
/etc/fstab
# <file system> <mount pt> <type> <options> <dump> <pass>
/dev/root / ext2 rw,noauto 0 1
proc /proc proc defaults 0 0
devpts /dev/pts devpts defaults,gid=5,mode=620,ptmxmode=0666 0 0
tmpfs /dev/shm tmpfs mode=0777 0 0
tmpfs /tmp tmpfs mode=1777 0 0
tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
sysfs /sys sysfs defaults 0 0
/dev/mmcblk0p3 /mnt/rw ext2 rw,noauto 0 0
これもrwデバイス側。
/mnt/rwは手動マウントするんで追加しなくても起動するが、シャットダウン時に自動アンマウントさせるためにnoautoで追加しといた。
これでumountしてくれる?
こんな感じで、/をsquashfsにした上で/etcの変更ができるシステムができた。
# df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/root 6016 6016 0 100% /
devtmpfs 116652 0 116652 0% /dev
/dev/mmcblk0p3 9911 920 8479 10% /mnt/rw
/dev/mmcblk0p3 9911 920 8479 10% /etc
/dev/mmcblk0p3 9911 920 8479 10% /home
tmpfs 125356 0 125356 0% /dev/shm
tmpfs 125356 28 125328 0% /tmp
tmpfs 125356 24 125332 0% /run
/は6MBになった。
他にboot用のパーティションがzImageとかで頑張っても4MBまでしか削れない。
余裕もたせてboot=6MB,root=8MBで残り2MBくらいか?
と思ったが、どうせ書き込み用のイメージ化しなきゃいけないんだし最適化するスクリプトでも作るか。
そうすると10MBくらいに収まるんで残りのrwは6MBくらい使えるか?