Logo address

venti - a Plan9 new archiver -

目次

改訂履歴

コンセプト

venti はベル研が生み出した新しいコンセプトに基づくファイルシステムである。
Plan9 第4版になって、ファイル名の長さの制限が事実上廃止された。ベル研はこれまでに使用されてきたファイルシステムの記録形式をそのまま残し、(でないとユーザが混乱する)、取り敢えず長いファイル名を扱えるようにするユーザインターフェース(lnfs)だけを準備した。第5版ではファイルシステムが置き換えられ、lnfs なしに長いファイル名が使用できるようになるであろう。

これまでに使用してきたファイルシステムを単に書き換えなかったのがベル研らしい。彼らは根本的に新しいアプローチを試みたのだ。

Plan9 のファイルシステムは二種類ある(注)。簡易ファイルシステム kfs と、システム全体の基礎をなすファイルシステム fs である。

注: Plan9 はあらゆるオブジェクトをファイルシステムとして扱えるようにしている訳だから、実は非常に沢山のファイルシステムを持っていることになる。例えば ramfs など。数え上げればきりがない。しかしここではディスク上のファイルシステムの事を言っている。

fs では dumpfs がサポートされており、ファイルの過去の状態をいつでも取り出せる。しかし kfs はそうではなかった。ベル研は venti によって fs でも kfs でも等しく dumpfs の機能を提供する予定でいるらしい。ユーザに採って素晴らしいことである。

それでは venti は fs を単に書き換えたものだろうか?
そうではない。彼らは新しい革新的なものを生み出し、それを論文として発表しなくてはならない立場だ。彼らはそれ故常にシステムの理想を追いかけている。その中から彼らの仕事の種を見つけるのである。venti はそのようにして生まれたいファイルシステムである。

venti は、ハードディスクのコストを巡る現在の状況、即ち大容量のハードディスクが低価格で手に入る状況、特殊な事をしなければ使い切れない程の状況を踏まえている。
つまり、ファイルを書き換える必要がなくなっているのである。
ファイルの上書きを止めれば、ファイルシステムはシンプルになり、かつ安全に運用できる。しかも過去の記録をいつでも取り出せる余地が発生する。

venti はハードディスクのパーティションをブロックに分け、データが記録されたブロックの SHA1 ハッシュを計算する。そしてブロック ID と SHA1 ハッシュの対応表を持つ。そして同じハッシュを持つブロックを作らない。(ブロックサイズは標準では 8 kB である。) 従って誰かが大きなファイルをどこかにコピーしても、もとのファイルとブロックを共有するのでディスクの消費が殆どない事になる。Plan9が使用してきた fs は共有可能な部分(ブロック)を共有していない。それ故に venti によってスペース効率が大幅に改善された。

最近 Plan 9 の Venti に刺激されて、 Linux などの OS で Venti を動かすプロジェクトが進んでいる。成果は商品として売り出されるそうであり、それ故に Venti のソースコードにアクセスせずに開発が進められているそうである。商品名は Eternal が予定されている。
詳しくは http://www.parvat.com/products/eternal/ を見よ。
このホームページでは、伝統的なバックアップの方法に対する 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/fdiskt 命令はマニュアルには書いてない。しかしこれをやらないとパーティションが作成されない。(首を傾げる事になる)
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 の終了

  1. vacfs を止めて
    term% unmount /n/vac
  2. venti を止める
    term% kill venti|rc