バージョニングファイルシステム『CopyFS』を使ってファイルのバージョン管理をしてみた

前回、バージョニングファイルシステム『NILFS』を用いてのファイルのバージョン管理を行ってみたが、今回は同じくバージョニングファイルシステムである『CopyFS』を用いて、バージョン管理を行ってみる。
といってもこのCopyFS、厳密にはファイルシステムではない。FUSEを利用して、バージョン管理用ディレクトリと利用するディレクトリを紐付けてバージョニングを行うように設定する、というものだ。そのため、マウントするディレクトリのパーティションに設定されているファイルシステムは、ext4でもなんでも構わない。ただ、事前にfuseをインストールしておく必要が有るので注意が必要だ。

今回も、検証にはCentOS 7を用いるものとする。

1.インストール

まずは、CopyFSをコンパイルする上で必要となるパッケージをインストールする。

yum install fuse-devel fuse-libs attr
cpan Algorithm::Diff

次に、CopyFSのソースコードを取得し、コンパイル、インストールを行う。

git clone https://github.com/cognusion/fuse-copyfs
cd fuse-copyfs
./configure
make all
make install
[root@dctest01 ~]# git clone https://github.com/cognusion/fuse-copyfs
Cloning into 'fuse-copyfs'...
remote: Counting objects: 85, done.
remote: Total 85 (delta 0), reused 0 (delta 0), pack-reused 85
Unpacking objects: 100% (85/85), done.
[root@dctest01 ~]# cd fuse-copyfs/
[root@dctest01 fuse-copyfs]# ./configure
loading cache ./config.cache
checking for gcc... (cached) gcc
checking whether the C compiler (gcc  ) works... yes
checking whether the C compiler (gcc  ) is a cross-compiler... no
checking whether we are using GNU C... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for fuse_main in -lfuse... (cached) no
checking for dirent.h that defines DIR... (cached) yes
checking for opendir in -ldir... (cached) no
checking how to run the C preprocessor... (cached) gcc -E
checking for ANSI C header files... (cached) yes
checking for fcntl.h... (cached) yes
checking for strings.h... (cached) yes
checking for sys/time.h... (cached) yes
checking for unistd.h... (cached) yes
checking for attr/xattr.h... (cached) yes
checking for working const... (cached) yes
checking for uid_t in sys/types.h... (cached) yes
checking for mode_t... (cached) yes
checking for off_t... (cached) yes
checking for size_t... (cached) yes
checking whether utime accepts a null argument... (cached) yes
checking for mkdir... (cached) yes
checking for strdup... (cached) yes
checking for lsetxattr... (cached) yes
checking for lgetxattr... (cached) yes
checking for llistxattr... (cached) yes
creating ./config.status
creating Makefile
[root@dctest01 fuse-copyfs]# make all
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o cache.o cache.c
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o create.o create.c
create.c: 関数 ‘create_copy_file’ 内:
create.c:387:12: 警告: ‘dst’ はこの関数内初期化されずに使用されるかもしれません [-Wmaybe-uninitialized]
       close(dst);
            ^
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o ea.o ea.c
ea.c: 関数 ‘callback_getxattr’ 内:
ea.c:351:10: 警告: 書式 ‘%lld’ は引数の型が ‘long long int’ であると予期されますが、第 8 引数の型は ‘__off_t’ です [-Wformat=]
          version->v_gid, st_data.st_size, st_data.st_mtime) < 0)
          ^
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o helper.o helper.c
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o interface.o interface.c
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o lookup.o lookup.c
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o main.o main.c
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o parse.o parse.c
gcc -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64   -c -o write.o write.c
gcc -o copyfs-daemon cache.o create.o ea.o helper.o interface.o lookup.o main.o parse.o write.o -lfuse
[root@dctest01 fuse-copyfs]# make install
install -d /bin
install -m 755 copyfs-daemon /bin
install -m 755 copyfs-mount copyfs-fversion /bin
install -d /man/man1
install -m 644 copyfs.1 copyfs-daemon.1 copyfs-mount.1 copyfs-fversion.1 /man/man1
[root@dctest01 fuse-copyfs]#

