Linux/XFS の directory size で 6 byte や 4096 byte が多い理由 | SEの道標
Linux基礎

Linux/XFS の directory size で 6 byte や 4096 byte が多い理由

Linux XFSファイルシステムの基礎

ファイルのタイプ

Linux では全てのリソースをファイルとして扱います。HDD 等のブロックデバイスやキーボード等のキャラクタデバイス等もそうですが、ディレクトリ自体もファイルの一種に分類されます。

ファイルの種類を以下に示します。(これは例えば "ls -l" で左端に表示される文字であったり、 find コマンドの -type で指定される文字だったりします)

b = block (buffered) special = HDD等のバッファを利用するブロックデバイス
c = character (unbuffered) special = CPU/memory/NIC や tty/vty コンソール等のバッファを利用しないデバイス
d = directory = ディレクトリ
p = named pipe = 同一OS内プロセス間通信で利用される名前付きパイプ
f = regular file = 通常のファイル
l = symbolic link = シンボリックリンク
s = socket = UNIXドメインソケット(.sockファイル)

ファイルの i-node領域およびデータ領域について

ファイル(ディレクトリ含む)は、メタ情報を持つ i-node 領域とそのファイルの中身であるデータ領域の2つに分かれます。i-node 領域には「パーミッション」や「所有者」、「タイムスタンプ」といったメタ情報が格納されます。データ領域は、通常のファイル、ディレクトリ、シンボリックリンクの場合のみに使われます。

通常のファイルの場合はそのファイルの中身(例えば vi で "test" と 4 文字 = 4 byte 打ち込んだ場合、改行コード [LF] も含め 5 byte 分)が含まれます。

ディレクトリのサイズとは何か?空ディレクトリのサイズが 6 byte なのは何故か?

ディレクトリの場合は特殊です。ディレクトリ自体にデータ領域が必要か?と思われるかもしれませんが、実際に "ls -l" で確認するとディレクトリ自体にもサイズがあることが分かります。

『ディレクトリ配下のファイルの総サイズ数か?』と思いきや、そうでもありません。以下の例では、10MB の test.dat ファイルを配下に収めるディレクトリのサイズが 22 Byte になっています。

[testuser@localhost ~]$ ls -l
合計 4
drwxrwxr-x. 2 testuser testuser 22  7月 13 22:15 test
-rw-rw-r--. 1 testuser testuser  2  7月 13 22:13 test.txt
[testuser@localhost ~]$ ls -l test
合計 10240
-rw-rw-r--. 1 testuser testuser 10485760  7月 13 22:15 test.dat
[testuser@localhost ~]$

Linux 初心者にしてみれば Windows と勝手が違って不思議かと思います。

実はディレクトリのデータ領域には「ヘッダ情報 (配下の file/dir 数 [2 byte] + 親ディレクトリの i-node 番号 [ 4 byte] の計 6 byte)」と「ディレクトリ配下のファイル名やその i-node 番号等」の情報が含まれています。XFSにおいて空ディレクトリが 6 byteと表示されるのは、このヘッダ情報のみが含まれるからです

また、ディレクトリ配下に file/dir が追加されると、そのディレクトリのサイズは、(file/dirの名前の長さのbyte+8byte)だけ増えます。8byte は i-node 番号(4byte)と名前の長さ情報(1byte), ファイルタイプ(1byte), offset 情報(2byte)です。offset 情報はプログラミングの際に便利な情報、という程度に覚えておけば良いでしょう。

ファイル/ディレクトリの追加・削除を行うためには、上位ディレクトリへの書き込み権が必要なのは何故か?

ディレクトリのデータ領域の使われ方を知ることで、とある1つの疑問が解けます。「なぜファイルの作成・削除するのに、そのファイルの1つ上のディレクトリに対する書き込み権限が必要なのだろうか?」そう思った人は多いかと思います。その答えは『ディレクトリ配下にファイルを作る=ディレクトリのデータ領域にそのファイル名や i-node 情報等を書き込むから』です。

