外部QSPI Flash分区删除文件后空间未释放的偶发问题排查
UBIFS大文件删除后空间未释放的偶发问题
背景
外接QSPI Flash的嵌入式设备,某MTD分区挂载UBIFS,用于存储最大17MB的固件镜像(仅作存储,不加载到DDR执行)。固件升级流程为:写入新固件后删除旧固件镜像。
异常现象
偶发出现:旧固件文件已不在ls输出中,但分区空间占用未相应减少。该情况仅针对17MB的大文件,且删除操作(通过remove()调用)完成后6-8秒就重置控制器时触发。
异常状态下的df输出
ubi16_0 72008 61016 7292 89% /problematic_partition
分区内实际文件列表
-rw-r----- 1 root root 4 May 28 15:02 File1Crc -rw-r----- 1 root root 745394 May 28 15:02 File2 -rw-r----- 1 root root 4 May 28 15:02 File2Crc -rw-r----- 1 root root 16344418 May 28 15:02 File3 -rw-r----- 1 root root 4 May 28 15:02 File3Crc -rw-r----- 1 root root 654930 May 28 15:02 File4 -rw-r----- 1 root root 4 May 28 15:02 File4Crc -rw-r--r-- 1 root root 925984 May 25 12:24 File5 -rw-r--r-- 1 root root 4 May 25 12:24 File5Crc -rw-r----- 1 root root 4 May 28 15:02 File6Crc -rw-r----- 1 root root 4 May 28 15:02 File7Crc -rw-r--r-- 1 root root 1504984 May 25 12:24 File8 -rw-r--r-- 1 root root 4 May 25 12:24 File9Crc -rw-r--r-- 1 root root 13403492 May 25 12:24 File10 -rw-r--r-- 1 root root 4 May 25 12:24 File10Crc -rw-r--r-- 1 root root 888784 May 25 12:24 File11Fw -rw-r--r-- 1 root root 4 May 25 12:24 File11Crc -rw-r--r-- 1 root root 675048 May 25 12:24 File12 -rw-r--r-- 1 root root 4 May 25 12:24 File12Crc -r-xr--r-- 1 root root 123 May 27 21:48 info.txt -rw-r--r-- 1 root root 114272 May 29 05:36 eventlog -rw-r--r-- 1 root root 512321 May 29 05:28 eventlog.0 -rw-r--r-- 1 root root 512260 May 26 12:34 eventlog.1 -rw-r--r-- 1 root root 512103 May 26 08:54 eventlog.2 -rw-r--r-- 1 root root 512318 May 25 13:25 eventlog.3 -rw-r--r-- 1 root root 512291 May 25 12:39 eventlog.4 -rw-r--r-- 1 root root 512245 May 25 12:21 eventlog.5 -rw-r--r-- 1 root root 512254 May 25 12:11 eventlog.6 -rw-r--r-- 1 root root 512288 May 25 11:56 eventlog.7 -rw-r--r-- 1 root root 2 Aug 17 2022 eventlog_dormant.txt -rw-r--r-- 1 root root 5 Aug 17 2022 eventlog_duplex.txt -rw-r--r-- 1 root root 5 Aug 17 2022 eventlog_opersatate.txt -rw-r--r-- 1 root root 2 Aug 17 2022 eventlog_type.txt drwxr-xr-x 2 root root 160 Jan 1 2015 mmc -rw-r--r-- 1 root root 76 May 28 15:12 platform.nvs
空间占用差异
实际文件总大小对应分区占用约54%(39.3MB),加上root预留的3MB,df却显示占用约61MB。此时写入超10MB会因空间耗尽失败。该“幽灵占用”仅能通过卸载UBI卷、用flash_eraseall擦除分区、重新挂载恢复,重启无效。
用户问题
- 该问题为何偶发,且仅能通过上述方式恢复?
remove()删除大文件后短时间重置控制器是否会导致该异常?
解答
问题1分析
UBIFS采用延迟垃圾回收+写回缓存策略:删除文件时,仅在内存中标记文件目录项为删除、对应Flash块为废弃,不会立即同步到Flash。只有当缓存满、触发垃圾回收或显式同步时,才会将这些元数据变更写入Flash。
偶发原因:
- 仅当
remove()返回后,UBIFS还未完成元数据(废弃块标记、目录项更新)的Flash写入就触发重置时才会发生;大文件涉及更多Flash块标记,元数据同步窗口更长,所以仅大文件出现该问题。
只能通过擦除分区恢复的原因:
- 重启时UBIFS会加载Flash中已持久化的元数据,错误的元数据(认为被删除文件的块仍占用空间)已经固化在Flash上,重启无法修正;
flash_eraseall会彻底清除分区内所有数据,重新挂载时生成全新的元数据,才能彻底清除“幽灵占用”。
问题2分析
是的,remove()删除大文件后短时间重置控制器是直接诱因:
remove()调用返回仅代表内核完成了文件系统层面的删除操作,但UBIFS为了性能,会将元数据变更缓存到内存,延迟写入Flash;- 6-8秒的窗口刚好落在元数据未完成Flash同步的时间段,此时重置会导致内存中的变更丢失,Flash上的元数据仍认为那些块是被占用的,从而出现空间未释放的情况。
预防与恢复建议
- 恢复方法:保留当前的卸载+
flash_eraseall+重新挂载流程,这是彻底清除错误元数据的唯一方法; - 预防方法:
- 删除大文件后,调用
sync()或fsync()强制将文件系统元数据同步到Flash,再执行控制器重置; - 调整UBIFS的元数据同步参数,缩短延迟(需权衡性能与可靠性);
- 升级UBIFS内核版本,修复可能存在的元数据同步bug。
- 删除大文件后,调用
内容的提问来源于stack exchange,提问作者Elliott Goldstein
相关产品推荐
相关产品推荐

