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 больше чем размер файла. Предварительно выделенные блоки с нулями за концом файла в этом случае полезны для оптимизации добавления.

Так как выделение выполняется кусками размером с блок, 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; если файловая система не поддерживает эту операцию, то возвращается ошибка. Операция поддерживается, как минимум, следующими файловыми системами:

*   XFS (начиная с Linux 2.6.38)

*   ext4 (начиная с Linux 3.0)

*   Btrfs (начиная с Linux 3.7)

*   tmpfs (начиная с Linux 3.5)

  Сворачивание (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 байт. Данный режим имеет те же ограничения что и 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 содержится код ошибки.

ОШИБКИ

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)).

EPERM
    Выполнение операции предотвращено опечатыванием (file seal); смотрите fcntl(2).

ESPIPE
    Значение fd указывает на канал или FIFO.

ETXTBSY
    Значение mode равно FALLOC_FL_COLLAPSE_RANGE или FALLOC_FL_INSERT_RANGE, но файл, на который указывает fd, в данный момент выполняется.

ВЕРСИИ
Вызов 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)