Chienomi

btrfsのsnapshot/send/receiveの挙動を検証する

snapshot

スナップショットと容量とリネーム(mv)

最初の状態。スナップショットはsharedとされている

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  96.00KiB       0.00B           -  ./test1
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
 192.00KiB       0.00B    96.00KiB  .

ファイルを追加。追加した分以外がsharedで、サイズが増えているのはsnapshotではなくワーキングボリューム。

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  68.00KiB    68.00KiB           -  ./test1/fileC
 164.00KiB    68.00KiB           -  ./test1
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
 260.00KiB    68.00KiB    96.00KiB  .

新規にスナップショットを取ると増えたファイルもsharedに入った。合計で3ファイル分の容量で無駄がない

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  68.00KiB       0.00B           -  ./test1/fileC
 164.00KiB       0.00B           -  ./test1
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
  40.00KiB       0.00B           -  ./snap2/fileA
  56.00KiB       0.00B           -  ./snap2/fileB
  68.00KiB       0.00B           -  ./snap2/fileC
 164.00KiB       0.00B           -  ./snap2
 424.00KiB       0.00B   164.00KiB  .

もう一度ファイルを増やす。

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  68.00KiB       0.00B           -  ./test1/fileC
  20.00KiB    20.00KiB           -  ./test1/fileD
 184.00KiB    20.00KiB           -  ./test1
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
  40.00KiB       0.00B           -  ./snap2/fileA
  56.00KiB       0.00B           -  ./snap2/fileB
  68.00KiB       0.00B           -  ./snap2/fileC
 164.00KiB       0.00B           -  ./snap2
 444.00KiB    20.00KiB   164.00KiB  .

そしてスナップショット。これは準備段階。

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  68.00KiB       0.00B           -  ./test1/fileC
  20.00KiB       0.00B           -  ./test1/fileD
 184.00KiB       0.00B           -  ./test1
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
  40.00KiB       0.00B           -  ./snap2/fileA
  56.00KiB       0.00B           -  ./snap2/fileB
  68.00KiB       0.00B           -  ./snap2/fileC
 164.00KiB       0.00B           -  ./snap2
  40.00KiB       0.00B           -  ./snap3/fileA
  56.00KiB       0.00B           -  ./snap3/fileB
  68.00KiB       0.00B           -  ./snap3/fileC
  20.00KiB       0.00B           -  ./snap3/fileD
 184.00KiB       0.00B           -  ./snap3
 628.00KiB       0.00B   184.00KiB  .

mvしてみると、ファイル名は異なっているが、sharedの量は増えていない。 mvは理解してくれるらしい。ファイル名ではなく実体の問題。

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  68.00KiB       0.00B           -  ./test1/fileC
  20.00KiB       0.00B           -  ./test1/fileE
 184.00KiB       0.00B           -  ./test1
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
  40.00KiB       0.00B           -  ./snap2/fileA
  56.00KiB       0.00B           -  ./snap2/fileB
  68.00KiB       0.00B           -  ./snap2/fileC
 164.00KiB       0.00B           -  ./snap2
  40.00KiB       0.00B           -  ./snap3/fileA
  56.00KiB       0.00B           -  ./snap3/fileB
  68.00KiB       0.00B           -  ./snap3/fileC
  20.00KiB       0.00B           -  ./snap3/fileD
 184.00KiB       0.00B           -  ./snap3
 628.00KiB       0.00B   184.00KiB  .

rsync fileE fileF; rm fileEとしてみた。 やはり、別ファイルとして扱われ、sharedの量が減っている。

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  68.00KiB       0.00B           -  ./test1/fileC
  20.00KiB    20.00KiB           -  ./test1/fileF
 184.00KiB    20.00KiB           -  ./test1
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
  40.00KiB       0.00B           -  ./snap2/fileA
  56.00KiB       0.00B           -  ./snap2/fileB
  68.00KiB       0.00B           -  ./snap2/fileC
 164.00KiB       0.00B           -  ./snap2
  40.00KiB       0.00B           -  ./snap3/fileA
  56.00KiB       0.00B           -  ./snap3/fileB
  68.00KiB       0.00B           -  ./snap3/fileC
  20.00KiB    20.00KiB           -  ./snap3/fileD
 184.00KiB    20.00KiB           -  ./snap3
 628.00KiB    40.00KiB   164.00KiB  .

