송신 측에서 ( 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-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-A수행 music-A할 수 있습니다.

btrfs send \
    -p movies-A \
    new_volume-A | btrfs receive /backup/

이는 항상 완벽하게 작동합니다(전송된 데이터가 거의 0에 가깝습니다). 하지만...

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 sendrsyncbtrfs 전송/수신이 동시에 실행되지 않고 대신 서로 다른 시간에 실행될 수도 있으므로 수신 측에 무엇이 있는지 없는지 전혀 고려하지 않습니다. 이는 피할 수 없습니다. 파일 읽기/쓰기.

부모는 한 명만 있을 수 있습니다.

그만큼매뉴얼 페이지그리고 (늙은)위키 FAQ불행하게도 오히려 혼란스럽습니다. 저자btrfs-clone 주장하다btrfs가 보내고 받는 것은 최대로 고려할 수 있습니다.하나증분 전송의 상위 항목입니다. 상위 항목은 -p하나 또는 여러 옵션을 통해 직접 지정하거나 간접적으로 지정할 수 있습니다 -c.

btrfs-sendbtrfs-tools 4.13에서 하위 볼륨 S의 상위 볼륨과 지정된 복제 소스 C_i 세트를 선택합니다.이와 같이:

  1. -p옵션이 지정된 경우 해당 옵션을 사용하십시오.
  2. S에 세트가 없거나 parent_uuid이 uuid를 찾을 수 없으면 포기하세요.
  3. C_iwith C_i->uuid == S->parent_uuid(S가 하위 볼륨인 하위 볼륨(스냅샷), "엄마"라고 부르겠습니다)이 있으면 사용하세요.
  4. C_i가 S와 동일하지 않으면 parent_uuid포기
  5. "mom"의 자식인 모든 C_i 중에서 "mom"에 가장 가까운 세대(실제로 ctransid"세대"와 정확히 차이점이 무엇인가요?)를 가진 C_i를 선택합니다.

참고하세요위키이는 약간 오해의 소지가 있습니다. 왜냐하면 일반적으로 위의 알고리즘에 의해 암시 되지만 -c없는 것은 with p와 다르다는 것을 의미하기 때문입니다. 관련된 유일한 예외는 상위 볼륨이 없는 하위 볼륨을 보내는 것입니다.-c-p-p

요약하자면, 항상 를 통해 하나의 부모를 명시적으로 지정 -p하고 무시하는 것이 좋습니다 -c. btrfs receive단순히 "두 부모"라는 개념이 없습니다.

수신 측에서 ( btrfs receive)

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

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

전체 전송의 경우 새 하위 볼륨이 생성되고, 증분 전송의 경우 스냅샷(수신 측 해당)의 새 <parent>스냅샷이 생성됩니다. 두 경우 모두 새로 생성된 하위 볼륨/스냅샷은 처음에읽기 쓰기"변경 스트림"이 btrfs send성공적으로 적용된 후 하위 볼륨/스냅샷이 생성될 때까지 가능합니다.읽기 전용.

분명히 두 개의 부모를 구현할 수 있는 방법은 없습니다. 처음부터 "변경 스트림"에 쓰기 시 복사/재링크 복사본이 없기 때문입니다. 의 스냅샷은 <parent>단순히 "변경 스트림"이 적용되는 기반을 제공합니다.

하지만 수신 측에서는 스냅샷이 송신 측의 스냅샷 <parent>과 동일하다는 것을 어떻게 보장합니까? <parent>그것절대 실제 내용을 확인/비교하지 않습니다스냅샷/하위 볼륨을 사용하는 것이 아니라UUID와 관련된 메타데이터불변성상위 스냅샷에 대한 가정입니다.

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>스냅샷과 완전히 동일해야 합니다. 왜냐하면 Received UUID보내는 쪽 부모의 UUID와 동일해야 하므로 이 스냅샷이 여기에서 생성되었는지 확인하고 관련된 모든 스냅샷의 읽기 전용 상태는 거기에 있음을 의미하기 때문입니다.해서는 안 된다그동안 어떤 변화가 있었나요?

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

두 개의 하위 볼륨/스냅샷을 병합하는 방법(< v5.14.2)

우리가 본 것처럼 병합은 only로는 불가능 하지만 수동으로 수행하는 것은 상당히 쉽습니다. 새로운 하위 볼륨에서 and를 btrfs send/receive결합 하고 수신 측에서도 and가 완전히 미러링된다고 가정하면 다음과 같습니다.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의 관점에서 중요한 것은 양측의 (미래) 부모가 한쪽이 Received UUID다른 쪽을 가리키는 방식으로 연결되고 둘 다 향후 전송 시에만 읽혀진다는 것입니다.

>= v5.14.2에 대해 수행할 작업

그만큼가장 덜 나쁜 해결책이전 섹션의 접근 방식을 따르지만 추가적으로 다음을 Received UUID통해 값을 수동으로 재설정하는 것이 좋습니다.python-btrfs에 의해 설정이 해제된 후 btrfs-properties.

없다좋은표준 btrfs-progs도구만 사용하는 솔루션입니다. "a" 솔루션에 가장 가까운 것은사실생성된 스냅샷은 전송이 완료될 때까지 읽기/쓰기 가능하며 스냅샷이 에 의해 읽기 전용으로 설정되기 전에 복사를 btrfs receive시도합니다 . 즉, 악용하는 것은--reflinkbtrfs-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(또한 클라이언트 쪽) 모두에 존재하기 때문에 추가 음악 디렉터리를 선택합니다 . 이제 IFF를 cp -a --reflink /bkp/to/music /bkp/to/unified/통해 수신 측(!)에서 새 unified스냅샷이 전송되는 동안 읽기 쓰기가 가능해지면 송신 측 unified하위 볼륨과 수신 측 스냅샷이 모두 동일해야 하며 하위 볼륨을 성공적으로 병합했습니다.

관련 정보