核心概念:为什么需要垃圾回收?

在 JFFS2 中,当数据需要修改或文件被删除时,它并不会在原来的位置覆盖写入。而是:

  1. 写入新数据:在闪存的空闲区域写入新的数据节点。
  2. 标记旧数据无效:之前存储旧数据的数据节点会被标记为“过时”或“脏”。
    随着文件系统的运行,闪存上会积累大量的“过时”节点,它们占据着空间但却无法再被使用。为了回收这些空间以供新的写入操作使用,JFFS2 必须有一个机制来清理这些“垃圾”区块,这个机制就是垃圾回收。

JFFS2垃圾回收触发机制

内核代码打开相关日志

垃圾回收相关代码路径kernel/fs/jffs2/gc.c,垃圾回收相关的打印由jffs2_dbg打印,相关代码路径kernel/fs/jffs2/debug.h我这边通过修改源码的方式将相关打印放开:

原代码,

#define jffs2_dbg(level, fmt, ...)		\
do { \
if (CONFIG_JFFS2_FS_DEBUG >= level) \
pr_debug(fmt, ##__VA_ARGS__); \
} while (0)

修改后,直接将printk的条件限制取消

#define jffs2_dbg(level, fmt, ...)		\
do { \
printk(fmt, ##__VA_ARGS__); \
} while (0)

相关打印:

[ 1848.178662] Picking block from very_dirty_list to GC next
[ 1848.178709] GC from block 00000000, used_size 00004ee4, dirty_size 0000b11c, free_size 00000000

何时触发?

自测会自动触发,但是有概率遇到过没有触发的情况(滚存写完立刻重启,重复N次),需要手动将文件复制到临时目录,在删除原文件,在复制回去,需要倒腾一手才能触发,目前没有研究明白原因