使用NFS时出现nfs_inode_cache占用内存过高问题的解决

本文介绍了一种因NFS文件系统引发的内存泄漏现象及排查过程。通过top、pmap等命令定位问题源头为nfs_inode_cache缓存异常膨胀,并提供了升级内核、打补丁及手动释放内存等解决方案。
一、现象
运行了使用NFS文件系统的应用程序后,内存缓慢泄漏,
最后导致整个服务器的内存全部耗尽,系统调起多个pdflush进程,并占到CPU的99%,
这时整个系统系统变得处理速度极慢,那怕是敲个命令都慢得不行;

二、检查流程
1. 查看系统最耗内存的进程
# top -m
Tasks: 428 total,   1 running, 427 sleeping,   0 stopped,   0 zombie
Cpu(s):  5.4%us,  0.1%sy,  0.0%ni, 94.4%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  32915200k total,  1576064k used, 31339136k free,   284588k buffers
Swap:  8385920k total,        0k used,  8385920k free,   317440k cached


  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                       
14099 root      15   0  144m  96m 2160 S  0.0  0.3 309:57.67 your_program 

发现最耗内存的就是使用NFS的应用程序;

2. 查看进程占用的内存
# pmap 进程号
...
00007fffbebfd000     12K r-x--    [ anon ]
ffffffffff600000   8192K -----    [ anon ]
 total           154604K

但应用程序实际使用的内存并不多,这时就开始怀疑是系统的原因;

3. 系统内存查看
每两秒统计一次内存使用情况,看内存的使用速度
# vmstat 2
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 31317192 284620 337800    0    0     0     0    0    1  5  0 94  0  0
...

接着看到底是什么占用了这么多内存,先看内核空间的
# vmstat -m 
Cache                       Num  Total   Size  Pages
nfs_direct_cache              0      0    136     28
nfs_write_data              189    207    832      9
nfs_read_data                32     40    768      5
nfs_inode_cache          1027389 1027389   1032      3
nfs_page                    304    360    128     30
...
kmem_cache                  144    144   2688      1

发现了是nfs_inode_cache异常,占用了大量的内存;

3. 使用slabtop命令查看内核slab 缓冲区信息
# slabtop -s c | head 
 Active / Total Objects (% used)    : 3318152 / 3333777 (99.5%)
 Active / Total Slabs (% used)      : 561213 / 561243 (100.0%)
 Active / Total Caches (% used)     : 92 / 145 (63.4%)
 Active / Total Size (% used)       : 1848724.93K / 1851100.14K (99.9%)
 Minimum / Average / Maximum Object : 0.02K / 0.55K / 128.00K


  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
1014219 1014219 100%    1.01K 338073        3   1352292K nfs_inode_cache

1021475 1021475 100%    0.52K 145925        7    583700K radix_tree_node
#

我们看到 nfs_inode_cache 占用了大概 1.3GB,
在正常情况下,nfs_inode_cache 应该 30 MiB 左右。所以 nfs_inode_cache 在这里是异常的。

三、原因
Redhat官方的解释:
https://access.redhat.com/site/solutions/64667
《nfs_inode_cache usage is high compared to older kernels on RHEL 5 and RHEL 6,
 and possibly system hangs with pdflush / flush consuming CPU》

Issue 
. nfs_inode_cache usage is high compared to older kernels. 
. pdflush or flush processes consuming 100% CPU, or soft lockups with pdflush or flush process running in nfs_flush_inode 
. nfs_inode_cache grows uncontrolled and memory pressure does not release the memory. 
. Under certain type of load the NFS performance from RHEL 6.1 client becomes very slow. 
  The case scenario: after writing a large number of small sized files in a sequence, 
  the write speed for large sized files becomes very slow, around 5 MB/sec or even less.
  When writing large sized files is not preceded by a sequence of writing large number of small sized files 
  the speed is normal - around 200 MB/sec. 
. nfs_inode_cache getting very big and eating the total amount of RAM 

Environment
Red Hat Enteprise Linux 5.7 (2.6.18-274) 
Red Hat Enteprise Linux 6.1 (2.6.32-131.0.15) 
NFS client 

