9legacyは「ベル研Plan 9最終版からのパッチ集」という位置付けです。更新がある場合、基本的には新しいパッチが追加されていきますが、パッチにバグがあった場合などはパッチ自体が更新されることもあります。そのため、手元の環境にパッチを適用したあと、次の更新を手元に適用するためには、過去に適用したパッチを元に戻してから再適用するなどの仕草が必要です。そのため現在は、直接パッチを手元の環境に適用するのではなく、9legacyが配布しているCDイメージを使って replica/pull する方法が推奨されています。
とはいえ自分自身でもPlan 9に手を入れているので、replica/pull で書き戻ってしまうと都合が悪いなどの事情があって、今はGitで差分を管理しています。この記事では、そのための手順をまとめます。
前提
事前に、以下2つのQEMUディスクイメージを用意しておきます。
- disk0.raw
- ベル研Plan 9を9legacyの安定版にアップデートするで最新の状態にアップデートしたディスクイメージ
- 以下ではvirtioが有効な状態で説明しているが、なくても良い
- disk1.raw
- ベル研の最終版をインストールした直後のディスクイメージ
- インストーラの configfs では fossil を選ぶ
disk1.raw はベル研Plan 9を9legacyの安定版にアップデートするで、
インストールが終わったら、あとで使うためにインストール直後のdisk0.rawをバックアップしておきましょう。ここでは disk0-orig.raw とします。
と書いているところでバックアップしたディスクイメージです。この記事では説明の都合上 disk1.raw と呼称します。このディスクイメージは何度もインストール直後へ戻すことになるので、バックアップは残しておきましょう。
必要なツールのインストール
disk0.raw で起動して、Gitをインストールします。
$ ./start.bash -v qemu-system-x86_64 -m 1G -smp 2 \ -device virtio-scsi-pci,id=scsi \ -device scsi-hd,drive=hd0 \ -drive file=disk0.raw,format=raw,cache=writethrough,id=hd0,if=none,index=0 \ -device virtio-net-pci,netdev=ether0 \ -netdev user,id=ether0,net=10.0.2.0/24 \ -machine type=pc,accel=hvf
386環境で使えるGitのバイナリは以下からダウンロードできるので、$home/bin/386 以下などに展開しておきましょう。
- lufia.org/git-386.tgz
また、パッチの管理を簡単にするため、9legacy-toolもインストールしておくと便利だと思います。
9legacyの差分をGitリポジトリに書き出す
準備ができたら、disk0.raw と disk1.raw を接続した状態で仮想マシンを起動します。
$ ./start.bash -v -a disk1.raw qemu-system-x86_64 -m 1G -smp 2 \ -device virtio-scsi-pci,id=scsi \ -device scsi-hd,drive=hd0 \ -drive file=disk0.raw,format=raw,cache=writethrough,id=hd0,if=none,index=0 \ -device scsi-hd,drive=hd1 \ -drive file=disk1.raw,format=raw,cache=writethrough,id=hd1,if=none,index=1 \ -device virtio-net-pci,netdev=ether0 \ -netdev user,id=ether0,net=10.0.2.0/24 \ -machine type=pc,accel=hvf
起動直後は disk1.raw をマウントしていないので、disk1.raw を /n/other にマウントします。
% con -l /srv/fscons prompt: fsys other config /dev/sd01/fossil # virtioが無効な場合はsd01をsdC1に読み替える prompt: fsys other open -AWPV prompt: srv fossil prompt: (ctl+\) >>> q % mount -n -c /srv/fossil /n/other other/active
これでインストール直後のPlan 9ファイルツリーを /n/other でアクセスできるようになります。以降は、このファイルツリーにパッチを適用していきます。
Gitリポジトリの準備(最初だけ)
ここで用意するもの
まずリポジトリを作成します。Gitのワーキングツリーは /n/other をそのまま使うので、Gitディレクトリ(ベアリポジトリ)だけ必要です。
% cd $home/lib % mkdir dist.git % git -C dist.git init --bare # 必要なら % git remote add origin https://github.com/xxx/xxx
dist.gitignore を準備します。ファイルの内容はgithub.com/lufia/plan9:.gitignoreです。/n/other は9legacyの更新があるたびにリセットするので、ここではまだ/n/other/.gitignore には置きません。
9legacyパッチの適用
9legacyのパッチを、/n/other 以下のファイルツリーに適用します。
% mkdir /tmp/20211208 # 作業用ディレクトリなので、どこでもいい % cd /tmp/20211208 % 9legacy/init -r `{pwd} % bind -c /n/other plan9 % 9legacy/update -r `{pwd} % 9legacy/stable -r `{pwd} >o % 9legacy/installall -n -r `{pwd} o % cp $home/lib/dist.gitignore plan9/.gitignore # libmemdraw-9kはalloc.cが1つのパッチで2回更新されるので、patchのテストが落ちる # そのためテストを無視して適用する % 9legacy/install -n -r `{pwd} -f libmemdraw-9k # 残りのパッチを適用 % 9legacy/installall -n -r `{pwd} o
次に9kカーネルのパッチを当てます。
% 9legacy/9k -r `{pwd} >o % 9legacy/installall -n -r `{pwd} o
必要なら、9legacyのページでOptionalとされているパッチを当てます。
% 9legacy/install -n -r `{pwd} libmux % 9legacy/install -n -r `{pwd} libworker
ここまで終われば、/tmp/20211208 の作業ディレクトリは不要なので消しても問題ありません。
% unmount plan9 # unmountせずrmするとdisk1.rawのファイルツリーが消えてしまうので注意
差分をリポジトリにコミット
Gitディレクトリ(ベアリポジトリ)とワークツリーを分けた関係で、--git-dir と --work-tree オプションを与えてあげる必要があります。何度も入力するのは面倒なのでシェル関数を作っておきます。
% fn x { git --git-dir $home/lib/dist.git --work-tree /n/other $* }
オプションの代わりに環境変数でも代用できます。
GIT_DIR=$home/lib/dist.git GIT_WORK_TREE=/n/other
これで、前回のリポジトリ状態と /n/other の差分を扱えるようになるので、必要な変更をGitリポジトリに追加しましょう。
% cd /n/other % x status % x add path/to/file # 内容をみてgit addする % x commit -m '2021-12-08' # 必要なら % x push
全部終わったら片付け。
% unmount /n/other
次回以降、9legacyのパッチが更新されたときは、disk1.raw をインストール直後のディスクイメージに戻して上記の手順を繰り返すと、差分だけをGitで管理できます。以下リポジトリの stable ブランチに、9legacyの変更をpushしているので必要なら使ってください。
リポジトリの内容をPlan 9へ反映する
これで、9legacyのパッチを戻さなくても必要な差分を扱えるようになったので、次にGitリポジトリを使って手元の環境を更新する手順を紹介します。ここでは、アップデートしたいPlan 9のディスクを disk2.raw とします。
disk2.raw を起動ディスクとしてブートした後、上記で作成したリポジトリをcloneします。当然ですがGitコマンドが必要なので、disk1.raw の時と同様にインストールしておいてください。
//memo: rc; rfork ne; bind -a /usr/lufia/bin/386 /bin % cd $home/lib % git clone -b stable https://github.com/lufia/plan9.git
2回目以降はpullで更新します。
% cd $home/lib/plan9 % git pull origin stable
次に、Plan 9のルートディレクトリには、実行中にしか存在しない仮想的なファイル*1が含まれるので、それらを除いた disk2.raw の実態を /n/boot から参照できるようにします。
% echo 'srv -AWP replica' >>/srv/fscons # -Vオプションは不要 # 少し待ってからマウントする % mount -c /srv/replica /n/boot
これで以下の準備ができました。
あとは git を使って、変更のあるファイルをリポジトリの状態にリストアしていけば、最終的には最新の9legacyファイルツリーへ更新できます。
% fn x { git --git-dir $home/lib/plan9/.git --work-tree /n/boot $* } % cd /n/boot % x status % x restore .gitignore % x restore path/to/file # 必要なだけ繰り返す
最後に片付けして終わり。
% unmount /n/boot
% rm /srv/replica
新しいソースコードでリビルド
あとは以下の記事と同じです。「ソースコードのリビルド」から先を参照してください。
気になる人のためのメモ
Gitでリストアしたファイルのオーナーやグループは、リストアしたユーザーのものに切り替わります。一般的に、/sys 以下のオーナーは sys ユーザーなので、この差が気になる人は chgrp -u などで個別に変更するといいです。
うまくいかない場合
2021年末の時点で、Plan 9に移植したGitコマンドは(特にpull/pushでハングするなど)やや不安定です。そういった場合、以下の環境変数をセットしておくとトレースログとそれぞれの実行にかかった時間などを表示するので原因の調査に役立ちます。
GIT_TRACE=1
GIT_TRACE_PERFORMANCE=1
*1:/mnt や /dev など