내부에서 희소 파일을 비희소 파일로 변환

내부에서 희소 파일을 비희소 파일로 변환

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는 동일하지만 다르게 표시될 뿐입니다(첫 번째 범위는 83886080에서 시작하는 512바이트 섹터를 포함하므로 0-4294967295바이트이므로 취약점은 4294967296-6442450944바이트 단위입니다.

조각화가 있는 경우 더 많은 범위를 표시할 수 있습니다. 불행하게도 두 명령 모두 취약점을 직접 표시하지 않으며, 어떤 명령도 취약점을 표시하지 않으므로 표시된 논리적 오프셋에서 이를 추론해야 합니다.

1048576-1572864이제 적절한 (동일)/값 sum 을 추가하여 위에 표시된 대로 이 구멍을 채울 수 있습니다 . 위에서 사용된 섹터를 사용하도록 조정되었습니다. ( 의 경우 청크 크기를 반영하도록 탐색/건너뛰기/카운트 값을 조정해야 합니다.)ddseekskipcountbs=4kfilefragbs=1M1M

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

블록 장치에서 직접 올바른 데이터를 읽는 것이 목적이라면 이는 충분하지 않습니다. 향후 쓰기에 필요한 저장 공간만 예약합니다.

관련 정보