Plan 9とGo言語のブログ

主にPlan 9やGo言語の日々気づいたことを書きます。

ベル研Plan 9を9legacyの安定版にアップデートする

従来のPlan 9公式サイトplan9.bell-labs.com/plan9は2020年現在、更新が停止しておりアクセスができません。代わりに、9p.io/plan9で最終更新日である2015年1月時点のデータがミラーされていて、Wikiやcontribソースコードなどベル研公式サイトが提供していたほとんどのリソースにアクセスできる状態になっています。

いまPlan 9をインストールするなら、

  • 9frontをインストールする
  • 9legacyをインストールする

のどちらかが無難ですが、9p.ioでは当然インストーラもミラーされているので、ベル研によって最後にリリースされたCDまたはUSBディスクイメージを9p.ioからダウンロードしてインストール可能です。とはいえ2015年のイメージなので、TLS 1.2に対応していないなど、色々錆び付いていてそのままでは使い物になりません。この記事と次の記事で、

  • ベル研Plan 9から9legacyの安定版に更新する
  • Gitを使って9legacyの更新を追う
  • (ついでに)Google Compute Engine用のディスクイメージを作る

の3点について、個人的にどうやっているのか紹介します。長くなったのでこの記事では安定版へアップデートするところまで。

ベル研Plan 9のインストール

まずはベル研Plan 9のインストールが必要なのでQEMUにインストールしましょう。この記事では最終的にCompute Engineイメージを作るためQEMUを使いますが、作らないのであればQEMU以外でも構いません。*1

ところで、QEMUには多くのオプションがあり、virtioを使う場合などは非常に長いコマンドラインになってしまうので簡単なwrapperを用意しました。以下の説明ではwrapperと生のオプションを併記しますが、だいぶシンプルになっていると思うので良ければどうぞ。

github.com

イメージ作成とインストール

まずはディスクを作ります。Compute Engineイメージのためraw形式でディスクイメージを作っていますが、Compute Engineイメージを作らないなら、どの形式でも構いません。

$ qemu-img create disk0.raw 10G

次に、ベル研Plan 9のCDイメージからブートします。

$ curl https://9p.io/plan9/download/plan9.iso.bz2 | bunzip2 | tar x
$ ./start.bash -d plan9.iso
qemu-system-x86_64 -m 1G -smp 2 \
  -drive file=disk0.raw,format=raw,cache=writethrough,id=hd0,index=0 \
  -device e1000,netdev=ether0 \
  -netdev user,id=ether0,net=10.0.2.0/24 \
  -machine type=pc,accel=hvf \ # ← Linuxならaccel=kvm
  -drive file=plan9.iso,index=2,media=cdrom \
  -boot order=d

この後は通常のPlan 9をインストールする手順なので省略しますが、fossil+ventiではなくfossilのみでフォーマットすると、GNU tarでtar --sparseした際にイメージサイズを小さくできるので、Compute Engineイメージを作る場合はこちらが良いと思います。少々面倒ですが、後からfossil+ventiディスクに移行することは可能です。

インストールが終わったら、あとで使うためにインストール直後のdisk0.rawをバックアップしておきましょう。ここではdisk0-orig.rawとします。

$ cp disk0.raw disk0-orig.raw

9legacyの安定版へアップデート

インストール直後のdisk0.rawから起動します。

$ ./start.bash
qemu-system-x86_64 -m 1G -smp 2 \
  -drive file=disk0.raw,format=raw,cache=writethrough,id=hd0,index=0 \
  -device e1000,netdev=ether0 \
  -netdev user,id=ether0,net=10.0.2.0/24 \
  -machine type=pc,accel=hvf

以下のプロンプトが表示されたら、glendaでログインするとrioと共にウィンドウが表示されると思います。

user[none]: 

グレーの背景で右クリックすると、新しいウィンドウを作成できるので作りましょう。以下の作業は、このウィンドウで行います。

ネットワーク設定