さて、これでCopyFSのインストールが完了した。

2.ディレクトリの紐付けを行う

さて、それでは実際にCopyFSを利用してみよう。
以下のようにコマンドを実行し、バージョニングを行うディレクトリとその管理用ディレクトリを関連付ける。

copyfs-mount /バージョン管理ファイルを設置するディレクトリ /実際に利用するディレクトリ

なお、最初のマウントの際はどちらのディレクトリも空でないとエラーが出るので注意。
2回目以降のマウントは、空ディレクトリで無くても問題は無い。

今回の場合だと、、バージョン管理を行う「/work」ディレクトリに対し、その管理ファイルを設置するディレクトリ「/copyfs」ディレクトリを紐付けるとした場合、以下のようにコマンドを実行する。

copyfs-mount /copyfs /work

3.バージョン管理を行う

ディレクトリのマウントも終わったので、実際にファイルのバージョン管理を行ってみよう。
まず、適当なファイルを「/work」ディレクトリ配下に設置する。

echo "1st version" >> /work/test.ini

すると、上記画面のようにバージョン管理ファイル用のmetadataなどが生成されていく。
次に、以下のようにコマンドを実行し、バージョンを上げていく。

echo "2nd version" >> /work/test.ini
echo "3rd version" >> /work/test.ini

上のコマンドによって、ファイルのバージョンは3になっているはずだ。
それでは、実際に現在のバージョンを確認してみよう。以下のコマンドを実行する。

copyfs-fversion バージョン管理をするファイルPATH

ファイルのPATHは絶対PATHではなく、copyfs-mountで指定した「/実際に利用するディレクトリ」から見ての相対PATHを指定する必要がある点に注意。
今回の場合だと、以下のようにコマンドを実行する。

copyfs-fversion test.ini

[root@dctest01 work]# cat /work/test.ini
1st version
[root@dctest01 work]# echo "2nd version" >> /work/test.ini
[root@dctest01 work]# cat /work/test.ini
1st version
2nd version
[root@dctest01 work]# echo "3rd version" >> /work/test.ini
[root@dctest01 work]# cat /work/test.ini
1st version
2nd version
3rd version
[root@dctest01 work]# copyfs-fversion /work/test.ini
copyfs-fversion: Removing leading '/' from absolute path names
[root@dctest01 work]# copyfs-fversion test.ini
File test.ini ('*' is active) :
  v1.0  : -rw-r--r--  root     root             12 2015年05月14日 10時11分00秒
  v2.0  : -rw-r--r--  root     root             24 2015年05月14日 10時15分29秒
  v3.0  : -rw-r--r--  root     root             36 2015年05月14日 10時15分34秒 [*]
[root@dctest01 work]#

確かに、バージョンが3まで作成されている事がわかる。

それでは、バージョンを2に切り戻してみよう。バージョンの切り戻しは、以下のようにコマンドを実行することで行える。

copyfs-fversion -l 切り戻したいバージョン番号 バージョン管理をするファイルPATH

今回の場合だと、ファイル「/work/test.ini」をバージョン2.0へ切り戻すので、以下のようにコマンドを実行する。

copyfs-fversion -l 2.0 test.ini

[root@dctest01 work]# copyfs-fversion -l 2.0 test.ini
[root@dctest01 work]# cat /work/test.ini
1st version
2nd version
[root@dctest01 work]#

確かに、バージョン2.0への切り戻しが行えた事が確認出来た。
ファイルごとの他、ディレクトリごとでの切り戻し機能もあるよだし、切り戻しが非常に簡単に行えるのもポイントだ。

多くのユーザーが利用するようなファイルサーバにいいのではないだろうか。
ただ、バージョン管理を行うディレクトリの容量がちょっと心配だけど…