ИМЯ 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 больше чем размер файла. Предварительно выделенные блоки с нулями за концом файла в этом случае полезны для оптимизации добавления.
Так как выделение выполняется кусками размером с блок, 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; если файловая система не поддерживает эту операцию, то возвращается ошибка. Операция поддерживается, как минимум, следующими файловыми системами:
Сворачивание (Collapsing) файлового пространства Задание флага 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; если файловая система не поддерживает эту операцию, то возвращается ошибка. Операция поддерживается, как минимум, следующими файловыми системами:
* XFS (начиная с Linux 3.15)
* ext4, для файлов на основе extent (начиная с Linux 3.15)
* SMB3 (начиная с Linux 3.17)
Увеличение файлового пространства Задание флага FALLOC_FL_INSERT_RANGE (доступен начиная с Linux 4.1) в mode увеличивает файловое пространство посредством вставки дыры (hole) в размер файла без перезаписывания существующих данных. Дыра начинается с offset и продолжается len байт. При вставки дыры внутрь файла содержимое файла, начинающееся с offset, будет сдвинуто вперёд (т. е., станет доступно по большему смещению в файле) на len байт. Вставка дыры внутрь файла увеличивает размер файла на len байт.
это XFS (начиная с Linux 4.1) и ext4 (начиная с Linux 4.2).
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ При успешном выполнении fallocate() возвращается 0; при ошибке возвращается -1, а в errno содержится код ошибки.
ОШИБКИ EBADF Значение fd не является допустимым файловым дескриптором или он не открыт на запись.
EFBIG Сумма offset+len превышает максимальный размер файла.
EFBIG В mode указан FALLOC_FL_INSERT_RANGE, и текущий размер файла+len превышает максимальный файловый размер.
EINTR При выполнении поступил сигнал; смотрите signal(7).
EINVAL Значение offset меньше 0, или len меньше или равно 0.
EINVAL Значение mode равно FALLOC_FL_COLLAPSE_RANGE, но диапазон, указанный в offset плюс len, достиг или перешагнул за конец файла.
EINVAL Значение mode равно FALLOC_FL_INSERT_RANGE, но диапазон, указанный в offset, достиг или перешагнул за конец файла.
EINVAL Значение mode равно FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE, но значение offset или len не кратно размеру блока файловой системы.
EINVAL Значение mode содержит FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE, а также другие флаги; но с FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE другие флаги указывать нельзя.
EINVAL Значение mode равно FALLOC_FL_COLLAPSE_RANGE, FALLOC_FL_ZERO_RANGE или FALLOC_FL_INSERT_RANGE, но файл, на который указывает fd, не является обычным файлом.
EIO При чтении или записи в файловую систему произошла ошибка ввода-вывода.
ENODEV Значение fd не указывает на обычный файл или каталог (если fd — канал или FIFO, то возникнет другая ошибка).
ENOSPC Недостаточно дискового пространства на устройстве, на котором расположен файл, указанный в fd.
ENOSYS В данном ядре вызов fallocate() не реализован.
EOPNOTSUPP Файловая система с файлом, на который указывает fd, не поддерживает данную операцию; или значение mode не поддерживается файловой системой, в которой находится файл, на который указывает fd.
EPERM Файл, на который указывает fd, помечен как неизменяемый (immutable) (смотрите chattr(1)).
EPERM Значение mode равно FALLOC_FL_PUNCH_HOLE, FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE и файл, на который указывает fd, помечен как только для добавления (смотрите chattr(1)).
ВЕРСИИ Вызов 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)
|