所以是内核的bug引起的;

四、解决办法
1. 内核升级
可以参见我写的《linux内核升级图文攻略》;

2. 给系统打补丁
# wget http://mirror.centos.org/centos/5/os/i386/CentOS/kernel-2.6.18-371.el5.i686.rpm
--2014-03-31 16:28:20--  http://mirror.centos.org/centos/5/os/i386/CentOS/kernel-2.6.18-371.el5.i686.rpm
Resolving mirror.centos.org... 94.46.0.18
Connecting to mirror.centos.org|94.46.0.18|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 20779178 (20M) [application/x-rpm]
Saving to: `kernel-2.6.18-371.el5.i686.rpm'

100%[==================================================>] 20,779,178  74.1K/s   in 4m 9s   
2014-03-31 16:32:31 (81.5 KB/s) - `kernel-2.6.18-371.el5.i686.rpm' saved [20779178/20779178]

# rpm -Uvh kernel-2.6.18-371.el5.i686.rpm 
# uname -r

3. 定期手动释放内存
/proc是一个虚拟文件系统,我们可以通过对它的读写操作做为与kernel实体间进行通信的一种手段。
也就是说可以通过修改/proc中的文件,来对当前kernel的行为做出调整。
那么我们可以通过调整/proc/sys/vm/drop_caches来释放内存。
操作如下:
# cat /proc/sys/vm/drop_caches               【首先,/proc/sys/vm/drop_caches的值,默认为0。】
0
# sync                                       【手动执行sync命令(描述:sync 命令运行 sync 子例程。
                                               如果必须停止系统,则运行sync 命令以确保文件系统的完整性。
                                               sync 命令将所有未写的系统缓冲区写到磁盘中,
                                               包含已修改的 i-node、已延迟的块 I/O 和读写映射文件)
# echo 2 > /proc/sys/vm/drop_caches          【将/proc/sys/vm/drop_caches值设为2】
# cat /proc/sys/vm/drop_caches
2
# free -m
     total used free shared buffers cached
Mem:  249   66   182      0     0    11
-/+ buffers/cache: 55 194
Swap: 511 0 511

再来运行free命令,会发现现在的used为66MB,free为182MB,buffers为0MB,cached为11MB。
那么有效的释放了buffer和cache。

可以设置成定时任务
# crontab -e
0 */4 * * * sync&&echo 2 >/proc/sys/vm/drop_caches