まずはネットワークの設定から。上のqemuコマンドを使っていればDHCPによってIPアドレスを設定できると思います。

# DHCPからIPアドレスを設定(再起動すると消える)
% ip/ipconfig

# DNSサーバのIPアドレスを設定
% cat >>/lib/ndb/local

ipnet=qemu-net ip=10.0.2.0 ipmask=255.255.255.0
    dns=10.0.2.3
^D

# DNSクライアントを起動(再起動すると消える)
% ndb/dns -r

このコマンドが何をしているのかは、以下の記事が少し参考になるかもしれません。

ここまで終われば、少なくともインターネットには出られるはず。

% ip/ping -n3 8.8.8.8

9legacy-toolの準備

9legacyはベル研Plan 9に対するパッチ集なので、PatchesからStableと9k kernelにリストされているパッチをローカルのソースコードに当てていく作業となります。一般的には、

% cd /
% hget http://9legacy.org/9legacy/patch/xxx.diff | ape/patch -p1

という手順なのですが、数が多くて非常に大変だし、頻繁にパッチが適用できず中途半端な状態に陥りがちなので、パッチを管理するためのコマンド群を作成しました。

しかしこの時点では、まだPlan 9ではTLS 1.2が使えないのでGitHubからダウンロードできません。なので少し面倒ですが、u9fsを使ってローカルから渡してしまいましょう。u9fsはローカルで実行します。著者の説明ではlaunchdから起動していますが、面倒なので、ここではplan9portのlisten1で一時的に起動させる方法を取りました。

まずはコンパイル

$ make

u9fsPlan 9から接続する際の認証情報を/etc/u9fs.keyから読み込みます*2。このファイルは上から、パスワード、ユーザ名、認証ドメインを1行ずつ書いたファイルなので作ってしまいましょう。u9fs -A fileオプションを使うと、/etc/u9fs.key以外のファイルでも扱えます。

# u9fsが認証するユーザー情報をu9fs.keyに書く; それぞれ値は何でもいい
$ cat u9fs.key
password
username
authdom

できたらu9fsを起動して、Plan 9側からマウントします。

# 9fsポート(564)でlisten
$ listen1 'tcp!*!9fs' ./u9fs -a p9any -A u9fs.key -u $USER -l log

# Plan 9側からu9fsへ接続(ローカルのIPアドレスは192.168.1.3とする)
% 9fs 192.168.1.3
(認証情報を聞かれるのでu9fs.keyに書いた内容を入力する)

% cd /n/192.168.1.3

ファイルのコピーが終わったらu9fsは終了して構いません。

% unmount /n/192.168.1.3

$ pkill u9fs
$ rm u9fs.key log

9legacyパッチを適用

9legacy-toolを使って、手元のソースコードを更新する方法は以下のとおりです。

# パッチを管理するディレクトリを$home/lib/9legacyに作成
% 9legacy/init

# 最新のパッチリストを取得
% 9legacy/update

# システム全体を更新対象のソースツリーとして設定
% echo 'srv -AWP replica' >>/srv/fscons
% mount -c /srv/replica $home/lib/9legacy/plan9

# Stableと9k kernelパッチを適用
% 9legacy/stable >stable.list
% 9legacy/9k >9k.list
% 9legacy/installall -n stable.list 9k.list

# 適用したパッチを確認
% 9legacy/list

# 後始末
% unmount $home/lib/9legacy/plan9
% rm /srv/replica

ソースコードのリビルド

これで手元のソースコードが最新の状態となったので、コマンドやカーネルを更新しましょう。

% cd /sys/src
% mk install

カーネルも更新しておきます。

% cd /sys/src/9
% mk 'CONF=pcf'
% 9fat:
% cp 9pcf /n/9fat/9pcf

% cd /sys/src/9/pcboot
% mk 9load
% cp 9load /n/9fat/9load

ところで9fatはただのFATファイルシステムなんですが、8文字以上のファイル名でも普通に作成できます。だけども9loadから扱えなくなってしまうのでファイル名の長さには注意しましょう。

