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
引数は、指定された領域に対して実行する操作を指定する。
サポートされている操作の詳細は以下のサブセクションで説明する。
fallocate()
のデフォルトの動作
(つまり
mode が 0 の場合)
は、
offset と
len
で指定された範囲のディスク領域の割り当てを行う。
offset+
len
がファイルサイズよりも大きかった場合、
(
stat(2) で報告される)
ファイルサイズが変更される。
offset と
len
で指定される範囲のサブ領域で、
呼び出し前にデータを保持していなかった場合、そのサブ領域は
0 で初期化される。
このデフォルトの動作は、
ライブラリ関数
posix_fallocate(3)
の動作と非常に似ている。
これは、
このシステムコールが
posix_fallocate(3)
を最適に実装する手段を提供することを目的としているからである。
呼び出しが成功した場合、
offset と
len
で指定された範囲へのそれ以降の書き込みでは、
ディスクの領域不足での書き込み失敗が起こらないことが保証される。
FALLOC_FL_KEEP_SIZE フラグが
mode
に指定された場合、このシステムコール
の動作は似ているが、
offset+
len
がファイルサイズよりも大きい場合で
あってもファイルサイズは変更されない点が異なる。この場合のファイルの末尾
よりも後ろの前もって割り当てられた
0
で埋められたブロックは、ファイルへの
追記を最適化したい場合に役に立つ。
If the
FALLOC_FL_UNSHARE flag is specified in
mode, shared file
data extents will be made private to the file to guarantee that a subsequent
write will not fail due to lack of space. Typically, this will be done by
performing a copy-on-write operation on all shared data in the file. This flag
may not be supported by all filesystems.
割り当てはブロックサイズ単位で行われるため、
fallocate()
は指定されたより
も大きなディスク領域を割り当てることがある。
FALLOC_FL_PUNCH_HOLE フラグ (Linux 2.6.38
以降で利用可能) を
mode
に指定すると、
offset
で始まる
len
バイトの領域の空間を解放する
(ホールを作成する)。
指定された範囲のうち、
部分的に使用しているファイルシステムブロックは
0 で埋められ、
全体を使用しているファイルシステムブロックはそのファイルから削除される。
呼び出しが成功すると、
これ以降のこの範囲からの読み出しでは
0 を返す。
FALLOC_FL_PUNCH_HOLE フラグは
FALLOC_FL_KEEP_SIZE と論理和 (OR)
をとって
mode
に指定しなければならない。
つまり、
ファイル末尾の punch off
を行った場合でも、 (
stat(2) で報告される)
ファイルサイズが変化しない。
すべてのファイルシステムで
FALLOC_FL_PUNCH_HOLE
がサポートされているわけではない。
ファイルシステムがこの操作をサポートしていない場合は、
エラーが返る。
この操作は少なくとも以下のファイルシステムでサポートされている。
- *
- XFS (Linux 2.6.38 以降)
- *
- ext4 (Linux 3.0 以降)
- *
- Btrfs (Linux 3.7 以降)
- *
-
tmpfs(5) (Linux 3.5 以降)
- *
-
gfs2(5) (Linux 4.16 以降)
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
(エクステントベースのファイル)
と XFS
でサポートされている。
FALLOC_FL_ZERO_RANGE フラグ (Linux 3.15
以降で利用可能) を
mode
に指定すると、
offset
で始まる
len
バイト範囲の空間をゼロ埋めする。
指定された範囲の中では、ブロックは、そのファイル内のホールが広がる領域にあらかじめ割り当てられたものである。
呼び出しが成功すると、
これ以降のこの範囲からの読み出しでは
0 を返す。
ゼロ埋めは、ファイルシステム内部では、指定された範囲を書き込みを伴わないエクステントに変換する方法をできるだけ使って行われる。
この方法は、指定された範囲について物理的にゼロ埋めしたデータがデバイスに書き込まれるのではないことを意味する
(例外は指定された範囲の端の部分的に使用しているブロックである)。
(これ以外で) I/O
が必要なのはメタデータの更新だけである。
FALLOC_FL_KEEP_SIZE フラグが
mode
に追加で指定された場合、
このシステムコールの動作は似ているが、
offset+
len
がファイルサイズよりも大きい場合であってもファイルサイズは変更されない点が異なる。
この動作は
FALLOC_FL_KEEP_SIZE
を指定してスペースを前もって割り当てた場合と同じである。
すべてのファイルシステムで
FALLOC_FL_ZERO_RANGE
がサポートされているわけではない。
ファイルシステムがこの操作をサポートしていない場合は、
エラーが返る。
この操作は少なくとも以下のファイルシステムでサポートされている。
- *
- XFS (Linux 3.15 以降)
- *
- ext4
のエクステントベースのファイル
(Linux 3.15 以降)
- *
- SMB3 (Linux 3.17 以降)
- *
- Btrfs (Linux 4.16 以降)
Specifying the
FALLOC_FL_INSERT_RANGE flag (available since Linux 4.1) in
mode increases the file space by inserting a hole within the file size
without overwriting any existing data. The hole will start at
offset
and continue for
len bytes. When inserting the hole inside file, the
contents of the file starting at
offset will be shifted upward (i.e.,
to a higher file offset) by
len bytes. Inserting a hole inside a file
increases the file size by
len bytes.
This mode has the same limitations as
FALLOC_FL_COLLAPSE_RANGE regarding
the granularity of the operation. If the granularity requirements are not met,
fallocate() fails with the error
EINVAL. If the
offset is
equal to or greater than the end of file, an error is returned. For such
operations (i.e., inserting a hole at the end of file),
ftruncate(2)
should be used.
FALLOC_FL_INSERT_RANGE
と他のフラグを同時に
mode
に指定することはできない。
FALLOC_FL_INSERT_RANGE requires filesystem support. Filesystems that
support this operation include XFS (since Linux 4.1) and ext4 (since Linux
4.2).
成功の場合、
fallocate() は 0
を返す。
エラーの場合、-1
を返し、
errno
にエラーを示す値を設定する。
- EBADF
-
fd
が有効なファイルディスクリプターでないか、
書き込み用としてオープンされていない。
- EFBIG
-
offset + len
がファイルサイズの最大値よりも大きい。
- EFBIG
-
mode is FALLOC_FL_INSERT_RANGE, and the
current file size+ len exceeds the maximum file size.
- EINTR
- 実行中にシグナルが捕捉された。
signal(7) 参照。
- EINVAL
-
offset が 0
未満だったか、 len
が 0 以下だった。
- EINVAL
-
mode が FALLOC_FL_COLLAPSE_RANGE
で、 offset と len
で指定された範囲がファイルの末尾かそれより先まで達している。
- EINVAL
-
mode が FALLOC_FL_INSERT_RANGE
で、 offset と len
で指定された範囲がファイルの末尾かそれより先まで達している。
- EINVAL
-
mode が FALLOC_FL_COLLAPSE_RANGE
か FALLOC_FL_INSERT_RANGE だが、
offset か len
のいずれかがファイルシステムのブロックサイズの倍数ではない。
- EINVAL
-
mode contains one of FALLOC_FL_COLLAPSE_RANGE
or FALLOC_FL_INSERT_RANGE and also other flags; no other flags are
permitted with FALLOC_FL_COLLAPSE_RANGE or
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
が参照するファイルを含むファイルシステムが
指定された操作を
サポートしていない。
fd
が参照するファイルを含むファイルシステムが
mode
をサポートしていない。
- EPERM
-
fd
が参照するファイルに変更不可
(immutable)
の属性が付いている (
chattr(1) 参照)。
- EPERM
-
mode に FALLOC_FL_PUNCH_HOLE か
FALLOC_FL_COLLAPSE_RANGE か FALLOC_FL_INSERT_RANGE
が指定されたが、 fd
が参照するファイルに追加のみ
(append-only)
の属性が付いている (
chattr(1) 参照)。
- EPERM
- 操作が file seal
により禁止されている。
fcntl(2) 参照。
- ESPIPE
-
fd がパイプか FIFO
を参照している。
- ETXTBSY
-
mode に FALLOC_FL_COLLAPSE_RANGE
か FALLOC_FL_INSERT_RANGE
が指定されたが、 fd
が参照するファイルは現在実行中である。
fallocate() はカーネル 2.6.23
以降の Linux
で利用可能である。 glibc
での対応はバージョン
3.10
以降で行われている。
FALLOC_FL_* が glibc
のヘッダーファイルで定義されているのは、バージョン
2.18 以降のみである。
fallocate() は Linux
固有である。
fallocate(1),
ftruncate(2),
posix_fadvise(3),
posix_fallocate(3)
この man ページは Linux
man-pages
プロジェクトのリリース
5.10
の一部である。プロジェクトの説明とバグ報告に関する情報は
https://www.kernel.org/doc/man-pages/
に書かれている。