簡単に説明します。映画と音楽の 2 つのサブボリュームがあり、送受信を使用して別のディスクにバックアップしています。2 つのサブボリュームを 1 つにマージし ( を使用cp --reflink
)、これを既存のスナップショットから参照リンクされたファイルのクローンを作成してバックアップ ドライブに送信したいと思います。
私は を作成しnew_volume
、cp -rx --reflink "music" "movies"
その中に入れ、そして:
btrfs send \
-c music-snapshot \
-c movies-snapshot \
new_volume-snapshot | btrfs receive /path/to/backup
new_volume
しかし、 (ID で識別される)の親を特定できないというエラーが表示されます。
ERROR: parent determination failed for <id_number>
もちろん、バックアップにはmusic-snapshot
と が存在します。にスナップショットを作成し、にスナップショットを作成し、 でスナップショットを作成して送信することmovies-snapshot
も試みましたが、 は効果がなく、とにかくデータが送信されるようです。movies
new_volume
cp -rx --reflink "music"
btrfs send -c music-snapshot -p movies-snapshot new_volume-snapshot
-c music-snapshot
私がやりたいことは可能なのでしょうか?
編集: 私もこれを試してみました:
btrfs sub snap -r movies movies-A
btrfs sub snap -r music music-A
btrfs sub snap movies new_volume
btrfs sub snap -r new_volume new_volume-A
この時点で私は次のことを持っています:
movies-A
music-A
new_volume-A (exact clone of movies-A)
それから:
cp -rx --reflink music/* new_volume/
btrfs sub snap -r new_volume new_volume-B
最終的に、宛先に と の両方が存在する場合movies-A
、music-A
次の操作を実行できます。
btrfs send \
-p movies-A \
new_volume-A | btrfs receive /backup/
そして、これは常に完璧に機能しています (送信されるデータはほぼゼロです)。しかし...
btrfs send \
-p new_volume-A \
-c music-A \
new_volume-B | btrfs receive /backup/
どう説明すればいいのかわかりません。「一部のファイル」ではmusic
動作しますが、他のファイルでは、ソースを無視したままデータを送信し続けます。この方法は間違いなく動作するはずですが、「動作する」動作も「動作しない」動作も確実に再現できません。どこかにバグがあるのではないかと考えています。誰かこれを試してみませんか?
答え1
(免責事項:lgaudinoのコメントによると、提案されたマージ方法はbtrfs-progsでは機能しなくなったとのことです>=v5.14.2変更されたためbtrfs プロパティスナップショットの読み取り専用ステータスを変更するときの動作)
望むことは達成できるが、直接的には達成できない。なぜなら、btrfs send
(とbtrfs receive
)はかなり単純なツールだからである。セカンダリ親を提供することでスナップショットを1つに「マージ」する方法はありません。ツールの内部から。
送信側(btrfs send
)
btrfs send
出力ファイルシステムレベルの操作(ディレクトリ/ファイルの作成、メタデータの転送、ファイルの内容の転送など)は、btrfs receive
「受信側」で別のbtrfsファイルシステムに同等のスナップショットを作成するために使用できます。これらの操作は、「ドライラン」を実行することで確認できます。btrfs receive --dump
。
アン増分send (例btrfs send -p <parent> <snapshot>
) は、 に関する限りまったく同じように動作しますが、の変更 (ディレクトリ/ファイルの追加/削除、メタデータの更新) によるbtrfs send
作成に必要なファイル システム操作のみが記録されます。<snapshot>
<parent>
また、特別な「親子」関係のチェックも行われません。-p
パラメータが「親」を指定するために使用されていると仮定すると、btrfs send
そのスナップショットから別のスナップショット(「子」として動作)に移動するために必要なコマンドが生成されるだけです。これは、2 つのスナップショットがまったく関連していない場合でも機能します。
送信側で唯一の要件btrfs send
は、すべてのスナップショットが読み取り専用読み取り専用のサブボリューム/スナップショットは通常-r
、btrfs subvolume snapshot -r <subvol> <snap>
、 それでもbtrfs property set <snap> ro true/false
作成後にフラグを変更する場合にも使用できます。
btrfs send
受信側に何があるか、何がないかについてはまったく考慮されていません。これは、rsync
btrfs の送信/受信が同時に実行されず、代わりにそれぞれが異なる時間にファイルの読み取り/書き込みを実行する場合のように、側間で双方向通信がないため避けられません。
親は一人しかいない
のマニュアルページそして(古い)ウィキFAQ残念ながら、かなり混乱を招きます。btrfs-clone
主張するbtrfsの送受信はせいぜい考慮できる1つ増分転送の親。親は、直接指定することも-p
、1 つまたは複数の-c
オプションを介して間接的に指定することもできます。
btrfs-send
btrfs-tools 4.13 からサブボリューム S の親と指定されたクローンソース C_i のセットを選択します。このような:
-p
オプションが指定されている場合はそれを使用する- Sが設定されていない場合
parent_uuid
、またはこのUUIDが見つからない場合は、諦めます- (Sが子(スナップショット)であるサブボリュームを「ママ」と呼ぶことにしましょう)
C_i
がある場合は、それを使用しますC_i->uuid == S->parent_uuid
- Sと同じC_iがない場合は
parent_uuid
諦めるctransid
「ママ」の子供であるすべての C_i から、 「ママ」に最も近い世代 (実際には、「世代」との違いは正確には何でしょうか?)を持つものを選択します。ご了承くださいウィキ少し誤解を招く恐れがあります。なぜなら、
-c
without はwithp
とは異なると示唆しているからです。ただし、これは上記のアルゴリズムによって通常は暗示されています。唯一の関連する例外は、親を持たないサブボリュームを送信することです。-c
-p
-p
要約すると、 と を介して常に 1 つの親を明示的に指定し、には「2 つの親」という概念が存在しないことから、-p
を無視することをお勧めします。-c
btrfs receive
受信側(btrfs receive
)
のbtrfs-receive
man ページでは、プログラムの目的が次のように説明されています。
変更のストリームを受信し、以前にbtrfs sendによって生成された1つ以上のサブボリュームを複製します。
完全転送の場合は新しいサブボリュームが作成され、増分転送の場合はスナップショット(受信側相当)の新しいスナップショットが<parent>
作成されます。どちらの場合も、新しく作成されたサブボリューム/スナップショットは、最初は読み書きから発生する「変更のストリーム」がbtrfs send
正常に適用された後、サブボリューム/スナップショットが作成されます。読み取り専用。
明らかに、2 つの親を実装する方法はありません。これは、そもそも「変更のストリーム」にコピーオンライト/参照リンクのコピーがないためです。 のスナップショットは、<parent>
単に「変更のストリーム」が適用されるベースを提供します。
しかし、受信側はどのようにしてスナップショットが送信側のスナップショット<parent>
と同一であることを保証するのでしょうか?<parent>
実際の内容を確認/比較しないスナップショット/サブボリュームではなく、言語メタデータに関連する不変性親スナップショットの仮定。
btrfs subvolume show <subvolume>
次のような出力が得られます。
/mnt/btrfs/subvolume
Name: subvolume
UUID: 5e076a14-4e42-254d-ac8e-55bebea982d1
Parent UUID: -
Received UUID: -
Creation time: 2018-01-01 12:34:56 +0000
Subvolume ID: 79
Generation: 2844
Gen at creation: 2844
Parent ID: 5
Top level ID: 5
Flags: -
Snapshot(s):
すべてのサブボリューム/スナップショットには 3 つの UUID スロットがあり、そのうち 2 つは空の場合があります。 によって作成されたすべてのスナップショットには、その親を明確に識別する がbtrfs subvolume snapshot
常に含まれParent UUID
、 によって作成されたすべてのスナップショットには、btrfs receive
常にReceived UUID
エントリが含まれます。完全転送の場合はエントリが含まれず、増分転送の場合はエントリとエントリのParent UUID
両方が含まれます。UUID エントリは、ユーザーが手動で変更することはできません。Received UUID
Parent UUID
btrfs receive
これらのIDは、「受信側」<parent>
スナップショットが存在するかどうかを確認するのに十分です。すべき送信側<parent>
スナップショットと完全に同一である必要があります。Received UUID
送信側親のUUIDと同等である必要があるため、そこから作成されたことが保証され、関連するすべてのスナップショットが読み取り専用ステータスであるため、いけないその間に何か変化はありましたか。
(補足: 2 つの親ボリュームの片側にのみ受信 UUID エントリが含まれていますが、btrfs の送信/受信は「変更のストリーム」でこのメタデータを提供できるほどスマートであるため、ユーザーのニーズに応じて、両方の側/ファイル システムが「送信」側または「受信」側として機能する可能性があります)
2 つのサブボリューム/スナップショットをマージする方法 (< v5.14.2)
これまで見てきたように、 のみではマージは不可能ですが、と を新しいサブボリュームの下に結合し、受信側でもと が完全にミラーリングされていると仮定するbtrfs send/receive
と、手動で行うのはかなり簡単です。movies
music
unified
movies
music
- 送信側に新しい(空の)サブボリュームを作成します。
btrfs subvolume create unified
- 読み取り専用に変更します:
btrfs property set unified ro true
- バックアップに送信:
btrfs send /path/to/unified | btrfs receive /receiving/side/
- 読み取り専用を無効にする両側に(例:
btrfs property set /path/to/unified ro false
送信側) - 手動での
--reflink
内容music
をmovies
unified
両側にcp -a --reflink /path/to/music /path/to/movies /path/to/unified/
- セット両側の
unified
スナップショットを読み取り専用に戻すbtrfs property set /path/to/unified ro true
unified
対話するための新しい読み取り書き込みスナップショットを作成し、unified
将来の増分転送の親として機能します。両側。
新しい/空のサブボリュームを作成して送信する代わりに、既存のサブボリュームmusic
またはmovies
スナップショットからステップ 4 から開始することもできます。btrfs の観点からは、2 つの側の (将来の) 親が一方から他方Received UUID
への接続を介して接続され、将来の転送時に両方が読み取り専用になることだけが重要です。
>= v5.14.2 の場合の対処方法
の最も悪い解決策ではないおそらく、前のセクションのアプローチに従うが、さらに手動でReceived UUID
値をリセットすることになるだろう。python-btrfs
によって設定解除された後btrfs-properties
。
ありません良い標準的なbtrfs-progs
ツールだけを使った解決策。「解決策」に最も近いのは、事実btrfs receive
転送が完了するまでは、作成されたスナップショットは読み取り書き込み可能であり、--reflink
スナップショットが読み取り専用に設定される前にコピーを実行しようとしていますbtrfs-receive
。言い換えれば、競合状態現時点では、btrfs-progs >=5.14.2 標準ツールのみを使用してこれを行う唯一の方法です。
しかし、明らかに本当に必要なのは、誰かが btrfs プロジェクトに機能リクエストを行い、何をしているのかわかっている人のために、少なくとも 5.14.2 より前と同じようにマージを許可することです。
とにかく、競合状態のエクスプロイトは次のようになるでしょう。送信側でスナップショットの読み取り専用ステータスを変更できるため、そのスナップショットを変更できます。たとえば、
使用しmovies
てreflinkコピーmusic
します:
btrfs property set -f movies ro false
cp -a --reflink /path/to/music /path/to/movies/
btrfs property set -f /path/to/movies ro true
btrfs subvolume snapshot /path/to/movies /path/to/unified_prep
必要に応じて、ディレクトリとファイルunified_prep
(ただし、音楽ディレクトリはそのままにしておきます)を移動し、準備ができたら次の操作を行います。
btrfs subvolume snapshot -r /path/to/unified_prep /path/to/unified
btrfs send -p /path/to/movies /path/to/unified | btrfs receive /path/to/backups/
btrfs send
そしてbtrfs receive
すべきだないmovies
追加の音楽ディレクトリは、送信側とunified
クライアント側の両方に存在するため、これを選択します。ここで、cp -a --reflink /bkp/to/music /bkp/to/unified/
新しいunified
スナップショットがまだ転送中で読み取り/書き込み可能な状態で受信側で処理できれば、送信側のunified
サブボリュームと受信側のスナップショットの両方が同一になり、サブボリュームが正常にマージされます。