在f2fs读写文件的时候,每修改一个块,都会改动f2fs_node的地址映射和NAT、SIT信息。为了避免频繁刷盘,f2fs将这种小变化写到journal里,在CP的时候再写入磁盘。
journal相关的数据结构有
struct f2fs_journal {
union {
__le16 n_nats; /* 这个journal里面包含多少个nat_journal对象 */
__le16 n_sits; /* 这个journal里面包含多少个sit_journal对象 */
};
/* spare area is used by NAT or SIT journals or extra info */
union {
struct nat_journal nat_j;
struct sit_journal sit_j;
struct f2fs_extra_info info;
};
} __packed;
这表示一个f2fs_journal要么保存nat,要么保存sit。
nat journal:
struct nat_journal {
struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES];
__u8 reserved[NAT_JOURNAL_RESERVED];
} __packed;
struct nat_journal_entry {
__le32 nid;
struct f2fs_nat_entry ne;
} __packed;
struct f2fs_nat_entry {
__u8 version; /* latest version of cached nat entry */
__le32 ino; /* inode number */
__le32 block_addr; /* block address */
} __packed;
sit journal
struct sit_journal {
struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES];
__u8 reserved[SIT_JOURNAL_RESERVED];
} __packed;
struct sit_journal_entry {
__le32 segno;
struct f2fs_sit_entry se;
} __packed;
struct f2fs_sit_entry {
__le16 vblocks; /* reference above */
__u8 valid_map[SIT_VBLOCK_MAP_SIZE]; /* SIT_VBLOCK_MAP_SIZE = 64,64 * 8 = 512 可以表示每一个块的valid状态 */
__le64 mtime; /* segment age for cleaning */
} __packed;
在f2fs_get_node_info中,首先在journal中找到地址。如果没找到,再去读盘上的f2fs_nat_block。
在cp的时候,将journal的信息写盘。
f2fs_flush_nat_entries
和 f2fs_flush_sit_entries
函数将entry都写入到 curseg_info->f2fs_summary->journal
的变量中。do_checkpoint函数
读取 curseg_info->f2fs_summary,然后通过函数f2fs_write_node_summaries或
f2fs_write_data_summaries` 刷写到磁盘中。