venti - a Plan9 new archiver -
目次- 1.0.0 コンセプト
- 2.0.0 venti ファイルシステムを作成する
- 2.1.0 arena を作成する
- 2.2.0 arena をフォーマットする
- 2.3.0 isect を作成する
- 2.4.0 インデックスを作成する
- 2.5.0 venti を動かす
- 3.0.0 ファイルを venti に保存する
- 4.0.0 筆者のツール
- 4.1.0 ve
- 4.2.0 vefs
- 4.3.0 venti の終了
改訂履歴
- 2003/10/26 追加
- 2002/11/21 改訂
- 2002/09/06 改訂
- 2002/09/04 改訂
- 2002/09/01
コンセプト
venti はベル研が生み出した新しいコンセプトに基づくファイルシステムである。Plan9 第4版になって、ファイル名の長さの制限が事実上廃止された。ベル研はこれまでに使用されてきたファイルシステムの記録形式をそのまま残し、(でないとユーザが混乱する)、取り敢えず長いファイル名を扱えるようにするユーザインターフェース(lnfs)だけを準備した。第5版ではファイルシステムが置き換えられ、lnfs なしに長いファイル名が使用できるようになるであろう。
これまでに使用してきたファイルシステムを単に書き換えなかったのがベル研らしい。彼らは根本的に新しいアプローチを試みたのだ。
Plan9 のファイルシステムは二種類ある(注)。簡易ファイルシステム kfs と、システム全体の基礎をなすファイルシステム fs である。
fs では dumpfs がサポートされており、ファイルの過去の状態をいつでも取り出せる。しかし kfs はそうではなかった。ベル研は venti によって fs でも kfs でも等しく dumpfs の機能を提供する予定でいるらしい。ユーザに採って素晴らしいことである。
それでは venti は fs を単に書き換えたものだろうか?
そうではない。彼らは新しい革新的なものを生み出し、それを論文として発表しなくてはならない立場だ。彼らはそれ故常にシステムの理想を追いかけている。その中から彼らの仕事の種を見つけるのである。venti はそのようにして生まれたいファイルシステムである。
venti は、ハードディスクのコストを巡る現在の状況、即ち大容量のハードディスクが低価格で手に入る状況、特殊な事をしなければ使い切れない程の状況を踏まえている。
つまり、ファイルを書き換える必要がなくなっているのである。
ファイルの上書きを止めれば、ファイルシステムはシンプルになり、かつ安全に運用できる。しかも過去の記録をいつでも取り出せる余地が発生する。
venti はハードディスクのパーティションをブロックに分け、データが記録されたブロックの SHA1 ハッシュを計算する。そしてブロック ID と SHA1 ハッシュの対応表を持つ。そして同じハッシュを持つブロックを作らない。(ブロックサイズは標準では 8 kB である。) 従って誰かが大きなファイルをどこかにコピーしても、もとのファイルとブロックを共有するのでディスクの消費が殆どない事になる。Plan9が使用してきた fs は共有可能な部分(ブロック)を共有していない。それ故に venti によってスペース効率が大幅に改善された。
このホームページでは、伝統的なバックアップの方法に対する Eternal のメリットが上手に解説されている。(ビジネスを成功させるにはこのような分かりやすい解説が必要なのですね。) Plan 9 以外のシステムで Venti の類似品を作成しても(もちろん素晴らしいバックアップシステムを提供はするが) Plan 9 環境の Venti には遠く及ばない。
2003/10/26 追加
venti ファイルシステムを作成する
venti の使い方はマニュアルの venti(8) に書かれている。ここでは筆者のインストールの記録を載せておく。紹介する前に venti のインストールで役に立つプログラムを作成しておこう。それは指定されたサイズのファイルを作成するプログラム createである。使い方はcreate [-s size] file ...である。size には単位として K, M, G が使用できる。
{create.c} のダウンロード
arena を作成する
arena は保存するファイルの実体の置き場所である。通常はディスクパーティションをそれに充てるが、単なる実験であれば、普通のファイルで構わない。その場合にはcreate
が役に立つ。筆者は
/dev/sdD1
に arena 用のパーティションを作成する事にした。term% ls -l /dev/sdD1 --rw-r----- S 0 arisawa arisawa 10486784 Aug 11 15:12 /dev/sdD1/9fat --rw-r----- S 0 arisawa arisawa 0 Aug 11 15:12 /dev/sdD1/ctl --rw-r----- S 0 arisawa arisawa 40020664320 Aug 11 15:12 /dev/sdD1/data --rw-r----- S 0 arisawa arisawa 4145367552 Aug 11 15:12 /dev/sdD1/fs3 --rw-r----- S 0 arisawa arisawa 8335906304 Aug 11 15:12 /dev/sdD1/fs4 --rw-r----- S 0 arisawa arisawa 4219536384 Aug 11 15:12 /dev/sdD1/ntfs --rw-r----- S 0 arisawa arisawa 12650480640 Aug 11 15:12 /dev/sdD1/plan9 -lrw------- S 0 arisawa arisawa 0 Aug 11 15:12 /dev/sdD1/raw --rw-r----- S 0 arisawa arisawa 158720000 Aug 11 15:12 /dev/sdD1/swap term% disk/fdisk /dev/sdD1/data cylinder = 8225280 bytes p1 0 513 (513 cylinders, 3.92 GB) HPFS * p2 513 2051 (1538 cylinders, 11.78 GB) PLAN9 empty 2051 4865 (2814 cylinders, 21.55 GB) >>> a p3 2051 3051 >>> p p1 0 513 (513 cylinders, 3.92 GB) HPFS * p2 513 2051 (1538 cylinders, 11.78 GB) PLAN9 ' p3 2051 3051 (1000 cylinders, 7.66 GB) EMPTY empty 3051 4865 (1814 cylinders, 13.89 GB) >>> h . [newdot] - display or set value of dot a name [start [end]] - add partition d name - delete partition h - print help message p - print partition table P - print commands to update sd(3) device w - write partition table q - quit A name - set partition active P - print table in ctl format e - show empty dos partitions t name [type] - set partition type >>> t p3 new partition type [? for list]: ? EMPTY FAT12 XENIX XENIX USR FAT16 EXTENDED FATHUGE HPFS AIXBOOT AIXDATA OS/2BOOT FAT32 FAT32LBA EXTHUGE UNFORMATTED HPFS2 PLAN9 CPM0 DMDDO GB SPEEDSTOR SYSV386 NETWARE PCIX MINIXV1.3 MINIXV1.5 LINUXSWAP LINUX LINUXEXTENDED AMOEBA AMOEBABB BSD386 BSDI BSDISWAP OTHER CPM SPEEDSTOR12 SPEEDSTOR16 LANSTEP BB new partition type [? for list]: OTHER >>> p p1 0 513 (513 cylinders, 3.92 GB) HPFS * p2 513 2051 (1538 cylinders, 11.78 GB) PLAN9 ' p3 2051 3051 (1000 cylinders, 7.66 GB) OTHER empty 3051 4865 (1814 cylinders, 13.89 GB)
>>> w >>> p p1 0 513 (513 cylinders, 3.92 GB) HPFS * p2 513 2051 (1538 cylinders, 11.78 GB) PLAN9 p3 2051 3051 (1000 cylinders, 7.66 GB) OTHER empty 3051 4865 (1814 cylinders, 13.89 GB) >>> q
disk/fdisk
の t
命令はマニュアルには書いてない。しかしこれをやらないとパーティションが作成されない。(首を傾げる事になる)disk/fdisk
が終了したら /dev/sdD1/other
が作成されている事を確認しよう。term% ls -l /dev/sdD1 --rw-r----- S 0 arisawa arisawa 10486784 Aug 11 15:12 /dev/sdD1/9fat --rw-r----- S 0 arisawa arisawa 0 Aug 11 15:12 /dev/sdD1/ctl --rw-r----- S 0 arisawa arisawa 40020664320 Aug 11 15:12 /dev/sdD1/data --rw-r----- S 0 arisawa arisawa 4145367552 Aug 11 15:12 /dev/sdD1/fs3 --rw-r----- S 0 arisawa arisawa 8335906304 Aug 11 15:12 /dev/sdD1/fs4 --rw-r----- S 0 arisawa arisawa 4219536384 Aug 11 15:12 /dev/sdD1/ntfs --rw-r----- S 0 arisawa arisawa 8225280000 Aug 11 15:12 /dev/sdD1/other --rw-r----- S 0 arisawa arisawa 12650480640 Aug 11 15:12 /dev/sdD1/plan9 -lrw------- S 0 arisawa arisawa 0 Aug 11 15:12 /dev/sdD1/raw --rw-r----- S 0 arisawa arisawa 158720000 Aug 11 15:12 /dev/sdD1/swap
arena をフォーマットする
term% venti/fmtarenas arena. /dev/sdD1/other clearing the partition configuring /dev/sdD1/other with arenas=16 for a total storage of bytes=8225275904 and directory bytes=65536 adding arena arena.0 at [335872,537206784) adding arena arena.1 at [537206784,1074077696) adding arena arena.2 at [1074077696,1610948608) adding arena arena.3 at [1610948608,2147819520) adding arena arena.4 at [2147819520,2684690432) adding arena arena.5 at [2684690432,3221561344) adding arena arena.6 at [3221561344,3758432256) adding arena arena.7 at [3758432256,4295303168) adding arena arena.8 at [4295303168,4832174080) adding arena arena.9 at [4832174080,5369044992) adding arena arena.10 at [5369044992,5905915904) adding arena arena.11 at [5905915904,6442786816) adding arena arena.12 at [6442786816,6979657728) adding arena arena.13 at [6979657728,7516528640) adding arena arena.14 at [7516528640,8053399552) adding arena arena.15 at [8053399552,8225275904)arena は 500MB 程度の領域に細分化されるのが分かる。バックアップを採りやすくしているのである。
フォーマットには筆者の場合には40分程かかった。
isect を作成する
isect のサイズは arena の 5% 程度がお勧めだそうだ。実際にはあまり気にする事はなく、後で変更あるいは追加できる。term% mkdir $home/venti term% cd $home/venti term% create -s400m isect0 term% ls -l --rw-rw-r-- M 8 arisawa arisawa 419430400 Aug 31 23:50 isect0 term% venti/fmtisect isect0 isect0 clearing the partition configuring index section isect0 with space for index config bytes=65536 term%複数のユーザを抱えている場合には
isect
は個人のディレクトリには置くべきではないであろう。
インデックスを作成する
term% cat>venti.conf index main isect /usr/arisawa/venti/isect0 arenas /dev/sdD1/other term% venti/fmtindex venti.conf configure index section in /usr/arisawa/venti/isect0 configure arenas in /dev/sdD1/other using 51159 buckets of 51159; div=83954 add arena arena.0 at [1048576,537903104) add arena arena.1 at [537903104,1074757632) add arena arena.2 at [1074757632,1611612160) add arena arena.3 at [1611612160,2148466688) add arena arena.4 at [2148466688,2685321216) add arena arena.5 at [2685321216,3222175744) add arena arena.6 at [3222175744,3759030272) add arena arena.7 at [3759030272,4295884800) add arena arena.8 at [4295884800,4832739328) add arena arena.9 at [4832739328,5369593856) add arena arena.10 at [5369593856,5906448384) add arena arena.11 at [5906448384,6443302912) add arena arena.12 at [6443302912,6980157440) add arena arena.13 at [6980157440,7517011968) add arena arena.14 at [7517011968,8053866496) add arena arena.15 at [8053866496,8225726464) configured index=main with arenas=16 and storage=8224677888 term%
venti を動かす
term% cd $home/venti term% venti/venti -h tcp!*!8088 -w & term% configure index section in /usr/arisawa/venti/isect0 configure arenas in /dev/sdD1/other initialize 1048576 bytes of lump cache for 128 lumps initialize 3072 bytes of index cache for 64 index entries initialize 294912 bytes of disk block cache sync arenas and index... initialize write queue... starting http server at tcp!*!8088 starting server term%venti はウェブのブラウザから状態が見えるように設計されている。筆者のシステムでは 80 も 8080 も使用済みなので 8088 を割り付けている。
venti/venti
は大量のメッセージを出す。それらのメッセージを吸収するには、ウィンドウをスクロール可にしておくか、あるいはventi/venti -h tcp!*!8088 -w >[2] /dev/null &とする。
動いているのを確認しよう
term% ps ... arisawa 10369 0:00 0:00 1860K Open venti arisawa 10370 0:00 0:00 1860K Rendez venti arisawa 10371 0:00 0:00 1860K Rendez venti arisawa 10372 0:00 0:00 1860K Open venti ... term% netstat -n ... tcp 19 arisawa Listen 8088 0 :: ...
ファイルを venti に保存する
注: この記事は古くなっている。現在では vac と vacfs の代わりに fossil が使用されている。(2003/10/23)
venti とユーザのインターフェースは vac と vacfs が受け持っている。vac はファイルを venti に保存し、vacfs は保存されたファイルをファイルシステムとしてユーザに提供する。しかし vac も vacfs もまだ荒削りである。次の版で洗練されたものに仕上げるらしい。
問題点が分かる様に以下に現在の vac と vacfs の使い方を述べる。
term% vac -h pc -f vacfile $home/bin/rc term% cat vacfile vac:d5a804e88fe4983404981caad1da2e8937f10e35 term% vacfs -h pc vacfile term% ls -l /n/vac d-rwxrwxr-x M 2510 arisawa arisawa 0 Sep 1 06:55 /n/vac/rc term% ls -l /n/vac/rc --rwxr-xr-x M 2510 arisawa arisawa 314 May 3 07:32 /n/vac/rc/" --rwxr-xr-x M 2510 arisawa arisawa 52 Jun 9 11:48 /n/vac/rc/-f --rwxr-xr-x M 2510 arisawa arisawa 118 May 3 07:32 /n/vac/rc/ACID --rwxr-xr-x M 2510 arisawa arisawa 207 May 21 20:31 /n/vac/rc/KILL ... term%ここでは vac と vacfs のオプションで
-h pc
を指定しているが、これは環境変数 venti を与えておけば省略できる。term% venti=pcここに
pc
は venti が置かれているホストである。(venti はネットワークファイルサーバなのである。)vac の
-f
オプションで指定された vacfile
は SHA1 ハッシュを書き出すファイルである。このハッシュ値は vacfs でファイルを閲覧するのに使用される。従ってこの値が分からなくなると venti からファイルを取り出せない!明らかに、このままでは使い物にならない。
vacfs は特に指定が無ければ
/n/vac
に vac で保存したファイルをマウントする。
vac と vacfs は今のところアーカイバとして位置付けられている。ファイルを保存するのに
cp foo /n/vac/barのようにできないのは Plan9 らしくない。次の版ではできるようにするらしい。
筆者のツール
vac と vacfs だけでは使い物にならないので、使い物になるようなツールを作る事にした。名前は ve と vefs である。term% ve $home/bin/rc term% ve ... 2002/09/01 12:03 /usr/arisawa/venti/memo 2002/09/01 12:06 /usr/arisawa/bin 2002/09/01 13:34 /usr/arisawa/bin/rc 2002/09/01 13:38 /usr/arisawa/bin/rc term%ve の出力は、ve が実行された時刻と、保存の対象となったディレクトリ(あるいはファイルである。
ve は引数が指定された時には、指定されたファイルあるいはディレクトリを venti に保存し、かつ vac が返した SHA1 ハッシュ値を
$home/venti/logに自動的に記録する。
term% tail $home/venti/log 0cec027b139527d09d257fdcf438249ddeb6227a 2002/09/01 12:03 /usr/arisawa/venti/memo d73e183e1a702a91fa388163084fef093bb8dbb5 2002/09/01 12:06 /usr/arisawa/bin 35969c6c72b05499392ee7a691e79b4617d14b93 2002/09/01 13:34 /usr/arisawa/bin/rc 4a509acc84156539240443f507b6058959ddac8f 2002/09/01 13:38 /usr/arisawa/bin/rc引数なしの ve は過去の記録を表示する。
venti に保存されたディレクトリあるいはファイルを見たい場合には
term% vefs 2002/09/01 12:06 /usr/a term% ls -l /n/vac d-rwxrwxr-x M 2516 arisawa arisawa 0 May 3 06:56 /n/vac/bin term% vafs nti/memo term% ls -l /n/vac --rw-rw-r-- M 2518 arisawa arisawa 37 Sep 1 09:12 /n/vac/memoのように、ve で行の特徴を表す文字列パターンを vefs の引数として渡す。マウスで目的の行に含まれる任意の文字列(空白を含んで構わない)を選び、vefs の引数として渡せばよいようにできている。(時刻情報が無難であろう。)
同じパターンが複数存在した場合には最後の行が選択される。
vefs の引数が与えられていない場合には ve で表示される最後の行が指定されたと見なされる。
ve で大きなディレクトリを指定した場合には、最初の実行はうんざりする程時間がかかるが、二回目からはあまり時間はかからない。
ve と vefs の組は、まだ Plan9 らしくはないのだが、 venti を充分に実用的に使っていくことができる。
以下に ve と vefs のソースコードを示す。
なお、2002/09/06 の ve のソースコードにはバグがありましたので改訂されています。
ve
#!/bin/rc # name: ve # usage: ve [file] # coded by Kenji Arisawa # source: http://plan9.aichi-u.ac.jp/netlib # last update: 2002/09/06 log=$home/venti/log switch($#*){ case 0 awk '{print $2,$3,$4}' $log case 1 if(! test -e $1){ echo $1 not exist exit } d=`{date} # $d is: Sun Sep 1 17:43:14 JST 2002 Jan=01;Feb=02;Mar=03;Apr=04;May=05;Jun=06;Jul=07;Aug=08; Sep=09;Oct=10;Nov=11;Dec=12 day=$d(3) if(~ $day ?) day=0^$day t=`{ifs=':' echo `{echo $d(4)}} t=$t(1)^':'^$t(2) d=$d(6)^/^$$d(2)^/^$day^' '^$t if(~ $1 /*) p=$1 if not p=`{pwd}^/$1 # `^' is required p=`{cleanname $p} a=`{grep ' '^$p^'$' $log | tail -1} if(~ $#a 4) v=`{vac -h pc -qd <{echo vac:$a(1)} $p} if not v=`{vac -h pc $p} if(! ~ $v vac:*){ echo '# vac error' exit 'vac error' } ifs=': ' v=`{echo -n $v} echo $v(2) $d $p >> $log case * echo 'usage: ve [file]' }
vefs
#!/bin/rc # name: vefs # usage: vefs patterm # coded by Kenji Arisawa # source: http://plan9.aichi-u.ac.jp/netlib # last update: 2002/09/04 log=$home/venti/log if(~ $#* 0) a=`{tail -1 $log} if not a=`{grep $"* $log | tail -1} if(! ~ $#a 4){ echo '# pattern not exist' exit 'pattern not exist' } unmount /n/vac >[2] /dev/null vacfs -h pc <{echo vac:$a(1)}
なお ve において日付は日本人が使うスタイルを採用した。
筆者はアメリカやイギリスで使用されるスタイルは大嫌いである。不合理の極みである。なぜ日本人は堂々と世界に日本流をアピールしないのか?
venti の終了
- vacfs を止めて
term% unmount /n/vac
- venti を止める
term% kill venti|rc