ちょっと手直し。3つ目のスナップショットを取る前の状態に。

# btrfs subvol delete test1
# mv snap3 test1
# btrfs property set -ts test1 ro false

mvして、ファイルを追加した。

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
  40.00KiB       0.00B           -  ./snap2/fileA
  56.00KiB       0.00B           -  ./snap2/fileB
  68.00KiB       0.00B           -  ./snap2/fileC
 164.00KiB       0.00B           -  ./snap2
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  68.00KiB       0.00B           -  ./test1/fileC
  20.00KiB       0.00B           -  ./test1/fileE
 112.00KiB   112.00KiB           -  ./test1/fileF
 296.00KiB   112.00KiB           -  ./test1
  40.00KiB       0.00B           -  ./snap3/fileA
  56.00KiB       0.00B           -  ./snap3/fileB
  68.00KiB       0.00B           -  ./snap3/fileC
  20.00KiB       0.00B           -  ./snap3/fileD
 184.00KiB       0.00B           -  ./snap3
 740.00KiB   112.00KiB   184.00KiB  .

shareされていないのは追加されたfileFだけ。ここでスナップショットを取っておく。

     Total   Exclusive  Set shared  Filename
  40.00KiB       0.00B           -  ./snap1/fileA
  56.00KiB       0.00B           -  ./snap1/fileB
  96.00KiB       0.00B           -  ./snap1
  40.00KiB       0.00B           -  ./snap2/fileA
  56.00KiB       0.00B           -  ./snap2/fileB
  68.00KiB       0.00B           -  ./snap2/fileC
 164.00KiB       0.00B           -  ./snap2
  40.00KiB       0.00B           -  ./test1/fileA
  56.00KiB       0.00B           -  ./test1/fileB
  68.00KiB       0.00B           -  ./test1/fileC
  20.00KiB       0.00B           -  ./test1/fileE
 112.00KiB       0.00B           -  ./test1/fileF
 296.00KiB       0.00B           -  ./test1
  40.00KiB       0.00B           -  ./snap3/fileA
  56.00KiB       0.00B           -  ./snap3/fileB
  68.00KiB       0.00B           -  ./snap3/fileC
  20.00KiB       0.00B           -  ./snap3/fileD
 184.00KiB       0.00B           -  ./snap3
  40.00KiB       0.00B           -  ./sendsnap-latest/fileA
  56.00KiB       0.00B           -  ./sendsnap-latest/fileB
  68.00KiB       0.00B           -  ./sendsnap-latest/fileC
  20.00KiB       0.00B           -  ./sendsnap-latest/fileE
 112.00KiB       0.00B           -  ./sendsnap-latest/fileF
 296.00KiB       0.00B           -  ./sendsnap-latest
   1.01MiB       0.00B   296.00KiB  .

send/receive

さて、ここからsend/receiveを試してみる。まずはsnapshot-latestの単純な送信

# btrfs send sendsnap-latest > ~/send1
At subvol sendsnap-latest

# ls -l send1
-rw-r--r-- 1 root root 294193  8月 31 12:42 send1

使用量通りと考えていいだろう。 次にsnap3に基づいて作ってみる。容量は差分容量通りといった感じ。

# btrfs send -p snap3 sendsnap-latest > ~/send2
At subvol sendsnap-latest

# ls -l send*
-rw-r--r-- 1 root root 294193  8月 31 12:42 send1
-rw-r--r-- 1 root root 114925  8月 31 12:44 send2

それぞれの差分を作る。

# btrfs send snap1 > ~/sendsnap1
At subvol snap1
# btrfs send -p snap1 snap2 > ~/sendsnap1-2
At subvol snap2
# btrfs send -p snap2 snap3 > ~/sendsnap2-3
At subvol snap3