Virtioを使う

この手順は間違えると起動しなくなるので、必要ならディスクイメージをコピーしておきましょう

Compute Engineで実行する場合、virtio必須なので手元の環境もvirtioを扱うようにしておきましょう。Compute Engineイメージを作らないなら、グラフィックスが使えなくなるなど不都合もあるので、この手順は省略しても構いません。

基本的な手順はvirtioを使うの通りですが、9legacyパッチでカーネルコンフィグにvirtioが追加されているので、デバイス名の変更と再起動だけ行います。ストレージはvirtio-blkとvirtio-scsiの2通り存在していて、QEMUのオプションでどちらを使うか切り替えられますが、Compute Engineに合わせて、この手順ではvirtio-scsiを使います。Plan 9から見ると、virtio-scsiの場合はデバイス名が/dev/sd00のように数字で構成されていて、virtio-blkは/dev/sdF0のようにアルファベットと数字で構成されます。

% 9fat:
% ed /n/9fat/plan9.ini
(bootfile, bootargs, bootdiskエントリのsdC0をsd00に変更)

% cd /tmp
% fossil/conf /dev/sdC0/fossil >fossil.conf
% ed fossil.conf
(fossil.confにあるsdC0をsd00に変更)
% fossil/conf -w /dev/sdC0/fossil fossil.conf
% rm fossil.conf

# Ventiを使っている場合のみ
% venti/conf /dev/sdC0/arenas >venti.conf
% ed venti.conf
(venti.confにあるsdC0をsd00に変更)
% venti/conf -w /dev/sdC0/arenas <venti.conf

virtioに切り替えるとドライバが対応していなくてグラフィックスが使えなくなるのでmonitorの値を変更しましょう。コンソールに流れたログを遡って読んだり、コピペしたりなどができなくなるのはさすがに不便なので、シリアルコンソールを使えるように設定しておきましょう。

# 以下のコマンドでは追記しているけど、既にあれば値を書き換える方が良い
% echo 'monitor=vesa' >>/n/9fat/plan9.ini
% echo 'console=0 b115200 l8 pn s1' >>/n/9fat/plan9.ini

これで再起動します。virtioを使うため、QEMUの起動オプションが変わります。

$ ./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

-nographicオプションを付けて起動したQEMUは閉じるボタンなどはありません。ctl+aに続けてcキーを入力するとQEMUモニタに入れるので、そこでqと入力すれば終了できます。また、おそらく終了した時点でターミナルが壊れているので、tputでリセットしておきましょう。

% fshalt

ctl+a q
(qemu) q
$ tput smam  # 反対のオプションはrmam

ところでLinuxでは、認識した順に/dev/sda, /dev/sdbとデバイス名が決まっていきますが、Plan 9は単純に接続された場所によって決まります。SATAプライマリのスレーブに接続されたディスクは、Plan 9では常に/dev/sdC1ですし、セカンダリのマスタは/dev/sdD0です。後の手順でも少し触れますが、Compute Engineの起動ディスクはSCSIの2番目にあるディスクとして接続されているようで、Plan 9からは/dev/sd01と見えます。

おわりに

ひとまずこれで、現在の9legacy安定版にまで更新できました。virtioを使えるようにできた後で、

$ cp disk0.raw disk.raw
$ gtar -Sczf plan9.tar.gz disk.raw

とするとCompute Engineで使えるディスクイメージを作れますが、とはいえ9legacyはパッチ集であり、同じパッチ名でも更新される時があるので、このままでは9legacyの更新に追従することがとても困難です*3。そこで次の記事では、Gitを使ってアップデートする方法を紹介します。

blog.lufia.org

*1:動くかどうかは知りませんが...少なくともESXiでは動作確認しました

*2:認証を不要とすることも試したけどうまく接続できなかった

*3:パッチは2015年時点のソースに対する差分だけど手元はもう変わっている