zfs diffがはいったのをすっかりわすれてたので、あわててためしてみた。

とりあえずつかいかたをみる

% zfs diff
must provide at least one snapshot name
usage:
        diff [-FHt] <snapshot> [snapshot|filesystem]

For the property list, run: zfs set|get

For the delegated permission list, run: zfs allow|unallow

スナップショットは1つは指定しないとだめってことか。

usageの最後にpropertyとpermissionの記述がくっついてるのを不思議におもったが、/usr/src/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c:usage()をみたら、とりあえず全部のヘルプにくっつけてるんだな。これまで気にしてなかった。

とりあえず動かしてみる。

% zfs diff tank/home/koie
Badly formed snapshot name tank/home/koie: missing '@' delimiter in snapshot name

おっとファイルシステムを指定したら文句をいわれた。ちゃんとusageよめよ>俺

% zfs diff tank/home/koie@__hour-01
The diff delegated permission is needed in order
to create a just-in-time snapshot for diffing
: unable to generate diffs

1引数だと/usr/src/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_diff.c:make_temp_snapshot()でスナップショットをとるみたいだ。ライブファイルシステムとスナップショットのdiffはスナップショット間のdiffにおとしこまれるようだ。スナップショットの作成コストが軽いからできるワザだな。それにしてもエラーメッセージの最後の行がくさっとる。

ちなみにzfs diff中にzfs list -t snapshot -r tank/home/koieしてみたら tank/home/koie@zfs-diff-55659-000000009f26d0d5 というスナップショットが作られてた。ソースコードをみると最初の数字はPIDなのはわかったが、後の方はわからんかった。

% zfs diff tank/home/koie@__hour-01 tank/home/koie@_hour-02
Unable to obtain diffs: そのようなファイルまたはディレクトリはありません

第2引数をタイポしたら不親切なメッセージがでた。

うちなおし。

% zfs diff tank/home/koie@__hour-01 tank/home/koie@__hour-02
Unable to obtain diffs:
   The sys_mount privilege or diff delegated permission is needed
   to execute the diff ioctl

特権が必要なようだ。あるいはzfs allowで許可しておくかどちらか。

% sudo zfs diff tank/home/koie@__hour-01 tank/home/koie@__hour-02
Password:
M       /home/koie/
M       /home/koie/Mail
M       /home/koie/Mail/trash/.mew-mtime
 ...
-       /home/koie/MailDB/id.db
-       /home/koie/.recentf.~2197~
 ...
R       /home/koie/.recentf -> /home/koie/.recentf.~2198~
+       /home/koie/MailDB/id.db
 ...
+       /home/koie/.recentf
 ...

libzfs_diff.cをみると先頭の文字は以下のようになっている:

+ ADD
M MODIFIED
- REMOVED
R RENAMED

ファイルシステムレベルでおいかけてるから、MODIFIEDなのかREMOVED+ADDなのかを区別できているな。ファイルを書き換えたなら"M"、一旦unlinkしてから作り直したら"-"と"+"がでる。上の例でいうとid.dbがそう。

man zfsしてもzfs diffの記述がまだないので/usr/src/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c:zfs_do_diff()をみると、オプションはこうなってた:

-F ZFS_DIFF_CLASSIFY ファイルタイプを表示
-H ZFS_DIFF_PARSEABLE renameで" -> "のかわりに"\t"をつかう
-t ZFS_DIFF_TIMESTAMP 時刻も表示

ファイルタイプは以下のとおり

B S_IFBLK
C S_IFCHR
/ S_IFDIR
> S_IFDOOR
| S_IFIFO
@ S_IFLNK
P S_IFPORT
= S_IFSOCK
F S_IFREG
? そのほか

引数の1番目は "@〜" と書けるようだ。そのときは2番目の引数は必須で、つかいかたはたぶんこんなかんじ:

% sudo zfs diff @__hour-14 tank/home/koie

べんりじゃな。libzfs_diff.c:get_snapshot_names()をみると、そのほかにもいろいろなバリエーションがあるようだ:

        /*
         * Can accept
         *    dataset@snap1
         *    dataset@snap1 dataset@snap2
         *    dataset@snap1 @snap2
         *    dataset@snap1 dataset
         *    @snap1 dataset@snap2
         */

そんなところでおしまい。