描述
使用Python处理数据集,大约需要生成20万个子目录。
生成到65000左右时候开始报错mkdir Failed: Too many links
类似cp mv
等命令也无法正常执行。
排查
首先怀疑文件inode用尽,检查磁盘inode余量
$ df -i /data1
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sdb 234389504 7908490 226481014 4% /data1
余量充足,排除该原因。进而怀疑文件系统限制,
查询资料得知ext3文件系统限制最大子目录数32000个,
但ext4无此限制,查看磁盘文件系统类型:
$ df -T /data1
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/sdb ext4 3691353224 3100686016 403157244 89% /data1
已经是ext4再次排除可能性。考虑到在Docker使用Python环境,怀疑OverlayFS存在限制。
诚然overlay存在一些限制,可通过升级overlay2解决。文中出现报错的类型如下:
failed to register layer: link /data/sys/var/docker/overlay/xxxxx: too many links
和我的错误有明显区别,anyway抱着试验心态将overlay升级为overlay2故障依旧没有解决。
定位
痛定思痛,排查了三个可能的原因都不对,怕是有遗漏。
作为对照,物理机直接新建70000个文件夹也复现了Too many links
此举排除OverlayFS嫌疑,有必要深究ext4的细节。
果然,在man ext4
发现一个名为dir_nlink
的选项:
Normally, ext4 allows an inode to have no more than 65,000 hard links. This applies to regular files as well as
directories, which means that there can be no more than 64,998 subdirectories in a directory (because each of the
'.' and '..' entries, as well as the directory entry for the directory in its parent directory counts as a hard
link). This feature lifts this limit by causing ext4 to use a link count of 1 to indicate that the number of hard
links to a directory is not known when the link count might exceed the maximum count limit.
实锤ext4对于子目录也存在65000默认数量限制,需手动解除。
解决
明确方向后很快在so找到了解除方法:
sudo umount /dev/sdb
sudo tune2fs -O dir_index,dir_nlink /dev/sdb
再次挂载后可以正常建立超过70000个子目录,限制解除。
$ mkdir {1..70000}
$ ll | wc -l
70003
该方法仅对新建目录生效,修改老目录限制则需要用到原文中的更新命令重建indices注意做好容灾。
参考
聊聊Linux上“too many links”报错出现的原因和处理方法_圣骑士控魔之手的技术博客_51CTO博客
ext4(5) - Linux manual page
filesystems - Ubuntu server ext4 hitting 65000 subdirectory limit - Server Fault