내 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
스파스 파일의 크기를 변경합니다 . 따라서 이는 tmpfs
HOLE_PUNCH 메커니즘 과 블록 장치 fallocate
의 교차점을 결합한 흥미로운 조합이 됩니다.