できれば / を SD に移行したほうが全体の構造としてはシンプルだ。 /home だけ ... などという中途半端なことをすると、元の dirty な構造も生き残ってしまう。 とはいえ、SD ドライバが module として提供されているために / 自身の移行は容易なことではない。
SD ドライバが module になっている以上、どうしても最初は cramfs 上に / が置かれる。 boot 時の / と実使用時の / を変えるのは ext-root-mini-HOWTO にあるように initrd を使うのが普通だし、SL-A300 の boot loader も initrd を扱えるようだが、 initrd.bin (cramfs) とは排他に見えるし、そもそも RAM を無駄使いする initrd は使いたくない(笑)。
ディレクトリの構成を触るなら /root/etc/rc.d/rc.rofilesys が中心になる。 ... と思って油断すると mount -a -t nonfs するときに参照する /etc/fstab (/home/etc/fstab) を直すのを忘れる。つーか、忘れた(泣)。
SD 移行するといっても /tmp, /var など書き変え頻度が高いものは SD に置きたくないし、
/var は出来ればリセットを跨いで保護したい。
もしかするとリセットを押さなければならなくなった理由の一端が /var/log/ に残っているかもしれないからだ。
あんまり役に立ったことないけど ...
ということで、こんな感じ:
/dev/mtdblock0 / cramfs ro 1 1 /dev/mtdblock1 /var ext2 defaults 0 2 /dev/mmcda2 /home ext2 defaults 0 3 /dev/shm /tmp tmpfs defaults 0 0 none /proc proc defaults none /dev/pts devpts gid=5,mode=620 0 0 /dev/hda1 /mnt/cf auto noauto,owner 0 0 /dev/mmcda1 /mnt/card auto noauto,owner 0 0
このままだと writable disk に置かなければならない /etc, /dev が cramfs に残る。 それぞれ /home/etc, /var/dev から bind にしてある。
# mount -o bind /var/dev /dev # mount -o bind /home/etc /etc"mount -o bind " は obsolete で、"mount --bind " と書くべきだが、 busybox ではまだ前者の構文が使われている。 古い構文にしても bind mount がちゃんと busybox で使えることが実は驚きだったり。
ディレクトリの差し替えにはふつー symlink を使うのだろうが、
これだと symlink 先を変えたい時に symlink を書き換える必要がある。
Read only device からの link は変えられない。
このため SL-A300 では symlink を ROMの中 → RAM の中 → ターゲットと 2 hop させ、
中間の link を置き換えたり、あるいは mount で link を潰したりして書き換えている。
同じことが mount --bind (mount -o bind) によっても出来る。
こちらは read only だろうとなんだろうとおかまいなしであり、
0 hop で出来る。
ならばいっそ /mnt/card を / に bind してしまえ ── という考え方もないでもないし、
実は出来るんだが、
「bind する時に潰されるディレクトリを使っていたアプリはそのままもとのディレクトリを使う」
という当然の仕様により、そのまんま全てのプログラムが旧 / を参照し続ける。ということで没になった。
ぶっちゃけて言えば、symlink がとびかうと cd の挙動や ls の表示が dirty になるのが嫌だ。 mount --bind の場合、かわりに /proc/mounts が少々 dirty になる。 あんまり見にいかないし、それなら許せる。本質的にはそういうことだ。
root 以外の uid で使うことを考え、もちろん writable disk の上に置くが、 そのために device を一つ用意するのは美しくない。 かといって /dev を symlink にすることはできない。 boot 時に /dev/* が存在していなければならないから。symlink で 2 hop 飛ばしてもいいのだが、 /var/dev に dev/* を置いて /dev へ bind した。このほうが綺麗。
... ていうか、SL-A300 が元々やってたように /dev に空の /dev/ram を mount して、 それから tar xf .dev_default.tar して device file を作るってこええよ。 tar が途中でコケたら device file ボロボロの状態で止まるんかい。 /dev の移行は atomic 操作にしてくれ。
再起動やリセットで /dev/mtdblock1 を正しく再利用するためには 再起動やリセット前に /dev/mtdblock1 を umount するか、少なくとも mount -o ro,remount しなければならないが、いまんとこそんなことはしていない。 ソフトリセットすると e2fsck が大量に文句言うのが見える :-)
/var の中に置いてないのは、/var が今や 2MB しかないからだ。 gcc は /tmp に大きな中間ファイルを置く。必要とあれば大きな領域となり、普段は小さい領域としたいのなら、 /dev/shm 以外に選択肢はない。
というわけで、実体を /mnt 自身とし、念のため /usr/mnt.rom は /mnt への symlink とした。
ところが、その直後 rc.sysinit 中で mount -a -t nonfs していて、 /etc/fstab にはちゃんと /home などのエントリも書かれているため、 /home などは二重に mount してしまっている。
rc.roflesys 内だけいじってディレクトリを構成したら、 /etc/fstab 由来のディレクトリで上書きされて /dev や /var の中身が消え、 /sbin/init がお亡くなりになってしまっていた ...
/home 等 rc.rofilesys 中で構成してしまうディレクトリの項は /etc/fstab ではコメントアウトすべきだろう。
で。SD カードを外した状態での boot と入れた状態での boot でシステムの構造が切り替わるようにしておく。 SD カードを外した状態での boot したときには、nfs と konsole が使えるくらいでいい。 そういう意味では、すぐに作れるようなシステムだが、 /home を SD に移した本来のシステムとの絡みで様相がかなり変わる。
/dev/mtdblock0 / cramfs ro 1 1 /dev/mtdblock1 /var ext2 defaults 0 2 /dev/shm /home ext2 defaults 0 3 none /proc proc defaults none /dev/pts devpts gid=5,mode=620 0 0 /dev/hda1 /mnt/cf auto noauto,owner 0 0 /dev/mmcda1 /mnt/card auto noauto,owner 0 0
/var を両者で共有し、SD が無い場合には /home を /dev/shm で構成している。 可変サイズ ramdisk が使えるのに /dev/ram 使う意味はない。 リセットの前後で保存する必要もない。どーせ rescue disk 扱いである。
/etc, /dev は上と同じく /var, /home の下に bind してある他、/tmp も /home/tmp に bind した。
Install したさい、pkg の install 先を「本体」に選ぶと install 先は /home 下になる。 定義によって SL-A300 は /home 下しか書き込めないことになっているからだ。 /home ごと切替えるならちゃんと整合するわけである。
のような形になる。2.4.18 くらいになると/dev/mtdblock1 on /var type ext2 (rw,sync) /dev/mtdblock1 on /dev type ext2 (rw,sync)
となって、デバイスでなくディレクトリ間の関係であることが明示されるのだけど。/tmp/A on /tmp/B type none (rw,bind)
このため、sysinfo の storage のページで /dev/mtdblock1 について 2 度 report するようになる。 この重複レポート対策で 1 行パッチ。
システム起動中のめんどうみてんのに、メッセージが読めないのはひどいってんで両者とも外した kernel (and system) を使っているが ... 標準では SL-A300 ってば、すげー寡黙だ。 標準では最下行に出る 2 行分くらいの文章しか読めないわけだが、 実は CONFIG_COTULLA_LOGO_SCREEN を外しても読める文はその 2 行だけである (笑)。 kernel も init もほとんど何のレポートもしてくれない。 fbcon の初期化が遅いこともあるのだろうが、それだけでは説明がつかんのだよな ...
Qt/Embedded のほうも、Startup_screen.bmp がない場合、 では何をするかというと白一色の「絵」をはりつける(笑)。 わりと早めに segmentation fault などでとらぶってる場合にのみ、メッセージが見える。 もちろん見えても ^C や ^S できるわけじゃないので 高速スクロールするエラーメッセージを指くわえて眺めてるだけだけど。
HOME キーとか CANCEL キーを ^C, ^S, ^Q あたりに bind しておくというようなことをしてくれてもバチはあたらんと思うのだがな ... fsck でとらぶった時に y/n 訊いてくるのに、いまのままではそれに答えることすらできん。
やー、さすがに広いわ ...。43MB の空きメモリ。ユーザーエリアは上から /var, /home, /mnt/card. /var に 2MB も要らんなとは思いつつ。
62MB 化するときは 15日の実験とは違い、mm.c のほうもいじった。 /dev/mtdblock1 の領域だけを 0xf9000000 にはりつけるようにしている。
前者がないと SD 経由の kernel/intird.bin upgrade が出来ないし、 後者がないと /home を移す気しない。... 2 枚カード使えばすむ話ではあるが、 入れ換えも手間だし、といちおう言ってみる。
なお、partiton を切っても kernel/initrd.bin の upgrade は正しく動いた。 /dev/mmcda1 を参照してるのか VFAT partition を参照してるのかは知らないけど (こういう時、おおむね最初の FAT partition を参照するらしいが、SL-A300 がどうかまでは確認してない)。