fstrim后ext4文件系统df与du报告已用空间不一致问题及空间回收咨询
我之前在折腾类似Radxa Rock 4B+这种ARM嵌入式设备的ext4扩容问题时,碰到过一模一样的情况——明明没往磁盘写任何东西,df突然就报用了19G,可du查根目录实际才4.5G,当时也懵了好一会儿。后来摸清楚了原因,给你拆解下:
核心原因:df和du的统计逻辑不一样
先搞懂两者的本质区别:
df统计的是文件系统已经分配出去的所有块,不管这些块有没有被实际文件占用;du统计的是当前存在的文件真正占用的块数。
你遇到的情况,大概率是以下两种原因之一:
1. 被进程“偷偷占用”的已删除文件
有些系统进程(比如日志服务、后台守护进程)会打开临时文件,之后把文件删除,但进程本身还在运行——这时候文件已经看不到了,但磁盘块还被进程占用着,df会把这些块算成已用,可du不会统计(因为文件已经不存在了)。
2. ext4的延迟分配与块回收延迟
ext4默认开启了延迟分配(delalloc挂载参数),内核为了优化IO性能,会提前预分配一些块;另外用resize2fs扩容后,文件系统调整块组结构时会产生一些临时块,这些块本该被标记为空闲,但内核的回收机制可能有延迟,导致df把它们算成已用空间。
解决方法,按优先级来试
1. 排查“幽灵文件”
先看看有没有被进程占用的已删除文件,执行:
sudo lsof | grep deleted
如果输出里有大文件,要么重启对应的进程,要么直接重启系统——重启后这些被占用的块就会被释放,df的数值就会和du对齐了。
2. 手动触发缓存与块回收
如果是延迟回收的块导致的,强制内核清理脏页并释放空闲块:
sudo sync && sudo sysctl -w vm.drop_caches=3
执行完再跑df -h,应该能看到已用空间降下来。
3. 调整TRIM相关的挂载参数
你的三星NVMe SSD支持TRIM,确保ext4挂载时能及时通知SSD回收空闲块:
- 编辑
/etc/fstab,找到根分区的挂载行,加上discard参数,比如:/dev/nvme0n1p3 / ext4 defaults,discard 0 1 - 重新挂载生效:
sudo mount -o remount,rw,discard /
如果担心discard影响性能,可以改用系统定期自动TRIM:
sudo systemctl enable --now fstrim.timer
4. 检查文件系统一致性
如果以上方法都没用,可能是文件系统有轻微的不一致,先卸载分区(或者进入单用户模式),执行文件系统检查:
sudo fsck.ext4 -f /dev/nvme0n1p3
注意:执行fsck时一定要确保分区未被挂载,不然可能损坏数据。
总结
你这个情况最可能是“被进程占用的已删除文件”或者“延迟回收的块”导致的,先试前两种方法,基本就能解决。调整TRIM参数则能避免后续再出现类似的统计异常。
备注:内容来源于stack exchange,提问作者bigmuscle

