Linux에서 희소 파일이 있는 경우 이를 희소하지 않은 파일로 만드는 방법은 무엇입니까?
copy 를 사용할 수 있지만 cp --sparse=never ...
파일이 10G이고 홀이 2G인 경우(즉, 할당된 공간이 8G인 경우) 원본 8G를 새 파일에 복사하지 않고 파일 시스템이 나머지 2G를 할당하도록 어떻게 할 수 있습니까?
답변1
표면적으로 이것은 간단합니다 dd
.
dd if=sparsefile of=sparsefile conv=notrunc bs=1M
전체 파일을 읽고 전체 내용을 다시 씁니다.
구멍 자체만 쓰려면 먼저 구멍이 어디에 있는지 확인해야 합니다. filefrag
또는 다음 을 사용하여 이 작업을 수행할 수 있습니다 hdparm
.
파일 조각:
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1048575: 187357696.. 188406271: 1048576:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188406272: last,eof
sparsefile: 2 extents found
HD 매개변수:
# hdparm --fibmap sparsefile
sparsefile:
filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
byte_offset begin_LBA end_LBA sectors
0 1498861568 1507250175 8388608
6442450944 1605633024 1614021631 8388608
말씀하신 대로 이 예제 파일에는 크기에 구멍이 10G
있습니다 . 2G
여기에는 첫 번째 커버 0-1048575
와 두 번째 커버의 두 가지 범위가 있습니다 1572864-2621439
. 이는 구멍이 1048576-1572864
(그림과 같이 4k 크기의 청크 filefrag
)임을 의미합니다. 표시된 정보 hdparm
는 동일하지만 다르게 표시될 뿐입니다(첫 번째 범위는 8388608
0에서 시작하는 512바이트 섹터를 포함하므로 0-4294967295
바이트이므로 취약점은 4294967296-6442450944
바이트 단위입니다.
조각화가 있는 경우 더 많은 범위를 표시할 수 있습니다. 불행하게도 두 명령 모두 취약점을 직접 표시하지 않으며, 어떤 명령도 취약점을 표시하지 않으므로 표시된 논리적 오프셋에서 이를 추론해야 합니다.
1048576-1572864
이제 적절한 (동일)/값 sum 을 추가하여 위에 표시된 대로 이 구멍을 채울 수 있습니다 . 위에서 사용된 섹터를 사용하도록 조정되었습니다. ( 의 경우 청크 크기를 반영하도록 탐색/건너뛰기/카운트 값을 조정해야 합니다.)dd
seek
skip
count
bs=
4k
filefrag
bs=1M
1M
dd if=sparsefile of=sparsefile conv=notrunc \
bs=4k seek=1048576 skip=1048576 count=$((-1048576+1572864))
파일 자체를 읽는 대신(0만 생성됨) 구멍을 채울 수도 있지만 오프셋이 잘못된 경우 데이터가 손상되지 않도록 /dev/zero
읽는 것이 더 안전합니다 .sparsefile
최신 버전에서는 GNU dd
더 큰 블록 크기를 고수하고 모든 값을 바이트 단위로 지정할 수 있습니다.
dd if=sparsefile of=sparsefile conv=notrunc bs=1M \
iflag=skip_bytes,count_bytes oflag=seek_bytes \
seek=4294967296 skip=4294967296 count=$((-4294967296+6442450944))
filefrag
실행 후:
# sync
# filefrag -e sparsefile
Filesystem type is: 58465342
File size of sparsefile is 10737418240 (2621440 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 1572863: 187357696.. 188930559: 1572864:
1: 1572864.. 2621439: 200704128.. 201752703: 1048576: 188930560: last,eof
sparsefile: 2 extents found
조각화로 인해 여전히 두 개의 범위입니다. 그러나 논리적 오프셋에 따르면 이번에는 구멍이 없으므로 파일이 더 이상 희박하지 않습니다.
물론 이 dd
솔루션은 매우 수동적인 접근 방식입니다. 정기적으로 이 기능이 필요한 경우 이러한 공백을 메우기 위해 작은 프로그램을 작성하는 것이 쉬울 것입니다. 이미 표준 도구로 존재한다면 들어본 적이 없습니다.
결국 fallocate
어느 정도 작동하는 것으로 보이는 도구가 있습니다.
fallocate -l $(stat --format="%s" sparsefile) sparsefile
그러나 마지막으로 XFS의 경우 파일에 물리적 영역을 할당하지만 실제로는 0으로 만들지 않습니다. filefrag
할당되었지만 기록되지 않은 범위를 표시합니다.
2: 3.. 15: 7628851.. 7628863: 13: 7629020: unwritten
블록 장치에서 직접 올바른 데이터를 읽는 것이 목적이라면 이는 충분하지 않습니다. 향후 쓰기에 필요한 저장 공간만 예약합니다.