我有一个带有 / on tmpfs 的系统。大多数 / 子目录都安装了 aufs,用只读的基本文件系统覆盖读写根文件系统(系统从只读介质启动)。早些时候,我使用unionfs而不是aufs。它一直正常工作,直到最近 tmpfs 开始填满。我不确定是什么触发了变化。它可能是 unionfs 到 aufs 的更改、内核升级或系统中的某些更改以及它如何访问文件系统。
无论如何,似乎是 tmpfs 的行为有些错误。
虽然系统不应该向 tmpfs 写入很多内容,但其中有相当一部分已经用完了:
# df -m /
Filesystem 1M-blocks Used Available Use% Mounted on
tmpfs 200 50 151 25% /
尽管:
# du -smx /
2 /
这是我的测试系统,基本上什么都不做。当使用率迅速超过 90% 并且系统崩溃时,生产系统就会出现故障。
我怀疑这些已删除的文件仍然打开,但是:
# lsof | grep deleted
什么都没显示。
另一个想法是, / 上的某些文件被安装在其上的文件系统所掩盖,所以我尝试了这个:
# mount --bind / /mnt
# du -sm /mnt
2 /mnt
仍然没有丢失 48MB 的痕迹。
我怎样才能找出是什么用完了我的 tmpfs 文件系统?
系统信息:
# uname -rm
3.4.6 i686
更新:我试过内核 3.4.17 和 3.6.6——没有变化。
在 aufs 维护者 Junjiro Okajima 的帮助下,我自己解开了这个谜团。
调试问题的第一步是以受控方式重现它。我花了一些时间(现在我想知道为什么这么多)才发现,当通过 aufs 写入和删除文件时会出现问题。
重现问题
创建挂载点:
挂载 tmpfs:
挂载 aufs,用 /tmp/rw 覆盖 /usr:
现在我可以在 /tmp/mnt 下看到 /usr 的内容:
我感兴趣的是下面 tmpfs 上的已用/可用空间:
/tmp/rw 中没有文件,但分配了 24 个块。仍然不是什么大问题。
我可以将文件写入 aufs,它将存储在 /tmp/rw 中的 tmpfs 上:
注意使用统计数据是如何变化的。
du
显示添加了 100kB,如预期的那样,但df
输出中的“已使用”值增加了 104 个块。当我删除文件时:
丢失了四个块。
当我重复
dd
和rm
命令几次时,我得到:越来越多的 tmpfs 块不见了,我不知道在哪里……
我做了同样的事情——
dd
直接rm
在 /tmp/rw 上,没有任何东西丢失。卸载 aufs 后,tmpfs 上丢失的空间被恢复。所以,至少,我知道这是 aufs,而不是 tmpfs 的罪魁祸首。发生了什么
知道应该责备什么,我在 aufs-users 邮件列表上描述了我的问题。我很快收到了第一个答案。来自 JR Okajima 的帮助我解释了丢失的 tmpfs 块发生了什么。
确实是一个被删除的文件。由于文件未被任何用户空间进程打开或映射,因此未
lsof
在其中任何地方显示。/proc/<pid>/*
这个文件,'xino 文件',是 aufs 的外部索引节点号转换表,由内核 aufs 模块在内部使用。可以从 sysfs 读取文件路径:
但是,随着文件被删除,无法直接看到它:
但是,可以从 debugfs 中读取有关其大小和其他特殊 aufs 文件大小的信息:
aufs 手册页中描述了详细信息。
解决方案
“xino 文件”可以通过以下方式手动截断:
可以在挂载 aufs 时使用 trunc_xino 选项请求自动 xino 文件截断:
我仍然不知道它如何影响文件系统性能,或者这是否真的能解决我在生产环境中的 tmpfs 空间不足问题……但我学到了很多东西。
我已经看到这种情况发生在文件被删除但进程仍在保留文件的情况下,这意味着在进程重新启动之前空间不会被释放。我已经在 Apache 日志文件中看到了这一点。它似乎继续写入现在已删除的日志文件,直到重新启动后空间才被清除。
要找出哪个进程可能保留已删除的文件,您可以尝试重新启动每个进程并查看是否清除了空间。如果是这样,您就找到了罪魁祸首。
HTH