VFS:达到文件最大限制 1231582

Ric*_*shi 7 linux kernel

我正在运行 Linux 2.6.36 内核,并且看到一些随机错误。像

ls: error while loading shared libraries: libpthread.so.0: cannot open shared object file: Error 23
Run Code Online (Sandbox Code Playgroud)

是的,我的系统无法始终如一地运行“ls”命令。:(

我注意到我的 dmesg 输出中有几个错误:

# dmesg | tail
[2808967.543203] EXT4-fs (sda3): re-mounted. Opts: (null)
[2837776.220605] xv[14450] general protection ip:7f20c20c6ac6 sp:7fff3641b368 error:0 in libpng14.so.14.4.0[7f20c20a9000+29000]
[4931344.685302] EXT4-fs (md16): re-mounted. Opts: (null)
[4982666.631444] VFS: file-max limit 1231582 reached
[4982666.764240] VFS: file-max limit 1231582 reached
[4982767.360574] VFS: file-max limit 1231582 reached
[4982901.904628] VFS: file-max limit 1231582 reached
[4982964.930556] VFS: file-max limit 1231582 reached
[4982966.352170] VFS: file-max limit 1231582 reached
[4982966.649195] top[31095]: segfault at 14 ip 00007fd6ace42700 sp 00007fff20746530 error 6 in libproc-3.2.8.so[7fd6ace3b000+e000]
Run Code Online (Sandbox Code Playgroud)

显然,file-max 错误看起来很可疑,它们聚集在一起并且是最近发生的。

# cat /proc/sys/fs/file-max
1231582
# cat /proc/sys/fs/file-nr
1231712 0       1231582
Run Code Online (Sandbox Code Playgroud)

这对我来说也有点奇怪,但问题是,我不可能在这个系统上打开 120 万个文件。我是唯一一个使用它的人,本地网络之外的任何人都看不到它。

# lsof | wc
  16046  148253 1882901
# ps -ef | wc 
    574    6104   44260
Run Code Online (Sandbox Code Playgroud)

我看到一些文档说:

文件最大和文件编号:

内核动态地分配文件句柄,但还没有再次释放它们。

file-max 中的值表示 Linux 内核将分配的最大文件句柄数。当您收到大量有关耗尽文件句柄的错误消息时,您可能希望增加此限制。

历史上,file-nr 中的三个值表示已分配的文件句柄数、已分配但未使用的文件句柄数和最大文件句柄数。Linux 2.6 总是报告 0 作为空闲文件句柄的数量——这不是错误,它只是意味着分配的文件句柄数量与使用的文件句柄数量完全匹配。

尝试分配比 file-max 多的文件描述符会用 printk 报告,查找“VFS:达到文件最大限制”。

我对这个的第一次阅读是内核基本上有一个内置的文件描述符泄漏,但我发现这很难相信。这意味着任何正在使用的系统都需要经常重新启动以释放文件描述符。正如我所说,我无法相信这是真的,因为让 Linux 系统一次运行数月(甚至数年)对我来说是正常的。另一方面,我也不敢相信我几乎空闲的系统打开了超过一百万个文件。

有没有人有任何想法,无论是修复还是进一步诊断?当然,我可以重新启动系统,但我不希望这每隔几周就会重复出现。作为权宜之计,我已经退出了 Firefox,即使我只打开了一个窗口,它也占了近 2000 行 lsof 输出(!),现在我可以再次运行 'ls',但我怀疑这会解决问题很久了。(编辑:哎呀,说得太早了。当我完成这个问题时,症状已经/又回来了)

在此先感谢您的帮助。


另一个更新:我的系统基本上无法使用,所以我决定我别无选择,只能重新启动。但在此之前,我小心地一次退出一个进程,/proc/sys/fs/file-nr在每次终止后检查。我发现,可以预见的是,当我关闭时,打开的文件数量逐渐减少。不幸的是,这并不是一个很大的影响。是的,我能够清理 5000-10000 个打开的文件,但仍然有超过 120 万个。我关闭了几乎所有的东西。所有交互式 shell,除了我打开以完成关闭的 ssh、httpd,甚至 nfs 服务。基本上进程表中的所有内容都不是内核进程,而且仍然有数量惊人的文件显然处于打开状态。

重新启动后,我发现/proc/sys/fs/file-nr显示大约打开了2000个文件,这更合理。像往常一样启动 2 个 Xvnc 会话,以及我喜欢保持打开的十几个监控窗口,使文件总数达到大约 4000 个。当然,我看不出有什么问题,但我显然未能确定根本原因。

我仍在寻找想法,因为我绝对希望它再次发生。


另一个更新,第二天:

我仔细观察了系统,发现/proc/sys/fs/file-nr每小时大约有 900 个打开的文件在增长。我在晚上关闭了系统唯一的 NFS 客户端,增长停止了。请注意,它并没有释放资源,但它至少停止了消耗更多的资源。这是 NFS 的已知错误吗?今天我将让 NFS 客户端重新联机,并进一步缩小范围。

如果有人熟悉这种行为,请随时加入“是的,NFS4 有这个问题,回到 NFS3”或类似的问题。

Ric*_*shi 7

经过更多测试,我认为这是 NFS 服务器错误。当 NFS 客户端上的进程在文件上放置写锁时,服务器会保留一个打开的文件句柄(这可能是错误的术语 - 我向任何阅读此内容的实际内核专家道歉)。如果服务器在释放锁时释放句柄,这可能没问题,但显然没有。

我原来的问题发生在 rrdtool。rrdtool 打开文件进行读/写,锁定文件进行写入,进行更改,然后退出。每次运行rrdtool,服务器上打开的文件数增加1。(挑剔的细节——服务器实际上以 32 个块为单位进行分配,所以它更像是“32 次运行生成 32 个打开的文件描述符”,但从长远来看,这是一个微不足道的细节)

我编写了一个最小的测试程序来验证这种行为。事实上,打开文件,锁定它,然后退出就足以触发这个。在退出之前显式释放锁没有任何帮助。打开该文件,而不锁定它并没有引发问题。

目前为止,除了重启,我还没有找到释放服务器资源的方法。如上所述,重新启动 NFS 服务是不够的。

我还没有测试 NFS 版本 3。也许它效果更好。

无论如何,感谢您的尝试。希望我的经历能在未来对其他人有所帮助。


最后一个更新:J. Bruce Fields,NFSv4 开发人员之一,已经确认这是一个错误,并表示它仅限于 NFSv4。看来我是第一个举报的。他希望尽快有补丁。

记住,孩子们:当你发现一个错误时,找到合适的地方报告它,它很有可能得到修复。为开源欢呼吧。:-)