데이터를 복제하지 않고 여러 스냅샷을 한 번에 복사하는 방법은 무엇입니까?

데이터를 복제하지 않고 여러 스냅샷을 한 번에 복사하는 방법은 무엇입니까?

오래된 스냅샷과 새로운 4TB 백업 드라이브를 포함하여 90%가 넘는 3.7TiB 라이브 btrfs 파일 시스템이 있습니다. 기존 스냅샷을 모두 백업 하드 드라이브에 복사하는 방법은 무엇입니까?

나는 노력했다

# btrfs send home_1 home_2 home_3 share_1 share_2 share_3 ...

그러나 스냅샷의 2/3가 전송되기 전에 백업 하드 드라이브가 가득 찼습니다. 그래서 저는 몇 가지 조사를 했습니다.

# ### create test image
# dd bs=1M count=1000 > btrfs_test.dd
# mkfs.btrfs btrfs_test.dd

# ### create snapshots
# btrfs subvol create testvol/
# btrfs subvol snapshot -r testvol/ testvol_0/
# ### (copy some ISO image)
# btrfs subvol snapshot -r testvol/ testvol_1/
# ### (proceed until testvol_3)

내 테스트 파일 시스템은 818MiB를 사용하여 91% 가득 찼습니다.

# btrfs send testvol_* | wc -c 
At subvol testvol_0
At subvol testvol_1
At subvol testvol_2
At subvol testvol_3
1466441978     # 1398MiB >> 1000MiB

단순히 한 번의 명령으로 모든 스냅샷을 전송하면 데이터가 중복되어 스트림의 크기는 물론 수신 측의 스냅샷 크기도 원래 사용했던 공간과 하드 디스크의 용량을 초과하게 됩니다.

따라서 실제 질문은 다음과 같습니다.2개 이상의 스냅샷에 포함된 데이터를 복사하지 않고 여러 스냅샷을 복사하려면 어떻게 해야 합니까?

이 간단한 테스트 사례에서는 점진적인 접근 방식을 성공적으로 시도했습니다.

# ( btrfs send testvol_0; btrfs send -p testvol_0 testvol_1; btrfs send -p testvol_1 testvol_2; btrfs send -p testvol_2 testvol_3 ) | wc -c 
At subvol testvol_0
At subvol testvol_1
At subvol testvol_2
At subvol testvol_3
838778546    # 800 MiB < 1000MiB

그러나 실제 파일 시스템에는 여러 하위 볼륨이 있고 각 하위 볼륨에는 여러 스냅샷이 있습니다. 와 함께 사용할 순서를 정의할 수 없습니다 -p. 물론 데이터 블록이 하위 볼륨 간에 공유되고 home_1이를 한 번만 전송하고 저장하고 싶다면 home_2. share_3이 작업을 수행하는 방법에 대한 아이디어가 있습니까?

답변1

간단히 말해서:일반적으로 -c상단에 설명된 매개변수를 사용하는 것이 유효합니다. 스냅샷에 하드 링크가 포함된 경우 스냅샷을 보낼 때 오류를 유발하는 Linux 커널 버그가 있습니다. 자세한 내용은 답변 끝에 있는 결론을 참조하세요.


이 매개변수를 시도 중인데 -c유망해 보입니다.

# for i in {0..3}; do btrfs send testvol_$i $(ls -d testvol_* | head -n$i | sed 's/^/-c /'); done | wc -c
### btrfs send testvol_0
### btrfs send testvol_1 -c testvol_0
### btrfs send testvol_2 -c testvol_0 -c testvol_1
### btrfs send testvol_3 -c testvol_0 -c testvol_1 -c testvol_2
At subvol testvol_0
At subvol testvol_1
At subvol testvol_2
At subvol testvol_3
838778546    # also 800MiB

이것이 나에게 필요한 것인지 아직 잘 모르겠습니다. 이 솔루션에 대한 의견이 있으십니까?

고쳐 쓰다:실제 파일 시스템에서 이것을 테스트하기 위해 하위 볼륨 세트를 쉽게 보내고(목록 작성은 -c빨리 지루해짐) 일부 데이터를 다음으로 보내는 Perl 스크립트를 작성했습니다 /dev/null.

#!/usr/bin/env perl

use strict;
use warnings;

my @subvols = @ARGV
  or die "Usage: $0 SUBVOLUME ...\n";

for(@subvols) {
    -d $_
      or die "Not a directory: $_\n";
}

for my $i (0 .. $#subvols) {
    my $subvol = $subvols[$i];
    my @clones = map { ('-c', $_) } @subvols[ 0 .. $i-1 ];
    print "btrfs send $subvol @clones\n";
}

결과:

  • btrfs send some-subvolme_* | pv > /dev/null:24GiB 0:04:17 [95.2MiB/초]
  • perl btrfs-send-all.pl some-subvolume_* | bash | pv > /dev/null:12.7GiB 0:03:58 [54.7MiB/초]

이로 인해 성능이 크게 향상되지는 않지만 거의저장 공간이 50% 감소했습니다.! 이제 실제로 실행해 보려고 하는데...

고쳐 쓰다:2개의 스냅샷을 성공적으로 전송했지만 세 번째 스냅샷은 btrfs receive다음 오류 메시지와 함께 실패했습니다.

ERROR: unlink path/to/some/file/in/the/snapshot failed. No such file or directory

지정된 파일이 subvol_2및 에 존재 subvol_3하지만아니요그러나 subvol_1.

전송된 스냅샷과 수신된 스냅샷을 비교하려고 합니다.

# ### sender
# du -s subvol_{1,2,3}
132472304       subvol_1
117069504       subvol_2
126015636       subvol_3

# ### receiver
# du -s subvol_*
132472304       subvol_1
117069504       subvol_2
132472304       subvol_3

처음 두 스냅샷은 올바르게 전송되는 것처럼 보이지만 subvol_3실제로는 subvol_1백업 디스크에서 사용된 공간이 스냅샷 전체 크기의 39%에 불과하므로 이는 확실히 복제입니다. 대부분의 파일을 공유합니다.

btrfs send subvol_3 -c subvol_1 -c subvol_2 | btrfs receive스냅샷이 올바르게 전송되지 않는데 복제가 보관해야 하고 존재하는 파일만 삭제하지 못하는 이유는 무엇입니까 subvol_1?subvol_3subvol_2

고쳐 쓰다:이 버그가 아닐까?https://patchwork.kernel.org/patch/10073969/

저는 커널 4.9로 Debian 9 Stretch를 실행하고 있는데 패치보다 오래된 것 같습니다.

고쳐 쓰다:해결책을 찾을 수 없었기 때문에 각 하위 볼륨의 최신 스냅샷을 복사했습니다. 그런 다음 약 500GiB의 여유 공간이 있고 복사된 스냅샷을 -p매개변수로 사용하여 이전 스냅샷을 추가하려고 합니다. 그런 다음 위와 동일한 스냅샷에 대해 동일한 오류 메시지가 표시되었습니다.

결론적으로:내 결론은 위에 링크된 오류가 발생했다는 것입니다. 최신 Linux 커널로 이 시스템을 재부팅하거나 다른 컴퓨터에서 파일 시스템에 액세스해야 하지만 이는 프로덕션 시스템이므로 불가능합니다.

지금까지 btrfs에 문제가 없었지만 rsnapshot(많은 하드 링크를 생성함)을 실행하고 btrfs 스냅샷을 보내는 것은 현재 데비안 안정 릴리스에서 여전히 문제가 될 수 있습니다.

관련 정보