発信者( btrfs send)

発信者( btrfs send)

まもなく説明します。転送/受信機能を持つ別のディスクにバックアップする映画と音楽のための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-snapshotmovies-snapshotあります。また、にスナップしてmoviesからその項目に移動し、 を使ってスナップして転送してみましたが、何も機能しないようです。とにかくデータは送信されます。new_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-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から別のスナップショット(「子」として機能する)に移動するために必要なコマンドのみが生成されます。これは、両方のスナップショットがまったく関連していない場合でも機能します。

転送側の唯一の要件btrfs sendは、すべてのスナップショットです読み取り専用。読み取り専用サブボリューム/スナップショットは通常、-rオプションで作成されます。btrfs subvolume snapshot -r <subvol> <snap>、しかしbtrfs property set <snap> ro true/false生成後のフラグの変更にも使用できます。

btrfs send受信側に何があるかにかかわらず、rsyncbtrfsと同様に、送受信は同時に実行されず、むしろ読み書きが可能であるかのように、両当事者間に双方向通信がないため、これは避けられません。別の時間に別々にファイルを保存してください。

親は1つしか持てません

これマニュアルページそして(古い)Wiki FAQ残念ながら、かなり混乱しています。著者はbtrfs-clone パラドックスbtrfsの送受信はせいぜい考慮することができます。一つデルタ転送の親です。親項目は、-p1 つ以上のオプションで-c直接または間接的に指定できます。

btrfs-sendbtrfs-tools 4.13で、サブボリュームSの親ボリュームと指定された複製ソースセットC_iを選択します。このように:

  1. オプションを指定すると-p使用されます。
  2. Sにセットがない場合、またはparent_uuiduuidが見つからない場合は放棄してください。
  3. C_iある場合C_i->uuid == S->parent_uuid(Sはサブボリュームのサブボリューム(スナップショット)なので「ママ」と呼びます)を使用します。
  4. C_iがSと等しくない場合はparent_uuidあきらめてください。
  5. "母"のすべての子供C_iの中から"母"に最も近い世代を選択します(実際に、ctransidと"世代"の違いは何ですか?)。

気づくウィキペディア上記のアルゴリズムは通常これを暗示していますが、-cwithはwithとは異なることを示唆しているため、少し誤解を招く可能性があります。p関連する唯一の例外は、親ボリュームなしで子ボリュームを送信することです。-c-p-p

要約すると、常に明示的に親を指定して-p無視することをお勧めします-cbtrfs receive「両親」という概念はまったくありません。

受信終了(btrfs receive

これbtrfs-receiveマニュアルページでは、プログラムの目的を次のように説明します。

変更ストリームを受け取り、以前にbtrfs sendで作成された1つ以上のサブボリュームをコピーします。

フル転送の場合は新しいサブボリュームが作成され、増分転送の場合はスナップショット<parent>の新しいスナップショット(受信側に対応)が作成されます。どちらの場合も、新しく作成されたサブボリューム/スナップショットは最初に読み書きbtrfs sendサブボリューム/スナップショットは、「変更ストリーム」が完了するまで作成されません。読み取り専用

明らかに、最初は「変更ストリーム」に書き込むときにコピー/参照リンクのコピーがないため、両親を実装する方法はありません。スナップショットは、<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

これらのIDは、「受信者」スナップショットがbtrfs receiveあることを確認するのに十分です。<parent>しなければならない<parent>送信者の親のUUIDと同じでなければならないという点で、「送信者」スナップショットとまったく同じです。Received UUIDつまり、このスナップショットがこのスナップショットから作成されたことを確認し、関連するすべてのスナップショットの読み取り専用状態は、スナップショットが存在することを意味します。してはいけないその間変わったことがありますか?

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

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

ご覧のように、usingだけをマージすることはできませんが、新しいサブボリュームの下の合計をマージし、合計が受信側でも完全にミラーリングされていると仮定すると、手動で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両側

musicmovies新しい/空のサブボリュームを作成して送信するのではなく、既存のサブボリュームまたはスナップショットを使用して手順4から始めることもできます。 btrfsの観点から重要なのは、両親(未来)が一方がReceived UUID他方を指すように接続されており、両方が将来の転送でのみ読み取られるということです。

>= v5.14.2 すべきこと

これ最も悪い解決策おそらく前のセクションの方法に従いますが、さらに次のようにReceived UUID値を手動でリセットできます。python-btrfs設定をキャンセルした後btrfs-properties

いいえいいね標準ツールのみを使用するbtrfs-progsソリューションです。 「a」の解決策に最も近いのは、次のことを活用することです。事実btrfs receive転送が完了する前に作成されたスナップショットは読み取り/書き込みが可能であり、スナップショットが読み取り専用に--reflink設定される前にコピーが試行されますbtrfs-receive。つまり、競争条件現在、btrfs-progs> = 5.14.2標準ツールを使用してこれを行う唯一の方法です。

明らかに本当に必要なのは、誰かが自分が何をしているのかを知っている人のために5.14.2以前に可能であったように、少なくともマージを許可するためにbtrfsプロジェクトに機能要求を送信することです。

とにかく競争条件のエクスプロイトは次のとおりです。送信側スナップショットの読み取り専用状態を変更し続けることができるため、そのスナップショットを変更できます。

moviesコピーを使用して再接続し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ボリュームと受信側スナップショットは同じでなければならず、サブボリュームを正常にマージしました。

関連情報