<think>嗯,用户这次问的是Linux inode_cache,结合之前的引用材料来看,ta可能在排查系统性能问题或研究内核机制。虽然用户没有明确说明场景,但引用[2]提到nfs_inode_cache内存问题,说明ta的实际需求更偏向故障排查而非纯理论。 注意到用户提供的三个引用很有针对性:[1]讲inode缓存结构,[2]是NFS场景下的内存问题案例,[3]涉及inode操作接口。这提示我需要把理论机制和实际应用结合起来回答,尤其要突出内存管理部分。 用户上次问过Android的Binder机制,这次转向Linux内核,跨度较大。可能是系统工程师或运维人员,对底层原理有持续探索需求。回答既要保持技术深度,又要给出可操作的解决方案——比如内存泄漏的排查方法。 关于inode_cache的核心点需要覆盖: 1)基本定义:必须强调inode_cache是slab分配器管理的缓存池,区别于page cache 2)链表结构:四个链表的功能差异要讲透,特别是"未使用链表"的LRU机制 3)NFS相关:引用[2]的案例表明这是常见痛点,需单独展开 4)调试方法:给出现成的命令和工具链,如slabtop、drop_caches 内存泄漏部分要重点设计排查路径:先看slabinfo,再定位具体inode类型,最后结合内核文档。引用[2]提到的nfs_flush_inode进程卡死是个典型线索,可以纳入排查步骤。 最后的问题设计要延续实用性方向:性能优化、内存回收、监控工具都是用户可能需要的延伸知识。特别加入NFS是因为引用材料暗示了用户环境涉及网络文件系统。</think>### Linux inode_cache 详解与管理 #### 1. **inode_cache 的本质** Linux 的 **inode_cache** 是内核通过 Slab 分配器(`inode_cachep`)管理的缓存机制,用于效存储和管理文件系统的 **inode 对象**。每个 inode 代表文件系统中的唯一文件(或目录),包含元数据(权限、大小、间戳等)和指向数据块的指针。该缓存通过以下**双向链表**组织内存中的 inode 对象[^1]: - **正在使用inode 链表**:当前被进程访问的活跃 inode。 - **未使用inode 链表**:未被使用但保留在内存中(采用 LRU 算法管理)。 - **inode 哈希链表**:通过哈希表快速定位 inode(根据超级块和 inode 号计算哈希值)。 - **匿名 inode 哈希链表**:用于特殊文件(如管道、套接字)的匿名 inode。 #### 2. **核心管理机制** - **Slab 分配器优化** 通过 `inode_cachep` Slab 缓存批量分配/释放 inode 对象,减少内存碎片,提升分配效率。 - **LRU 内存回收** 当系统内存不足,内核从“未使用inode 链表”尾部淘汰旧 inode 释放内存[^1]。 - **哈希表加速查询** 哈希链表确保根据 `(超级块, inode号)` 快速查找 inode,降低访问延迟。 #### 3. **常见问题与排查方法** ##### 问题:`nfs_inode_cache` 内存占用(如引用[2]) **原因**: - NFS 客户端频繁访问远程文件,导致大量 inode 缓存未及释放。 - 网络延迟或服务端故障使 `nfs_flush_inode` 进程(负责写回数据)阻塞,引发缓存堆积[^2]。 **解决方案**: 1. **手动释放缓存**(临): ```bash sync && echo 2 > /proc/sys/vm/drop_caches # 释放所有 Slab 缓存 ``` 2. **调整 NFS 参数**: ```bash # 减少缓存停留间(单位:秒) echo 600 > /proc/fs/nfs/inode_cache_expire_time ``` 3. **监控工具**: - 查看 Slab 缓存占用: ```bash slabtop -o | grep inode_cache # 按内存排序显示 ``` - 检查内存分布: ```bash cat /proc/meminfo | grep -e Slab -e SReclaimable ``` ##### 问题:`pdflush` 或 `flush` 进程 CPU 占用 100%(如引用[2]) **原因**: `nfs_flush_inode` 持续尝试写回脏数据失败,导致进程阻塞。 **解决步骤**: 1. 检查 NFS 服务端状态:`rpcinfo -p <server_ip>` 2. 排查网络延迟:`ping <server_ip>` 3. 重启 NFS 服务:`systemctl restart nfs-client.target` #### 4. **inode_operations 的角色** 内核通过 `struct inode_operations` 定义 inode 的行为(如引用[3]),例如: ```c struct inode_operations { struct dentry * (*lookup) (struct inode *, struct dentry *, unsigned int); // 查找目录项 int (*permission) (struct inode *, int); // 检查权限 struct posix_acl * (*get_acl)(struct inode *, int); // 获取访问控制列表 }; ``` 这些函数指针由具体文件系统(如 ext4、NFS)实现,控制 inode 的底层操作[^3]。 --- ### 管理总结 | **操作** | **命令/文件** | **作用** | |-------------------------|----------------------------------|-----------------------------------| | 查看 Slab 缓存 | `slabtop` 或 `cat /proc/slabinfo` | 分析 `inode_cache` 内存占用 | | 手动释放缓存 | `echo 2 > /proc/sys/vm/drop_caches` | 紧急释放 Slab 缓存(包括 inode) | | 调整 NFS 缓存过期 | `/proc/fs/nfs/inode_cache_expire_time` | 缩短 inode 缓存保留间 | | 监控内存 | `cat /proc/meminfo` | 查看 Slab 总内存和可回收部分 | > **关键提示**: > - 生产环境中避免频繁 `drop_caches`,可能引发性能抖动。 > - NFS 问题优先排查网络和服务端状态,而非仅调整客户端[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北雨南萍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值