重现问题

重现问题

我有一个在 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 – 没有变化。

答案1

在 aufs 维护者 Junjiro Okajima 的帮助下,我自己解开了这个谜团。

调试问题的第一步是以一种可控的方式重现问题。我花了一些时间(现在我想知道为什么花这么多时间)才发现,问题发生在通过 aufs 写入和删除文件时。

重现问题

创建挂载点:

# cd /tmp
# mkdir rw
# mkdir mnt

挂载 tmpfs:

# mount -t tmpfs none /tmp/rw

挂载 aufs,用 /tmp/rw 覆盖 /usr:

# mount -t aufs  -n -o "br:/tmp/rw:/usr" none "/tmp/mnt"

现在我可以看到 /tmp/mnt 下的 /usr 内容:

# ls /tmp/mnt
bin  games  include  lib  lib64  local  sbin  share  src

我感兴趣的是下面 tmpfs 上的已用/可用空间:

# du -sk /tmp/rw   
0   /tmp/rw
# df /tmp/rw  
Filesystem     1K-blocks  Used Available Use% Mounted on
none             1031128    24   1031104   1% /tmp/rw

/tmp/rw 中没有文件,但分配了 24 个块。仍然不是大问题。

我可以将文件写入aufs,它将被存储在/tmp/rw中的tmpfs上:

# dd if=/dev/zero of=/tmp/mnt/test bs=1024 count=100
100+0 records in
100+0 records out
102400 bytes (102 kB) copied, 0.000343903 s, 298 MB/s
# du -sk /tmp/rw
100 /tmp/rw
# df /tmp/rw
Filesystem     1K-blocks  Used Available Use% Mounted on
none             1031128   128   1031000   1% /tmp/rw

注意使用情况统计数据是如何变化的。du显示增加了 100kB,正如预期的那样,但是输出中的“已使用”值df增加了 104 个块。

当我删除该文件时:

# du -sk /tmp/rw   
0   /tmp/rw
# df /tmp/rw
Filesystem     1K-blocks  Used Available Use% Mounted on
none             1031128    28   1031100   1% /tmp/rw

四个区块丢失。

当我重复ddrm命令几次时,我得到:

# df /tmp/rw                                         
Filesystem     1K-blocks  Used Available Use% Mounted on
none             1031128    36   1031092   1% /tmp/rw

越来越多的 tmpfs 块消失了,我不知道它去了哪里……

我做了同样的事情 –dd直接rm在 /tmp/rw 上这样做不会丢失任何东西。卸载 aufs 后,tmpfs 上丢失的空间被恢复了。所以,至少我知道这是 aufs 的问题,而不是 tmpfs 的问题。

发生了什么

知道该归咎于什么之后,我在 aufs-users 邮件列表上描述了我的问题。我很快就收到了第一批答复。JR冈岛的帮助我解释丢失的 tmpfs 块发生了什么。

确实,这是一个已删除的文件。它没有被显示出来,lsof因为/proc/<pid>/*该文件没有被任何用户空间进程打开或映射。该文件,即“xino 文件”,是 aufs 的外部 inode 编号转换表,由内核 aufs 模块内部使用。

可以从 sysfs 中读取文件路径:

# cat /sys/fs/aufs/si_*/xi_path         
/tmp/rw/.aufs.xino

但由于文件已被删除,因此无法直接看到:

# ls -l /tmp/rw/.aufs.xino
ls: cannot access /tmp/rw/.aufs.xino: No such file or directory

但是,可以从 debugfs 中读取有关其大小以及其他特殊 aufs 文件大小的信息:

# for f in /sys/kernel/debug/aufs/si_8c8d888a/* ; do echo -n "$f: " ; cat $f ; done 
/sys/kernel/debug/aufs/si_8c8d888a/xi0: 1, 32x4096 132416
/sys/kernel/debug/aufs/si_8c8d888a/xi1: 1, 24x4096 626868
/sys/kernel/debug/aufs/si_8c8d888a/xib: 8x4096 4096
/sys/kernel/debug/aufs/si_8c8d888a/xigen: 8x4096 88

详细信息请参见aufs 手册页

解决方案

可以通过以下方式手动截断“xino 文件”:

# mount -o remount,itrunc_xino=0 /tmp/mnt

在挂载 aufs 时可以使用 trunc_xino 选项来请求自动 xino 文件截断:

# mount -t aufs -n -o "br:/tmp/rw:/usr,trunc_xino" none "/tmp/mnt"

我仍然不知道它如何影响文件系统性能,或者这是否真的能解决我的生产中的 tmpfs 空间不足问题......但我已经学到了很多东西。

答案2

我曾见过这种情况:文件被删除,但进程仍保留着该文件,这意味着空间直到进程重新启动后才会释放。我在 Apache 日志文件中也见过这种情况。它似乎继续写入现已删除的日志文件,空间直到重新启动后才会被清除。

要找出哪个进程可能保留了已删除的文件,您可以尝试重新启动每个进程,看看是否能清除空间。如果能,您就找到了罪魁祸首。

高血压

相关内容