Определение

Разрежённый файл (англ. sparse file) — файл, в котором последовательности нулевых байтов заменены на информацию об этих последовательностях (список дыр)

Дыра — последовательность нулевых байт внутри файла, не записанная на диск. Информация о дырах (смещение от начала файла в байтах и количество байт) хранится в метаданных ФС.

Один из самых частых случаев применения можно найти в образах виртуальных машин формата raw, поскольку в отличие от qcow2, образы raw не содержат какой-либо метаинформации для экономии дискового пространства

При этом виртуальный размер такого файла может превышать максимальную емкость на ФС, в которой он расположен

Практика

Попробуем создать такой файл разными способами:

qemu-img create -f raw gigantic_image.img 10T
truncate -s 100G big_file
dd of=sparse-file bs=10G seek=10 count=0

Если посмотреть размер этих файлов привычным всем способом через утилиту ls, то мы увидим лишь виртуальный размер файлов:

ls -lh
total 4.0K
-rw-r--r-- 1 alexander alexander 100G Sep 18 21:10 big_file
-rw-r--r-- 1 alexander alexander  10T Sep 18 21:10 gigantic_image.img
-rw-r--r-- 1 alexander alexander 100G Sep 18 21:10 sparse-file

Для того чтобы увидеть реальный размер, который эти файлы занимают на диске можно воспользоваться любой из нижеперечисленных команд: • ls -s — флаг -s, --size выведет слева (перед дискреционными правами) реальный размер файлов • du -h <file> — флаг -h нужен для человекочитаемого вывода размера файлов, du, умеет распознавать такие файлы без дополнительных флагов • qemu-img info <image> — для образов (с обычными файлами тоже работает) • stat <file> — хоть и показывает виртуальный размер, но число блоков будет соответстовать реальному

На этом список команд не заканчивается, перечислять все возможные способы не имеет смысла

При этом можно конвертировать обычный файл в разрежённый:

dd if=/dev/zero of=sparse_file bs=50M count=5

ls -lhs
total 250M
250M -rw-r--r-- 1 alexander alexander 250M Sep 18 21:26 sparse_file

fallocate -d sparse_file

ls -lhs
total 0
   0 -rw-r--r-- 1 alexander alexander 250M Sep 18 21:27 sparse_file

При копировании через cp можно передать флаг --sparse=always, который позволит создать разрежённую версию файла из неразрёженного файла

dd if=/dev/zero of=sparse_file bs=50M count=5

cp --sparse=always sparse_file sparse_copy

ls -lsh
total 251M
   0 -rw-r--r-- 1 alexander alexander 250M Sep 18 21:32 sparse_copy
251M -rw-r--r-- 1 alexander alexander 250M Sep 18 21:32 sparse_file

Однако, помимо очевидных преимуществ в виде экономии дискового пространства, что особено полезно в виртуальных машинах, есть и ряд существенных недостатков:

  • фрагментация файла при частой записи данных в дыры
  • копирование разрежённого файла программой, которая не поддерживает работу с таким типом файлов, может создать файл без сжатия размера
  • заполнение систем с такими файлами может привести к непредвиденным ошибкам