FreeBSD アドベントカレンダー初参加です。
FreeBSD には GEOM という仕組みがありますが、みなさんは ggatel って使っていますか?
僕は最初、mdconfig があるからいらないでしょ?
って思ってました。
でも詳しく調べてみると、ユーザ空間でいろいろと出来そうだと認識を改めました。
この文書で取り上げるのは、mruby 上で動作する Ruby スクリプトによって構築された、GEOM Gate ローカルプロバイダのお話となります。
僕が五年前に作ったまま放置している CRuby 向け gem の二番煎じのようなものです。
匿名巨大掲示板の某スレにあった最近の書き込みをネタにしました。
なおこの mruby で GEOM Gate ローカルプロバイダを提供するソフトウェアは、https://github.com/dearblue/mruby-bin-suzuna として公開しています。
ビルド
ビルド環境を整える
まず最初に、mruby をビルドする環境づくりからです。
- mruby のビルドに最低限必要なパッケージ:
ruby git bison - mruby-bin-suzuna のサンプルをビルドするために必要なパッケージ:
sqlite3 oniguruma
pkg
でさくっとインストール。
% sudo pkg install ruby git bison sqlite3 oniguruma
mruby と mruby-bin-suzuna のソースコードの取得と展開
最初にソースコードの展開やバイナリ実行が可能なディレクトリへ移動して下さい。
そうしたらソースコードの取得と展開を行います。
% mkdir -p ~/sandbox
% cd ~/sandbox
% fetch -o- https://github.com/mruby/mruby/archive/2.1.0.tar.gz | tar xf -
% fetch -o- https://github.com/dearblue/mruby-bin-suzuna/archive/master.tar.gz | tar xf -
もし mruby の最新版が欲しいのであれば、"https://github.com/mruby/mruby/archive/master.tar.gz" に置き換えて下さい。
suzuna のビルド
ビルドは mruby ディレクトリの中で行なうのが無難でしょう。
% cd mruby-2.1.0
% ruby minirake -j8 MRUBY_CONFIG=../mruby-bin-suzuna-master/quick_config.rb
これで bin/suzuna
(あるいは build/suzuna/bin/suzuna
) ファイルが出来ます。
mruby でワンライナーを使ったり、Ruby スクリプトを単純に実行させたりしたいなれば bin/mruby
(あるいは build/suzuna/bin/mruby
) を試して下さい。
mruby 上で動作する GEOM Gate ローカルプロバイダ
200 MiB のブロックデバイスとして動作させるサンプルスクリプトを mruby-bin-suzuna/sample.rb として用意してあります。
このファイルを bin/suzuna
に渡すと、/dev/ggateXX
が生えます。
スーパーユーザーで動作させる必要があります。
% sudo ./bin/suzuna -u99 ../mruby-bin-suzuna-master/sample.rb
これで mruby 上で動作する GEOM Gate ローカルプロバイダは /dev/ggate99
でアクセス出来ます。
% sudo newfs /dev/ggate99
% sudo mkdir /media/ggtest
% sudo mount /dev/ggate99 /media/ggtest
終了したい場合、別の仮想端末から ggatel destory
を行って下さい。
% sudo umount /media ggtest
% sudo ggatel -u99
Ctrl+C でも終了できますが、ggate99 は残ったままになります。修正は今後の課題。
バグ×バグ?=カーネルパニック
zpool create する場合、zpool の作成途中で suzuna がセグフォると zpool がフリーズします。
一度目の ggatel -fu99
を行うと、zpool create はエラーを出力してプロンプトに戻ってきます。
再度 suzuna -u99 ....
のあとに zpool create
で同じプール名の作成途中で suzuna がセグフォった場合、ggatel -fu99
するとカーネルパニックします。
簡単な GEOM Gate ローカルプロバイダスクリプト
mruby-bin-suzuna/sample.rb の再掲となりますが、冗長なコメントを抜くと短く…………う〜ん、まあ40行くらいなので、充分短いでしょう。
200 MiB の容量を持つ揮発性ボリュームはこんな感じで組むことが出来ます。
mystorage = Object.new
mystorage.instance_eval do
@buf = StringIO.new("\0" * (200 * 1024 * 1024))
end
class << mystorage
def mediasize
@buf.size
end
def flags
Suzuna::FLAG_READWRITE
end
def sectorsize
512
end
def info
"Powered by #{MRUBY_DESCRIPTION}"
end
def readat(offset, size, buf)
@buf.seek offset
@buf.read(size, buf)
nil
end
def writeat(offset, buf)
@buf.seek offset
@buf.write(buf)
nil
end
def deleteat(offset, size)
nil
end
end
Suzuna.unit(mystorage)