送信側(btrfs send)

送信側(btrfs send)

簡単に説明します。映画と音楽の 2 つのサブボリュームがあり、送受信を使用して別のディスクにバックアップしています。2 つのサブボリュームを 1 つにマージし ( を使用cp --reflink)、これを既存のスナップショットから参照リンクされたファイルのクローンを作成してバックアップ ドライブに送信したいと思います。

私は を作成しnew_volumecp -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も試みましたが、 は効果がなく、とにかくデータが送信されるようです。moviesnew_volumecp -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-Amusic-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は、すべてのスナップショットが読み取り専用読み取り専用のサブボリューム/スナップショットは通常-rbtrfs subvolume snapshot -r <subvol> <snap>、 それでもbtrfs property set <snap> ro true/false作成後にフラグを変更する場合にも使用できます。

btrfs send受信側に何があるか、何がないかについてはまったく考慮されていません。これは、rsyncbtrfs の送信/受信が同時に実行されず、代わりにそれぞれが異なる時間にファイルの読み取り/書き込みを実行する場合のように、側間で双方向通信がないため避けられません。

親は一人しかいない

マニュアルページそして(古い)ウィキFAQ残念ながら、かなり混乱を招きます。btrfs-clone 主張するbtrfsの送受信はせいぜい考慮できる1つ増分転送の親。親は、直接指定することも-p、1 つまたは複数の-cオプションを介して間接的に指定することもできます。

btrfs-sendbtrfs-tools 4.13 からサブボリューム S の親と指定されたクローンソース C_i のセットを選択します。このような:

  1. -pオプションが指定されている場合はそれを使用する
  2. Sが設定されていない場合parent_uuid、またはこのUUIDが見つからない場合は、諦めます
  3. (Sが子(スナップショット)であるサブボリュームを「ママ」と呼ぶことにしましょう)C_iがある場合は、それを使用しますC_i->uuid == S->parent_uuid
  4. Sと同じC_iがない場合はparent_uuid諦める
  5. ctransid「ママ」の子供であるすべての C_i から、 「ママ」に最も近い世代 (実際には、「世代」との違いは正確には何でしょうか?)を持つものを選択します。

ご了承くださいウィキ少し誤解を招く恐れがあります。なぜなら、 -cwithout はwithpとは異なると示唆しているからです。ただし、これは上記のアルゴリズムによって通常は暗示されています。唯一の関連する例外は、親を持たないサブボリュームを送信することです。-c-p-p

要約すると、 と を介して常に 1 つの親を明示的に指定し、には「2 つの親」という概念が存在しないことから、-pを無視することをお勧めします。-cbtrfs receive

受信側(btrfs receive

btrfs-receiveman ページでは、プログラムの目的が次のように説明されています。

変更のストリームを受信し、以前に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 UUIDParent UUID

btrfs receiveこれらのIDは、「受信側」<parent>スナップショットが存在するかどうかを確認するのに十分です。すべき送信側<parent>スナップショットと完全に同一である必要があります。Received UUID送信側親のUUIDと同等である必要があるため、そこから作成されたことが保証され、関連するすべてのスナップショットが読み取り専用ステータスであるため、いけないその間に何か変化はありましたか。

(補足: 2 つの親ボリュームの片側にのみ受信 UUID エントリが含まれていますが、btrfs の送信/受信は「変更のストリーム」でこのメタデータを提供できるほどスマートであるため、ユーザーのニーズに応じて、両方の側/ファイル システムが「送信」側または「受信」側として機能する可能性があります)

2 つのサブボリューム/スナップショットをマージする方法 (< v5.14.2)

これまで見てきたように、 のみではマージは不可能ですが、と を新しいサブボリュームの下に結合し、受信側でもと が完全にミラーリングされていると仮定するbtrfs send/receiveと、手動で行うのはかなり簡単です。moviesmusicunifiedmoviesmusic

  1. 送信側に新しい(空の)サブボリュームを作成します。btrfs subvolume create unified
  2. 読み取り専用に変更します:btrfs property set unified ro true
  3. バックアップに送信:btrfs send /path/to/unified | btrfs receive /receiving/side/
  4. 読み取り専用を無効にする両側に(例:btrfs property set /path/to/unified ro false送信側)
  5. 手動での--reflink内容musicmoviesunified 両側に cp -a --reflink /path/to/music /path/to/movies /path/to/unified/
  6. セット両側unifiedスナップショットを読み取り専用に戻すbtrfs property set /path/to/unified ro true
  7. 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サブボリュームと受信側のスナップショットの両方が同一になり、サブボリュームが正常にマージされます。

関連情報