Interested Article - Разрежённый файл

Расположение на диске двух одинаковых файлов:
сверху и посередине — обыкновенный файл;
снизу — разрежённый файл;
зелёные области — данные;
серые области — дыры

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

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

Преимущества и недостатки

Преимущества:

Недостатки:

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

Поддержка

Для реализации поддержки разрежённых файлов требуются:

  • возможность записи метаданных в ФС;
  • поддержка со стороны системного и прикладного ПО.

Следующие ФС поддерживают разрежённые файлы: BTRFS , NILFS , ZFS , NTFS , ext2 , ext3 , ext4 , XFS , JFS , ReiserFS , Reiser4 , UFS , Rock Ridge , UDF , ReFS , APFS , F2FS .

Следующее ПО поддерживает работу с разрежёнными файлами:

Применение

Разрежённые файлы используются для хранения контейнеров , например:

Команды

Команды для работы с разрежёнными файлами.

Linux :

  • создание разрежённого файла размером 200 Гб :
dd if=/dev/zero of=./sparse-file bs=1 count=0 seek=200G
# или
truncate -s200G ./sparse-file
  • преобразование обычного файла в разрежённый (выполнение поиска дыр и записи их расположения (смещений и длин) в метаданные файла):
cp --sparse=always ./simple-file ./sparse-file
  • сохранение копии диска в разрежённый файл утилитой ddrescue :
ddrescue --sparse /dev/sdb ./sparse-file ./history.log

Windows :

  • создание (не разрежённого) файла размером 200 Гб ( 214 748 364 800 байт ) (размер задаётся в байтах):
fsutil file createnew some-file 214748364800
  • установка флага «разрежённый» (поиск дыр внутри файла не выполняется):
fsutil sparse setflag some-file
  • удаление флага «разрежённый» :
fsutil sparse setflag some-file 0
  • получение значения флага «разрежённый»:
fsutil sparse queryflag some-file
  • пометка области файла, как дыры (смещение и длина задаются в байтах):
fsutil sparse setrange some-file 0 214748364800

Особенности

  • При чтении из дыры возвращаются нулевые байты; обращения к диску не происходит (предполагается, что карты расположения областей уже прочитаны с диска из метаданных файла и находятся в памяти).
  • При записи в дыру запускается алгоритм поиска свободного места (свободных блоков) на диске. Если блоки найдены, данные будут записаны. Зачастую найденные блоки расположены на диске далеко от блоков с уже записанным содержимым файла; это приводит к фрагментации ФС. Если место на диске закончится, алгоритм не найдёт ничего и запись не будет выполнена ( write() сообщит о нехватке свободного места, а, если файл использовался с помощью mmap() , произойдёт ошибка segmentation fault ).
  • Запись в произвольное место разрежённого файла, как правило, приводит к большой фрагментации ФС.
  • Разрежённые файлы не всегда корректно копируются; при копировании файла вместо информации о дырах на диск могут быть записаны нулевые байты. Для Linux правильное копирование выполняется командой cp с ключом --sparse . Реализовать правильное копирование можно двумя способами: 1) искать области, заполненные нулевыми байтами (дыры), и выполнять seek() (вместо записи нулей с помощью write() ); 2) получить карту расположения файла на диске с помощью fibmap() .
  • Пометить произвольную область файла как дыру позволяет системный вызов fallocate() с флагом punch hole («пробить дырку»). Системный вызов не только освободит место на диске, но ещё и выполнит команду TRIM у SSD-дисков для блоков указанной области.
  • Так как адресация в большинстве ФС осуществляется с помощью блоков , то смещение и размер дыр не могут быть произвольными, а должны быть кратны размеру блока (выровнены по размеру блока). Размер блока постоянен для одного раздела . Таким образом, нельзя сделать «дыру» в пару байт; при такой попытке драйвер ФС запишет на диск нулевые байты.
  • Утилиты для отображения размера файла обычно выводят реальный размер файла (в байтах) и размер, занимаемый файлом на диске (в блоках ФС или байтах). Разрежённый файл может занимать меньше места на диске.
  • Обратите внимание, что системный вызов fallocate() с флагом 0 выделяет блоки под файл и помечает их, как «заполненные нулевыми байтами». Это позволяет почти мгновенно создать большой файл без записи нулевых байтов на диск. Отличие от разрежённых файлов заключается в резервировании блоков; блоки под файл выделяются сразу; при записи в блок флаг «заполнен нулевыми байтами» снимается; если на диске закончится свободное место, при записи в область, содержащую нулевые байты, ошибки не возникнет. Команда TRIM у SSD-дисков вызывается и для этого случая.

Примечания

  1. Нулевой байт — байт , все биты которого установлены в ноль (0, NUL или '\0' в Си ).
  2. . Дата обращения: 6 апреля 2011. 15 марта 2012 года.
  3. FALLOC_FL_PUNCH_HOLE. См.
    man 2 fallocate
    
  4. Для разных ФС «блок» называется по-разному: «кластер» ( англ. cluster ) в NTFS , «блок» ( англ. block ) в ext4 .
Источник —

Same as Разрежённый файл