발신자( btrfs send)

발신자( btrfs send)

곧 설명하겠습니다. 전송/수신 기능이 있는 다른 디스크에 백업하는 영화와 음악을 위한 두 개의 별도 하위 볼륨이 있습니다. 두 개의 하위 볼륨을 하나로 병합하고( 사용 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)는 상당히 간단한 도구이기 때문입니다.보조 상위 항목을 제공하여 스냅샷을 하나로 "병합"할 수 없습니다.도구 내부에서.

발신자( 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와 마찬가지로 보내기/받기가 동시에 실행되지 않고 오히려 읽기/쓰기가 가능한 것처럼 두 당사자 간에 양방향 통신이 없기 때문에 이는 피할 수 없습니다. 다른 시간에 별도로 파일을 보관하세요.

부모는 하나만 가질 수 있습니다

이것매뉴얼 페이지그리고 (늙은)위키 FAQ불행하게도 꽤 혼란스럽습니다. 저자는btrfs-clone 역설btrfs 보내기 및 받기는 기껏해야 고려할 수 있습니다.하나델타 전송의 상위입니다. 상위 항목은 -p하나 이상의 옵션을 통해 -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하고 무시하는 것이 좋습니다 -c. btrfs receive"두 부모"라는 개념은 전혀 없습니다.

수신 종료( btrfs receive)

이것btrfs-receive매뉴얼 페이지에서는 프로그램의 목적을 다음과 같이 설명합니다.

변경 스트림을 수신하고 이전에 btrfs send로 생성된 하나 이상의 하위 볼륨을 복사합니다.

전체 전송의 경우 새 하위 볼륨이 생성되고, 증분 전송의 경우 <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즉, 이 스냅샷이 이 스냅샷에서 생성되었는지 확인하고 관련된 모든 스냅샷의 읽기 전용 상태는 스냅샷이 존재한다는 것을 의미합니다.해서는 안 된다그 사이 달라진 게 있나요?

(참고: 두 개의 상위 볼륨 중 한쪽에만 수신된 UUID 항목이 포함되어 있지만 btrfs 보내기/받기는 "변경 스트림"에서 이 메타데이터를 제공할 만큼 충분히 똑똑한 것으로 나타나므로 양쪽/파일 시스템이 "보내기" 또는 "보내기" 역할을 할 수 있습니다. 사용자 요구에 따라 "수신" 끝)

두 개의 하위 볼륨/스냅샷을 병합하는 방법(< 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볼륨과 수신 측 스냅샷이 동일해야 하며 하위 볼륨을 성공적으로 병합했습니다.

관련 정보