FALLOCATE(2) | Руководство программиста Linux | FALLOCATE(2) |
fallocate - управление пространством файла
#define _GNU_SOURCE /* Смотрите feature_test_macros(7) */ #include <fcntl.h>
int fallocate(int fd, int mode, off_t offset, off_t len);
Это непереносимый системный вызов, существующий только в Linux. В POSIX.1 есть переносимый метод, обеспечивающий выделение пространства под файл (смотрите posix_fallocate(3)).
Вызов fallocate() позволяет вызывающему напрямую управлять выделением дискового пространства под файл, на который указывает fd, для байтового диапазона, начинающегося с offset и имеющего длину len байт.
В аргументе mode задаётся операция, выполняемая над указанным диапазоном. Детали о поддерживаемых операциях представлены в подразделах далее.
По умолчанию (т. е. значение mode равно нулю) fallocate() выделяет место на диске в диапазоне, задаваемом offset и len. Размер файла (получаемый через stat(2)) будет изменён, если offset+len больше чем размер файла. Любая подобласть внутри диапазона, заданного offset и len, которая не содержала данных до вызова, будет заполнена нулями. Такое поведение по умолчанию очень напоминает поведение библиотечной функции posix_fallocate(3), и было введено для оптимальной реализации этой функции.
После успешного выполнения вызова последующие операции записи в диапазон, указанный offset и len, гарантированно не завершатся с ошибкой из-за нехватки места на диске.
Если в mode указан флаг FALLOC_FL_KEEP_SIZE, то поведение по умолчанию почти то же, но размер файла не будет изменён даже, если offset+len больше чем размер файла. Это полезно для предварительного выделения блоков с нулями за концом файла для оптимизации загруженности при добавлении.
Если в modeуказан флаг FALLOC_FL_UNSHARE, то общие файловые extent-данные будут сделаны частными для файла, чтобы гарантировать, что последующая запись не завершится ошибкой из-за нехватки места. Обычно, это выполняется с помощью операции копирования при записи для всех общих данных файла. Данный флаг может поддерживаться не во всех файловых системах.
Так как выделение выполняется кусками размером с блок, fallocate() может выделить больший диапазон дискового пространства, чем было указано.
Указание флага FALLOC_FL_PUNCH_HOLE (доступен, начиная с Linux 2.6.38) в mode освобождает пространство (т.е., создаёт дыру) в диапазоне начиная с offset и до len байт. Внутри заданного диапазона неполные блоки файловой системы заполняются нулями, а полные блоки файловой системы удаляются из файла. После успешного выполнения вызова, последующие операции чтения из этого диапазона вернут нули.
Флаг FALLOC_FL_PUNCH_HOLE должен быть логически добавлен к флагу FALLOC_FL_KEEP_SIZE в mode; другими словами, даже когда пробивание (punching) выходит за конец файла, размер файла (получаемый с помощью stat(2)) остаётся неизменным.
Не все файловые системы поддерживают FALLOC_FL_PUNCH_HOLE; если файловая система не поддерживает эту операцию, то возвращается ошибка. Операция поддерживается, как минимум, следующими файловыми системами:
Задание флага FALLOC_FL_COLLAPSE_RANGE (доступен, начиная с Linux 3.15) в mode приводит к удалению байтового диапазона из файла без создания дыры. Сворачиваемый диапазон байт начинается с offset и длится len байт. По завершению операции, содержимое файла, начиная с offset+len, будет добавлено в расположение offset, и файл будет на len байт меньше.
У файловой системы могут быть ограничения на детализацию операции, для большей эффективности реализации. Обычно, значения offset и len должны быть кратны размеру логического блока файловой системы, различающемуся в разных файловых системах и зависящему от настроек. Если файловая система содержит такое требование и оно нарушено, то fallocate() завершается ошибкой EINVAL.
Если область, заданная offset плюс len достигает или выходит за конец файла, то возвращается ошибка; вместо этого используйте ftruncate(2) для обрезания файла.
Вместе с FALLOC_FL_COLLAPSE_RANGE другие флаги в mode указывать нельзя.
В Linux 3.15 флаг FALLOC_FL_COLLAPSE_RANGE поддерживается в ext4 (только для файлов на основе extent) и XFS.
Задание флага FALLOC_FL_ZERO_RANGE (доступен, начиная с Linux 3.15) в mode приводит к обнулению байтового диапазона, начиная с offset и размером len байт. Внутри указанного диапазона блоки выделяются заранее для областей, которые попадают в дыры в файле. После успешного выполнения вызова последующие операции чтения из этого диапазона будут возвращать нули.
Зануление, желательно, выполнять внутри файловой системы, преобразуя диапазон в незаписываемые extents. Этот подход означает, что указанный диапазон на устройстве в действительности не будет содержать нули на физическом уровне (за исключением неполных блоков в одном из концов диапазона), и ввод-вывод требуется только для обновления метаданных.
Если в mode также указан флаг FALLOC_FL_KEEP_SIZE, то поведение вызова похоже, но размер файла не будет изменён даже, если offset+len больше размера файла. Такое поведение совпадает с предварительным выделением пространства с помощью указания флага FALLOC_FL_KEEP_SIZE.
Не все файловые системы поддерживают FALLOC_FL_ZERO_RANGE; если файловая система не поддерживает эту операцию, то возвращается ошибка. Операция поддерживается, как минимум, следующими файловыми системами:
Задание флага FALLOC_FL_INSERT_RANGE (доступен начиная с Linux 4.1) в mode увеличивает файловое пространство посредством вставки дыры (hole) в размер файла без перезаписывания существующих данных. Дыра начинается с offset и продолжается len байт. При вставки дыры внутрь файла содержимое файла, начинающееся с offset, будет сдвинуто вперёд (т. е., станет доступно по большему смещению в файле) на len байт. Вставка дыры внутрь файла увеличивает размер файла на len байт.
Данный режим имеет те же ограничения что и FALLOC_FL_COLLAPSE_RANGE, независимо от детализации операции Если требования детализации не удовлетворяются, то fallocate() завершается ошибкой EINVAL. Если offset больше или равно концу файла, то возвращается ошибка. Для таких операций (т. е., вставка дыры в конец файла) нужно использовать ftruncate(2).
Вместе с FALLOC_FL_INSERT_RANGE другие флаги в mode указывать нельзя.
Для работы FALLOC_FL_INSERT_RANGE требуется поддержка в файловой системе; сейчас это XFS (начиная с Linux 4.1) и ext4 (начиная с Linux 4.2).
При успешном выполнении fallocate() возвращается 0; при ошибке возвращается -1, а в errno содержится код ошибки.
Вызов fallocate() доступен в Linux начиная с ядра 2.6.23. Поддержка в glibc добавлена в версии 2.10. Флаги FALLOC_FL_* определены в заголовочных файлах glibc только начиная с версии 2.18.
Вызов fallocate() есть только в Linux.
fallocate(1), ftruncate(2), posix_fadvise(3), posix_fallocate(3)
2018-04-30 | Linux |