これまでに使用してきたファイルシステムを単に書き換えなかったのがベル研らしい。彼らは根本的に新しいアプローチを試みたのだ。
Plan9 のファイルシステムは二種類ある(注)。簡易ファイルシステム kfs と、システム全体の基礎をなすファイルシステム fs である。
fs では dumpfs がサポートされており、ファイルの過去の状態をいつでも取り出せる。しかし kfs はそうではなかった。ベル研は venti によって fs でも kfs でも等しく dumpfs の機能を提供する予定でいるらしい。ユーザに採って素晴らしいことである。
それでは venti は fs を単に書き換えたものだろうか?
そうではない。彼らは新しい革新的なものを生み出し、それを論文として発表しなくてはならない立場だ。彼らはそれ故常にシステムの理想を追いかけている。その中から彼らの仕事の種を見つけるのである。venti はそのようにして生まれたファイルシステムである。
venti は、ハードディスクのコストを巡る現在の状況、即ち大容量のハードディスクが低価格で手に入る状況、特殊な事をしなければ使い切れない程の状況を踏まえている。
つまり、ファイルを書き換える必要がなくなっているのである。
ファイルの上書きを止めれば、ファイルシステムはシンプルになり、かつ安全に運用できる。しかも過去の記録をいつでも取り出せる余地が発生する。
venti はハードディスクのパーティションをブロックに分け、データが記録されたブロックの SHA1 ハッシュを計算する。そしてブロック ID と SHA1 ハッシュの対応表を持つ。そして同じハッシュを持つブロックを作らない。(ブロックサイズは標準では 8 kB である。) 従って誰かが大きなファイルをどこかにコピーしても、もとのファイルとブロックを共有するのでディスクの消費が殆どない事になる。Plan9が使用してきた fs は共有可能な部分(ブロック)を共有していない。それ故に venti によってスペース効率が大幅に改善された。
http://www.parvat.com/products/eternal/
を見よ。2003/10/26 追加
create [-s size] file ...
create.c
のダウンロード
補注: dd コマンドでやっていける。1024 B の空ファイル "xxxx
" を作るには
dd -if /dev/zero -of xxxx -bs 1024 -count 1
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
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 程度の領域に細分化されるのが分かる。バックアップを採りやすくしているのである。
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%
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 が受け持っている。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 はネットワークファイルサーバなのである。)-f
オプションで指定された vacfile
は SHA1 ハッシュを書き出すファイルである。このハッシュ値は vacfs でファイルを閲覧するのに使用される。従ってこの値が分からなくなると venti からファイルを取り出せない!/n/vac
に vac で保存したファイルをマウントする。
vac と vacfs は今のところアーカイバとして位置付けられている。ファイルを保存するのに
cp foo /n/vac/bar
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 が実行された時刻と、保存の対象となったディレクトリ(あるいはファイルである。
$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 は過去の記録を表示する。
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 の引数として渡せばよいようにできている。(時刻情報が無難であろう。)
ve と vefs の組は、まだ Plan9 らしくはないのだが、 venti を充分に実用的に使っていくことができる。
以下に ve と vefs のソースコードを示す。
なお、2002/09/06 の 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($#*)<code> case 0 awk '<code>print $2,$3,$4</code>' $log case 1 if(! test -e $1)<code> echo $1 not exist exit </code> d=`<code>date</code> # $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=`<code>ifs=':' echo `<code>echo $d(4)</code></code> t=$t(1)^':'^$t(2) d=$d(6)^/^$$d(2)^/^$day^' '^$t if(~ $1 /*) p=$1 if not p=`<code>pwd</code>^/$1 # `^' is required p=`<code>cleanname $p</code> a=`<code>grep ' '^$p^'$' $log | tail -1</code> if(~ $#a 4) v=`<code>vac -h pc -qd <<code>echo vac:$a(1)</code> $p</code> if not v=`<code>vac -h pc $p</code> if(! ~ $v vac:*)<code> echo '# vac error' exit 'vac error' </code> ifs=': ' v=`<code>echo -n $v</code> echo $v(2) $d $p >> $log case * echo 'usage: ve [file]' </code>
#!/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=`<code>tail -1 $log</code> if not a=`<code>grep $"* $log | tail -1</code> if(! ~ $#a 4)<code> echo '# pattern not exist' exit 'pattern not exist' </code> unmount /n/vac >[2] /dev/null vacfs -h pc <<code>echo vac:$a(1)</code>
なお ve において日付は日本人が使うスタイルを採用した。
筆者はアメリカやイギリスで使用されるスタイルは大嫌いである。不合理の極みである。なぜ日本人は堂々と世界に日本流をアピールしないのか?