XFS の ブロックサイズと i-node サイズ

ls -l で表示されるサイズ情報は、データ領域のみの byte 数であり、i-node 領域は含まれません。データ領域に書き込むデータは「ブロック」に書き込まれますので、空ファイルだとブロックは割り当てられませんが、1 byte でも情報があると1ブロックが割り当てられます。以下に空ファイルの "test1.txt" と 1 byte ファイルの "test2.txt" を比較した例を示します。

[root@localhost test]# ls -lsh
合計 4.0K
   0 -rw-r--r--. 1 root root 0  7月  6 10:31 test1.txt
4.0K -rw-r--r--. 1 root root 1  7月  6 10:31 test2.txt
[root@localhost test]#

test1.txt はサイズ( root root の右横)が 0 になっており、利用ブロックサイズ(左端)も 0 になっていますが、test2.txt はサイズが 1 となっており、利用ブロックサイズも 4KB になっています。

一方、i-node 領域はどうかというと、XFS へのフォーマット時に i-node のサイズがあらかじめ決まっています。

xfs_info 結果の meta-data= の行にある isize で示された値が i-nodeサイズ、data=の行にある bsize がブロックサイズです。以下の例では / にマウントしている /dev/mapper/ccentos-root パーティションの i-nodeサイズが "512 byte"、ブロックサイズが 4096=4KB となっています。

[root@localhost /]# df
ファイルシス            1K-ブロック    使用   使用可 使用% マウント位置
/dev/mapper/centos-root    19056640 1110260 17946380    6% /
~~~
[root@localhost /]# xfs_info /dev/mapper/centos-root
meta-data=/dev/mapper/centos-root  isize=512 agcount=4, agsize=1191680 blks
~~~
data = bsize=4096 blocks=4766720, imaxpct=25
~~~

Short Form Directories

先程の例で示した環境において、i-node 領域内のうちメタ情報に使うサイズは 232 Byte になっており、空きが 280Byte あります。XFS ファイルシステムでは、ディレクトリのデータ領域が i-node 内に収まるのであれば収めてしまいます。このように file/dir が少なく、ディレクトリのデータ領域が i-node 内に収まるディレクトリのことを「Short Form Directories」と呼びます。このような小サイズのディレクトリが多い場合、XFS ファイルシステムでは大幅に利用ブロックを減らすことができます。

例えば /temp 配下に "a" が 129 文字続くファイル名のファイルと同様に "b" が 129 文字続くファイルを 2 つ配置すると、ヘッダ 6 byte + (129 byte +8 byte) * 2 = 280 byte となります。

[root@localhost temp]# ls -als
合計 0
0 drwxr-xr-x.  2 root root 280  7月  5 19:47 .
0 dr-xr-xr-x. 18 root root 236  7月  5 19:42 ..
0 -rw-r--r--.  1 root root   0  7月  5 19:46 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0 -rw-r--r--.  1 root root   0  7月  5 19:46 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
[root@localhost temp]#

. (Current Directory)のサイズが 280 となっています。a...のファイルに 1 byte 分 "z" を足すと

[root@localhost temp]# mv aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz
[root@localhost temp]# ls -als
合計 4
4 drwxr-xr-x.  2 root root 4096  7月  5 19:52 .
0 dr-xr-xr-x. 18 root root  236  7月  5 19:42 ..
0 -rw-r--r--.  1 root root    0  7月  5 19:46 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz
0 -rw-r--r--.  1 root root    0  7月  5 19:46 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
[root@localhost temp]#

4096 になりました。また、-s により左端に"データ領域の利用ブロックサイズ"が表示されていますが、これも 0 からブロックサイズ1つ分を表す 4KB になりました。
つまり、データ領域が i-node サイズ内に収まりきらないため、ブロックサイズ1つ分を確保したのです。

なお、ブロックサイズは xfs_info の結果の "data =" の横にある "bsize=4096" に示されています。

コメント

タイトルとURLをコピーしました