結論
-
ext4のdir_indexのhashの衝突が原因のようである。 - 解決方法はいくつか見つかったが、良い解決法は見つからなかった。
- ディレクトリを分けることで対応することにした。
状況
同じフォルダに大量にファイルを生成している途中で(1505406ファイル目で発生)No space left on deviceのエラーが出ました。
調べたところ、ストレージの容量不足でもinode数の枯渇でもなさそうです。
環境
OS:Ubuntu 16.04.6 LTS
ファイルシステム:ext4
ストレージの残量とinode数の確認
まずはNo space left on deviceの原因の多くであるストレージの容量不足かどうか、inode数が枯渇しているかどうかを調べました。
ストレージの残量はdf、inodeはdf -iで調べられます。
結果はどちらも該当していませんでした。
原因はdir_indexのhashの衝突か?
よく調べるとext4: Mysterious “No space left on device”-errorsというサイトに行き着きました。
曰く、ext4はdir_indexのハッシュのメカニズムとしてhalf_md4を使っているが、half_md4はアルゴリズムはmd4を使うものの32ビット分しか使用しないため、十分なファイル数があった時は衝突する可能性が高いとのこと。
dir_indexはext3から導入され、その名の通りインデックスで検索を高速化させるためのものですが、上記サイトによると、インデックスに使うハッシュの衝突が原因の可能性がありそうです。
dir_indexの調査
まず、dir_indexが有効化されてるかを調べます。
dfを打ち、Filesystemの行にある調べたいファイルシステム名をメモします。
次に以下を打ち込みます。YOUR_FILE_SYSTEM_NAMEは先ほど調べたファイルシステム名を入力します。
sudo tune2fs -l YOUR_FILE_SYSTEM_NAME| grep -o dir_index
実行後にdir_indexと出てくればdir_indexが有効化されていることになります。
対策
対策としては以下の三通りを思いつきました。
- ハッシュのアルゴリズムを変更する
-
dir_indexを無効化する - ディレクトリを分ける
1はtune2fsのマニュアルを見るとhalf_md4の他にteaが選べるようです。
以下でhash_algを変更できますが、先程のext4: Mysterious “No space left on device”-errorsにはteaに変更してもハッシュの衝突は発生したと書いてあるのであまり期待しないほうが良さそうです。
sudo tune2fs -E "hash_alg=tea" YOUR_FILE_SYSTEM_NAME
そもそもパフォーマンスの面でhash_md4が選択されておりteaに変更するとパフォーマンスに影響が出るとも書いてあるので、その面でもしないほうが良さそうです。
2は以下でdir_indexの無効化ができますがインデックスを無効化するとパフォーマンスに大きく影響が出るのでこれもしないほうが良さそうです。
sudo tune2fs -O "^dir_index"
3はインデックスはディレクトリ毎に作成されるのでディレクトリを分ければ衝突は回避できますが、分けたディレクトリでまた衝突する可能性はあります。
1,2,3番の対策を考えた結果、迂闊にファイルシステムを変更してパフォーマンスに影響が出ては困るので今回は3のディレクトリを分けて対応することにしました。
何か良い解決方法はないものか...
調べてもこれ以上の解決方法は見つかりませんでした。
どなたか良い解決方法をご存知の方いらっしゃいましたらご教授いただけると幸いです。