2018年的问题,今天才看到,2018年那会我应该正好在VxWorks做相关的内容:高可靠文件系统的开发维护,也就是那个(bug巨多的)HRFS。
先说一些结论吧:
1. 不存在绝对可靠的文件系统
2. 可靠性要依赖于硬件,只依靠软件无法实现完整的可靠性
3. 可靠性仅仅指的是元数据(meta-data)
4. 可靠性与性能有冲突
5. 非可靠性相关的:实时性跟性能也有冲突
可靠文件系统的设计原理很简单,本质上就是copy-on-write,设置transaction point,保证transaction point提交的时候,所有依赖的数据都被正确的写入即可。
原理很简单,可以说这个设计,给一个编程水平高一点的本科毕业生都能搞定,但实际实现出来根本不是那么一回事。
最核心的一个问题就是,如何保证数据被确认写下去了?要知道硬件为了提升性能,有硬件缓存(不管是HDD还是SSD),还可能乱序写(SATA-NCQ),还可能多队列(NvME),那么软件怎么保证到transaction point的位置的时候,数据是真的被写下去了?
有人会说,发一个SYNC指令(硬件flush)不行吗?理论上是可以的,至少按照规范来说SATA命令集里是有SYNC指令的,但硬件能不能保证就是另外一回事了。
对于SSD设备,当年SSD刚出来的时候(大概十年前了),就遇到一些劣质的(但是是正规厂商的)SSD产品,对SYNC命令执行不满足期望值,实际并没有SYNC成功。这种情况下,软件用任何手段都无法保证文件系统可靠性。(顺便说一句,没有规范要求硬件写一个扇区的操作是“原子“的,所以理论上一个扇区可能是会写一半的,虽然极其罕见)
对于EMMC设备,EMMC规范里有提到一个可靠写(reliable write)的标志,但设备万一不支持,那么EMMC也不可靠了。
对于USB设备,USB驱动里如果不集成SYNC命令,或者U盘控制器不支持这个命令,那么U盘也不可靠。
对于SPI flash一类的设备,这些都是通过MMIO的方式映射的,总线上的信号可能根本保证不了可靠写,那么文件系统的可靠性就无从谈起。
所以高可靠性文件系统,到实际应用场景就会发现,有各种坑。甚至客户的flash会有比特翻转的问题,但flash焊死在板子上,换不了……你说你搞不定?对不起,客户是上帝,上帝要求你搞定……
搞定硬件可靠性就没问题了吗?也不是,可靠性需要依赖SYNC,SYNC对软件性能是一个极大的破坏,题主描述里提到了HRFS,我可以给点数据,HRFS在关闭SYNC以后(自然也就失去了可靠性),性能提升10-50倍。
其实,也不是没办法降低SYNC的影响,用多组copy-on-write,或者长一点的journal(日志),把多个提交点的内容都记录一下来就可以了。甚至长journal可以抵消一些硬件的不可靠性。出错时回滚一个日志记录不行,就回滚2个,回滚3个……只要你硬盘有空间,然后也不发SYNC了,只要我写的足够多,肯定会把硬件cache写满,写满了自然就刷了。
但这相当于用空间换性能,用空间换可靠性,本质上要看硬件的缓存有多大,而工业级的SSD,缓存可能是上GB的,设计一个日志长达10G的文件系统?客户不疯,开发也疯了。要知道日志多,代码逻辑越复杂,bug可能性更高。
所以即使是一个软件上完美无瑕无bug的文件系统,要实现高可靠性,前置条件也很多。
所以PC操作系统,还有服务器操作系统,选择了另外一条路:搞不定可靠性,那么就从另外一个角度,出错了checkdisk去修复,或者干脆提供一个更可靠的供电系统(UPS)。
Linux和Windows的文件系统实际上更依赖于check disk,虽然EXT和NTFS都有日志系统,也都有check disk,假设文件系统的可靠性是99.9%,check disk能修复99%的错误,那么整体的可靠性就可以达到99.999%了。
Linux和Windows的这种设计思路,比RTOS里的那种高可靠文件系统要更实际一些,也更简单一些,照顾的硬件种类更多,对硬件要求也不是特别高。
因为是两年前的问题,我不确定题主现在是不是已经解决了,对于Linux来说,提供一些方案:
1. 关掉各种缓存,用性能换可靠性;
2. 强制fsck,或者实现一个掉电检测机制,然后每次掉电就fsck;
在RTOS里,性能、可靠性、实时性都是互斥的,只能选择其中的某一个。