ぶていのログでぶログ

思い出したが吉日

ZFSの重複排除の範囲を調べる

ZFSの重複排除機能がどの範囲で有効なのか(ボリューム?プール?ディレクトリ?)気になったので調べてみた。

環境

調査

準備

適当にボリュームを作成

# zfs list
NAME   USED  AVAIL  REFER  MOUNTPOINT
vol    104K  1000G    31K  /vol
# zfs create vol/test
# zfs list
NAME       USED  AVAIL  REFER  MOUNTPOINT
vol        141K  1000G    30K  /vol
vol/test    30K  1000G    30K  /vol/test

重複排除を有効化

# zfs set dedup=on vol/test
# zfs get all vol/test
NAME      PROPERTY              VALUE                  SOURCE
vol/test  type                  filesystem             -
vol/test  creation              Thu Apr 11 21:05 2013  -
vol/test  used                  30K                    -
vol/test  available             1000G                  -
vol/test  referenced            30K                    -
vol/test  compressratio         1.00x                  -
vol/test  mounted               yes                    -
vol/test  quota                 none                   default
vol/test  reservation           none                   default
vol/test  recordsize            128K                   default
vol/test  mountpoint            /vol/test              default
vol/test  sharenfs              off                    default
vol/test  checksum              on                     default
vol/test  compression           off                    default
vol/test  atime                 on                     default
vol/test  devices               on                     default
vol/test  exec                  on                     default
vol/test  setuid                on                     default
vol/test  readonly              off                    default
vol/test  zoned                 off                    default
vol/test  snapdir               hidden                 default
vol/test  aclinherit            restricted             default
vol/test  canmount              on                     default
vol/test  xattr                 on                     default
vol/test  copies                1                      default
vol/test  version               5                      -
vol/test  utf8only              off                    -
vol/test  normalization         none                   -
vol/test  casesensitivity       sensitive              -
vol/test  vscan                 off                    default
vol/test  nbmand                off                    default
vol/test  sharesmb              off                    default
vol/test  refquota              none                   default
vol/test  refreservation        none                   default
vol/test  primarycache          all                    default
vol/test  secondarycache        all                    default
vol/test  usedbysnapshots       0                      -
vol/test  usedbydataset         30K                    -
vol/test  usedbychildren        0                      -
vol/test  usedbyrefreservation  0                      -
vol/test  logbias               latency                default
vol/test  dedup                 on                     local
vol/test  mlslabel              none                   default
vol/test  sync                  standard               default
vol/test  refcompressratio      1.00x                  -
vol/test  written               30K                    -
vol/test  snapdev               hidden                 default

重複排除の確認

まずは重複排除が動作するか確認(確実に動くだろうけど一応…)

# dd if=/dev/urandom of=test bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 275.28 s, 3.9 MB/s

# ls -lh
total 1.1G
-rw-r--r-- 1 root root 1.0G Apr 11 21:12 test

# zfs list
NAME       USED  AVAIL  REFER  MOUNTPOINT
vol       1.00G   999G    31K  /vol
vol/test  1.00G   999G  1.00G  /vol/test

ファイルをコピーしてみる

# cp test test2
# ls -lh
total 2.1G
-rw-r--r-- 1 root root 1.0G Apr 11 21:12 test
-rw-r--r-- 1 root root 1.0G Apr 11 21:13 test2

# zfs list
NAME       USED  AVAIL  REFER  MOUNTPOINT
vol       2.00G   999G    31K  /vol
vol/test  2.00G   999G  2.00G  /vol/test

ってな感じで、見た目上は1GBのファイルが2つできているがファイルシステム上では、 1GBしか使用していない。

zdbでも確認してみる。

# zdb -S vol
Simulated DDT histogram:

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     2       8K      1G      1G      1G      16K      2G      2G      2G
 Total       8K      1G      1G      1G      16K      2G      2G      2G

dedup = 2.00, compress = 1.00, copies = 1.00, dedup * compress / copies = 2.00

dedupが2.00になっており、200%(って書き方はおかしいけど)の効果を発揮していることがわかる。

一つ上の階層で試してみる

vol/ 直下にテストファイルをコピーしてみる。 この領域は重複排除がOFFになっているのでこちらは単純増加するはず。

# cp test ../test3
# ls -lh ../
total 1.1G
drwxr-xr-x 2 root root    4 Apr 11 21:13 test
-rw-r--r-- 1 root root 1.0G Apr 11 21:23 test3

# zfs list
NAME       USED  AVAIL  REFER  MOUNTPOINT
vol       3.01G   998G  1.00G  /vol
vol/test  2.00G   998G  2.00G  /vol/test

# zdb -S vol
Simulated DDT histogram:

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1       8K      1G      1G      1G       8K      1G      1G      1G
     2       8K      1G      1G      1G      16K      2G      2G      2G
 Total      16K      2G      2G      2G      24K      3G      3G      3G

dedup = 1.50, compress = 1.00, copies = 1.00, dedup * compress / copies = 1.50

予想通りの結果

ディレクトリ配下にコピーしてみる

vol/testボリューム配下にディレクトリを作成し、その下にコピーしてみる。

# mkdir dir1
# cp test dir1/test4
# ls -lh dir1/
total 1.1G
-rw-r--r-- 1 root root 1.0G Apr 11 21:26 test4

# zfs list
NAME       USED  AVAIL  REFER  MOUNTPOINT
vol       4.01G   998G  1.00G  /vol
vol/test  3.00G   998G  3.00G  /vol/test

# zdb -S vol
Simulated DDT histogram:

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1       8K      1G      1G      1G       8K      1G      1G      1G
     2       8K      1G      1G      1G      24K      3G      3G      3G
 Total      16K      2G      2G      2G      32K      4G      4G      4G

dedup = 2.00, compress = 1.00, copies = 1.00, dedup * compress / copies = 2.00

この場合でも、重複排除が働くことがわかる。

別のボリュームにコピーしてみる

新しいボリュームを作成し、そちらへコピーしてみる。 この時、新しいボリュームでも重複排除機能を有効化する。

# zfs create vol/test2
# zfs set dedup=on vol/test2
# ls -lhd ../test2
drwxr-xr-x 2 root root 2 Apr 11 21:28 ../test2

# cp test ../test2/test5
# zfs list
NAME        USED  AVAIL  REFER  MOUNTPOINT
vol        5.01G   998G  1.00G  /vol
vol/test   3.00G   998G  3.00G  /vol/test
vol/test2  1.00G   998G  1.00G  /vol/test2

# zdb -S vol
Simulated DDT histogram:

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
------   ------   -----   -----   -----   ------   -----   -----   -----
     1       8K      1G      1G      1G       8K      1G      1G      1G
     4       8K      1G      1G      1G      32K      4G      4G      4G
 Total      16K      2G      2G      2G      40K      5G      5G      5G

dedup = 2.50, compress = 1.00, copies = 1.00, dedup * compress / copies = 2.50

別のボリュームでも重複排除が働いた! これは予想外。

重複排除のメタデータはプール毎に持っているので、別々のボリュームになっても機能するということかな?

参考