zfs send -DというのがあるのでFreeBSDであそんでみた。

まずはファイルシステムをつくってdedupが効きそうなファイルを5つ作る。

# zfs create tank/test
# cd /tank/test
# dd if=/dev/urandom of=file1 bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes transferred in 2.452660 secs (42752602 bytes/sec)
# ls -l file1
-rw-r--r--  1 root  wheel  104857600  6月 14 23:51 file1
# cp file1 file2
# cp file1 file3
# cp file1 file4
# cp file1 file5
# df -h /tank/test
Filesystem    Size    Used   Avail Capacity  Mounted on
tank/test     640G    499M    639G     0%    /tank/test

※tank/testはdedup=off

スナップショットをつくってファイルシステムイメージ(full stream)をとる。

# zfs snapshot tank/test@freeze
# zfs send tank/test@freeze >/tmp/tank-test-freeze.zfs
# zfs send -D tank/test@freeze >/tmp/tank-test-freeze.ddzfs
# ls -l /tmp/tank-test-freeze*zfs
-rw-r--r--  1 root  wheel  106120104  6月 14 23:55 /tmp/tank-test-freeze.ddzfs
-rw-r--r--  1 root  wheel  525550504  6月 14 23:55 /tmp/tank-test-freeze.zfs

zfs send -Dで作成するとdedupが効いて1/5になっているのがわかる。

受け側のファイルシステムをつくってファイルシステムを複製する。

# zpool create pool /dev/ada1s4 /dev/ada2s4 /dev/ada3s4
# zpool list pool
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
pool  29.2G  81.5K  29.2G     0%  1.00x  ONLINE  -
# zfs receive pool/test </tmp/tank-test-freeze.ddzfs
# zpool list pool
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
pool  29.2G   501M  28.8G     1%  1.00x  ONLINE  -

dedupが効いたストリームをreceiveしただけではdedupが効かないようだ。

明示的にdedup=onにしてファイルシステムをつくって複製するとOKだった。

# zfs destroy -r pool/test
# zfs create -o dedup=on pool/test
# zfs receive -F pool/test </tmp/tank-test-freeze.ddzfs
# zpool list pool
NAME   SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
pool  29.2G   101M  29.2G     0%  5.00x  ONLINE  -
# zfs send pool/test@freeze >/tmp/pool-test-freeze.zfs
# ls -l /tmp/pool-test-freeze.zfs
-rw-r--r--  1 root  wheel  525550504  6月 15 00:51 /tmp/pool-test-freeze.zfs

dedupが効いているファイルシステムのイメージをとってもdedupが効いたストリームにはならないようだ。

というわけでファイルシステムのdedupとストリームのdedupはまったく別物のようだ。

zfs send -Dでdedupしなくても圧縮プログラムがうまいことやってくれるかもとおもって試してみたが、まったく圧縮されなかった(ファイルの繰り返しの周期が1MiBなのが原因かな)。

% gzip <tank-test-freeze.zfs >tank-test-freeze.zfs.gz
% xz <tank-test-freeze.zfs >tank-test-freeze.zfs.xz
% ls -l tank-test*
-rw-r--r--  1 root  wheel  525550504  6月 15 00:50 tank-test-freeze.zfs
-rw-r--r--  1 koie  wheel  524886344  6月 15 23:52 tank-test-freeze.zfs.gz
-rw-r--r--  1 koie  wheel  525564756  6月 16 00:01 tank-test-freeze.zfs.xz
%