# ls -l send*
-rw-r--r-- 1 root root 294193  8月 31 12:42 send1
-rw-r--r-- 1 root root 114925  8月 31 12:44 send2
-rw-r--r-- 1 root root  94926  8月 31 12:45 sendsnap1
-rw-r--r-- 1 root root  66551  8月 31 12:45 sendsnap1-2
-rw-r--r-- 1 root root  18576  8月 31 12:45 sendsnap2-3

全サブボリュームを削除してみる。

# for i in *; do btrfs subvol delete $i; done
Delete subvolume (no-commit): '/mnt/1/sendsnap-latest'
Delete subvolume (no-commit): '/mnt/1/snap1'
Delete subvolume (no-commit): '/mnt/1/snap2'
Delete subvolume (no-commit): '/mnt/1/snap3'
Delete subvolume (no-commit): '/mnt/1/test1'

最新ボリュームのsend2をreceiveしてみる。

# btrfs receive . < ~/send2
At snapshot sendsnap-latest
ERROR: cannot find parent subvolume

元になるサブボリュームがないとだめらしい。 順に戻してみる。

# btrfs receive . < ~/sendsnap1
At subvol snap1
# btrfs receive . < ~/sendsnap1-2
At snapshot snap2
# btrfs receive . < ~/sendsnap2-3
At snapshot snap3
# btrfs receive . < ~/send2
At snapshot sendsnap-latest

順当に行える。では、名前が変わったらどうだろう? sendsnap-latestを削除して、ベースになるsend3をリネームしてみる。

# btrfs subvol delete sendsnap-latest/
Delete subvolume (no-commit): '/mnt/1/sendsnap-latest'
# mv snap3 sendsnap-base
# btrfs receive . < ~/send2
At snapshot sendsnap-latest
# ls
sendsnap-base  sendsnap-latest  snap1  snap2

sendsnap-latestはsnap3というサブボリュームに基づいて作られていたが、snap3という名前のサブボリュームは、sendsnap-baseという名前に変更されてしまったため、もうない。 だが、一致する名前はなくても正しく書き戻すことができた。

ls -l sendsnap-latest/
合計 296
-rw------- 1 yek yek  40005  8月 31 12:11 fileA
-rw------- 1 yek yek  54006  8月 31 12:20 fileB
-rw------- 1 yek yek  66006  8月 31 12:22 fileC
-rw------- 1 yek yek  18066  8月 31 12:24 fileE
-rw------- 1 yek yek 114066  8月 31 12:35 fileF

ということは名前ではなく、IDなどで判断しているのだろう。元になったサブボリュームが存在していればOKだ。 では中間がなくなったらどうだろう?

元snap3、元sendsnap-baseだけを残してみる

# btrfs subvol delete sendsnap-latest/
Delete subvolume (no-commit): '/mnt/1/sendsnap-latest'
[mint 1]# btrfs subvol delete snap2
Delete subvolume (no-commit): '/mnt/1/snap2'
[mint 1]# btrfs subvol delete snap1
Delete subvolume (no-commit): '/mnt/1/snap1'
# btrfs fi du .
     Total   Exclusive  Set shared  Filename
  40.00KiB    40.00KiB           -  ./sendsnap-base/fileA
  56.00KiB    56.00KiB           -  ./sendsnap-base/fileB
  68.00KiB    68.00KiB           -  ./sendsnap-base/fileC
  20.00KiB    20.00KiB           -  ./sendsnap-base/fileD
 184.00KiB   184.00KiB           -  ./sendsnap-base
 184.00KiB   184.00KiB       0.00B  .

全くシェアはされていないが、シェアフラグを削除し、データは消していないようだ。 ハードリンクのような仕組みだろうか。

サブボリューム名とシンボリックリンク

では、名前においてsubvol名はシンボリックリンクでも良いのだろうか? send2を戻してリンクしてみる。

# btrfs receive . < ~/send2
At snapshot sendsnap-latest
# ln -s sendsnap-latest/ current
# mount -o subvol=current /dev/mapper/hymaster_1 /mnt/3
# ls /mnt/3
fileA  fileB  fileC  fileE  fileF

こうなった。

マウントするサブボリュームの切り替えは、set-defualtでも良いが、シンボリックリンクを論理的な名前にすることも可能なようだ。