tmpfs에서 이 이상한 희소 파일 처리를 설명할 수 있는 것은 무엇입니까?

tmpfs에서 이 이상한 희소 파일 처리를 설명할 수 있는 것은 무엇입니까?

ext4파일 시스템 파티션에서 다음 코드를 실행할 수 있습니다.

fs="/mnt/ext4"

#create sparse 100M file on ${fs}
dd if=/dev/zero \
   of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2> /dev/null

#show its actual used size before
echo "Before:"
ls ${fs}/sparse100M -s

#setting the sparse file up as loopback and run md5sum on loopback
losetup /dev/loop0 ${fs}/sparse100M 
md5sum /dev/loop0

#show its actual used size afterwards
echo "After:"
ls ${fs}/sparse100M -s

#release loopback and remove file
losetup -d /dev/loop0
rm ${fs}/sparse100M

이는

Before:
0 sparse100M
2f282b84e7e608d5852449ed940bfc51  /dev/loop0
After:
0 sparse100M

tmpfs에서도 동일한 작업을 수행합니다.

fs="/tmp"

생산하다

Before:
0 /tmp/sparse100M
2f282b84e7e608d5852449ed940bfc51  /dev/loop0
After:
102400 /tmp/sparse100M

이것은 기본적으로 데이터를 읽는 것만으로 희소 파일이 "풍선처럼 폭발"할 것으로 예상한다는 의미입니까?

특히 FIEMAP ioctl 누락으로 인해 파일 시스템의 희소 파일에 대한 지원이 완벽하지 않기 때문일 것으로 예상 tmpfs하지만 이 동작의 원인이 무엇인지 잘 모르겠습니다. 나에게 말해 줄 수 있나요?

답변1

첫 번째당신은 혼자가 아닙니다이런 질문 때문에 혼란스러워요.

이는 이에 국한되지 tmpfs않고 항상 우려되는 사항이었습니다. NFSv4.

응용 프로그램이 희소 파일의 "구멍"을 읽으면 파일 시스템은 빈 블록을 0으로 채워진 "실제" 블록으로 변환하고 이를 응용 프로그램에 반환합니다.

파일을 검사하려고 할 때 md5sum명시적으로 검사하도록 선택합니다. 주문하다, 이는 md5sum이 수행하려는 작업에 따라 의미가 있습니다.

파일에 본질적으로 "구멍"이 있기 때문에 이 순차 읽기는 (경우에 따라) 파일을 채우기 위해 쓰기 시 복사와 유사한 작업을 수행하게 됩니다. 이는 더 깊은 문제, 즉 fallocate()구현된 파일 시스템이 지원하는지 여부 와 관련됩니다.FALLOC_FL_PUNCH_HOLE.

다행히도 tmpfs이것이 지원될 뿐만 아니라 구멍을 뒤로 "파는" 메커니즘도 있습니다.

CLI 유틸리티를 사용하면 fallocate이러한 취약점을 성공적으로 탐지하고 재이용할 수 있습니다.

에 따르면 man 1 fallocate:

-d, --dig-holes
      Detect and dig holes.  This makes the file sparse in-place, without
      using extra disk space.  The minimum size of the hole depends on
      filesystem I/O  block size (usually 4096 bytes).  Also, when using
      this option, --keep-size is implied.  If no range is specified by
      --offset and --length, then the entire file is analyzed for holes.

      You can think of this option as doing a "cp --sparse" and then
      renaming the destination file to the original, without the need for
      extra disk space.

      See --punch-hole for a list of supported filesystems.

fallocate실행 대상문서md5sum 하지만 레벨에 직면하면블록 장치fallocate()(순차 읽기 요청) 시스템 호출이 작동하는 방식 사이의 간격 에 갇혀 있습니다 . 우리는 실제로 그것을 볼 수 있습니다:

실제로 귀하의 예를 사용하면 다음과 같은 내용을 볼 수 있습니다.

$ fs=$(mktemp -d)
$ echo ${fs}
/tmp/tmp.ONTGAS8L06
$ dd if=/dev/zero of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2>/dev/null
$ echo "Before:" "$(ls ${fs}/sparse100M -s)"
Before: 0 /tmp/tmp.ONTGAS8L06/sparse100M
$ sudo losetup /dev/loop0 ${fs}/sparse100M
$ sudo md5sum /dev/loop0
2f282b84e7e608d5852449ed940bfc51  /dev/loop0
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 102400 /tmp/tmp.ONTGAS8L06/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ONTGAS8L06/sparse100M

이제... 이것이 귀하의 기본적인 질문에 대한 답변입니다. 내 모토가 "이상해지자"라서 더 파헤쳐봤는데...

$ fs=$(mktemp -d)
$ echo ${fs}
/tmp/tmp.ZcAxvW32GY
$ dd if=/dev/zero of=${fs}/sparse100M conv=sparse seek=$((100*2*1024-1)) count=1 2>/dev/null
$ echo "Before:" "$(ls ${fs}/sparse100M -s)"
Before: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo losetup /dev/loop0 ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 1036 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51  /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 1036 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 520 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51  /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 520 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 516 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51  /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 512 /tmp/tmp.ZcAxvW32GY/sparse100M
$ fallocate -d ${fs}/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ZcAxvW32GY/sparse100M
$ sudo md5sum ${fs}/sparse100M
2f282b84e7e608d5852449ed940bfc51  /tmp/tmp.ZcAxvW32GY/sparse100M
$ echo "After:" "$(ls ${fs}/sparse100M -s)"
After: 0 /tmp/tmp.ZcAxvW32GY/sparse100M

있잖아, 딱 이런 행동이잖아성능losetup스파스 파일의 크기를 변경합니다 . 따라서 이는 tmpfsHOLE_PUNCH 메커니즘 과 블록 장치 fallocate의 교차점을 결합한 흥미로운 조합이 됩니다.

관련 정보