【文件系统】 F2FS文件系统学习

news2025/1/18 14:01:39

一、基本介绍

1、F2FS History

        F2FS(Flash Friendly File System)是专门为Nand Flash设计的一个日志型文件系统,于2012年12月合入Linux3.8内核,Google也在2018年(Android P)将其吸收到安卓原生版本中,使所有使用安卓的厂商受益

2、F2FS特点

        F2FS可以极大程度上避免碎片产生,相对于传统日志型文件系统,F2FS在wandering tree和gc方面,有一定的优化,可以复用离散的数据页写入数据,显著减少GC带来的卡顿

wandering tree:在文件更新时,指向文件的DIrect Pointer由于数据异地更新,也会随之更新 ,同时指向这个DIrect Pointer的Indirect Pointer也会更新,然后保存这个Indirect Pointer的inode、inode blockmap等结构也需要更新,这样会导致频繁的metadata更新

3、为什么需要F2FS

        Nand Flash在更新某个位置的值时,必须先擦除,才能写入新的内容,如果在频繁写入的场景,都需要消耗大量的时间进行擦除,导致整体性能下降。F2FS基于LFS型文件系统,解决了先擦后写的问题,当需要更新某个块时,会重新申请一个未使用的快,将数据写到新的块上,并更新相应的管理数据,这样就避免等待block擦除的开销,并且可以将随机写转化为顺序写,提升性能

        不仅仅是提升性能,对写放大也有所降低,这是因为如果按照先擦后写,就会导致某个块频繁被删除,导致写穿寿命到期,成为坏块,而F2FS使用append-only logging策略,按顺序写入数据,天然的在文件系统层做了磨损均衡,延长了设备使用寿命

        此外,F2FS支持冷热Node/Data分流,将不经常变动的数据写入冷分区,将经常需要变动的数据写入到热分区,这样在器件回收数据块时,可以根据数据块的冷热进行选择,提高回收效率

二、F2FS 数据结构

1、F2FS Layout

        F2FS磁盘布局如下图所示,它考虑了闪存感知和低清理成本

闪存感知:指文件系统匹配闪存物理特性

        (a)superblock metadata放在一起,且是头部,提高局部性和并行性

        (b)main area起始地址对对齐zoned大小,考虑了FTL工作特性

        (c)以section为单位进行文件系统GC

低清理成本:使用Multi-Stream logging实现冷热数据分流

(a)F2FS将整个磁盘划分为若干segment,每个大小为2MB

(b)目前zone,section,segment都是1:1:1的关系,zone的大小与物理设备有关

(c)除superblock外,其他area都有多个segment

(d)1个segment包含512个block,1个block大小为4KB

 (1) SuperBlock

        该区域占一个segment(2MB),包含两个f2fs_super_block数据结构,每个占用4KB。

struct f2fs_super_block {
	__le32 magic;			/* Magic Number */
	__le16 major_ver;		/* Major Version */
	__le16 minor_ver;		/* Minor Version */
	__le32 log_sectorsize;		/* log2 sector size in bytes */
	__le32 log_sectors_per_block;	/* log2 # of sectors per block */
	__le32 log_blocksize;		/* log2 block size in bytes */
	__le32 log_blocks_per_seg;	/* log2 # of blocks per segment */
	__le32 segs_per_sec;		/* # of segments per section */
	__le32 secs_per_zone;		/* # of sections per zone */
	__le32 checksum_offset;		/* checksum offset inside super block */
	__le64 block_count;		/* total # of user blocks */
	__le32 section_count;		/* total # of sections */
	__le32 segment_count;		/* total # of segments */
	__le32 segment_count_ckpt;	/* # of segments for checkpoint */
	__le32 segment_count_sit;	/* # of segments for SIT */
	__le32 segment_count_nat;	/* # of segments for NAT */
	__le32 segment_count_ssa;	/* # of segments for SSA */
	__le32 segment_count_main;	/* # of segments for main area */
	__le32 segment0_blkaddr;	/* start block address of segment 0 */
	__le32 cp_blkaddr;		/* start block address of checkpoint */
	__le32 sit_blkaddr;		/* start block address of SIT */
	__le32 nat_blkaddr;		/* start block address of NAT */
	__le32 ssa_blkaddr;		/* start block address of SSA */
	__le32 main_blkaddr;		/* start block address of main area */
	__le32 root_ino;		/* root inode number */
	__le32 node_ino;		/* node inode number */
	__le32 meta_ino;		/* meta inode number */
	__u8 uuid[16];			/* 128-bit uuid for volume */
	__le16 volume_name[MAX_VOLUME_NAME];	/* volume name */
	__le32 extension_count;		/* # of extensions below */
	__u8 extension_list[F2FS_MAX_EXTENSION][F2FS_EXTENSION_LEN];/* extension array */
	__le32 cp_payload;
	__u8 version[VERSION_LEN];	/* the kernel version */
	__u8 init_version[VERSION_LEN];	/* the initial kernel version */
	__le32 feature;			/* defined features */
	__u8 encryption_level;		/* versioning level for encryption */
	__u8 encrypt_pw_salt[16];	/* Salt used for string2key algorithm */
	struct f2fs_device devs[MAX_DEVICES];	/* device list */
	__le32 qf_ino[F2FS_MAX_QUOTAS];	/* quota inode numbers */
	__u8 hot_ext_count;		/* # of hot file extension */
	__le16  s_encoding;		/* Filename charset encoding */
	__le16  s_encoding_flags;	/* Filename charset encoding flags */
	__u8 s_stop_reason[MAX_STOP_REASON];	/* stop checkpoint reason */
	__u8 s_errors[MAX_F2FS_ERRORS];		/* reason of image corrupts */
	__u8 reserved[258];		/* valid reserved region */
	__le32 crc;			/* checksum of superblock */
} __packed;

        SuperBlock的内容在格式化时候就被确定,通常不会被修改,为了更好的适配VFS层,放在磁盘第一个扇区。它的主要作用是记录整个文件系统的分区信息,包括总的block的数量、已使用的block数量、各区的起始地址、F2FS的默认参数、支持的特性等。在F2FS挂载时,内存会创建一个f2fs_sb_info结构从superblock中读取相关数据。

        为了避免文件系统崩溃,它具有2个备份,如果#0损坏,则使用#1恢复,

 (2) CheckPoint

        该区域占2个segment(4MB),记录了上次卸载F2FS时刻,系统的block、node的分配状态,用于下次挂载F2FS时,恢复整个系统的block,node分配状态,主要作用就是为了保持数据一致性

struct f2fs_checkpoint {
	__le64 checkpoint_ver;		/* checkpoint block version number */
	__le64 user_block_count;	/* # of user blocks */
	__le64 valid_block_count;	/* # of valid blocks in main area */
	__le32 rsvd_segment_count;	/* # of reserved segments for gc */
	__le32 overprov_segment_count;	/* # of overprovision segments */
	__le32 free_segment_count;	/* # of free segments in main area */

	/* information of current node segments */
	__le32 cur_node_segno[MAX_ACTIVE_NODE_LOGS];
	__le16 cur_node_blkoff[MAX_ACTIVE_NODE_LOGS];
	/* information of current data segments */
	__le32 cur_data_segno[MAX_ACTIVE_DATA_LOGS];
	__le16 cur_data_blkoff[MAX_ACTIVE_DATA_LOGS];
	__le32 ckpt_flags;		/* Flags : umount and journal_present */
	__le32 cp_pack_total_block_count;	/* total # of one cp pack */
	__le32 cp_pack_start_sum;	/* start block number of data summary */
	__le32 valid_node_count;	/* Total number of valid nodes */
	__le32 valid_inode_count;	/* Total number of valid inodes */
	__le32 next_free_nid;		/* Next free node number */
	__le32 sit_ver_bitmap_bytesize;	/* Default value 64 */
	__le32 nat_ver_bitmap_bytesize; /* Default value 256 */
	__le32 checksum_offset;		/* checksum offset inside cp block */
	__le64 elapsed_time;		/* mounted time */
	/* allocation type of current segment */
	unsigned char alloc_type[MAX_ACTIVE_LOGS];

	/* SIT and NAT version bitmap */
	unsigned char sit_nat_version_bitmap[];
} __packed;

        在运行中,F2FS会定期将当前分配状态写入CheckPoint区域,采用“乒乓操作”,如上次写入的是cp#0,下次就会写入cp#1,在此数据结构中有一个checkpoint_ver用来记录版本,如果两个cp都能用,则会选择最新的那个

        CheckPoint一般只在F2FS启动时候被读取,用于数据恢复,在运行过程中大部分都是被写,用于记录恢复信息。当F2FS需要通过fsync或umount等命令对系统同步时,F2FS会触发一次CheckPoint机制,主要完成以下工作

a.页缓存的脏node和dentry block会刷写回到磁盘;
b.挂起系统其他的写行为,如create,unlink,mkdir;
c.将系统的meta data,如NAT、SIT、SSA的数据写回磁盘;
d.更新checkpoint的状态,包括checkpoint的版本,NAT和SIT的bitmaps以及journals,SSA,Orphan inode
 (3) SIT

        SIT(Segment Information Table)区域记录了Main area中各个segment的详细信息,例如该segment中Valid 以及修改时间等,配合GC流程的选择策略,它的大小由Main Area所占用的segment数量确定的

struct f2fs_sm_info {
	struct sit_info *sit_info;		/* whole segment information */
	struct free_segmap_info *free_info;	/* free segment information */
	struct dirty_seglist_info *dirty_info;	/* dirty segment information */
	struct curseg_info *curseg_array;	/* active segment information */

	struct f2fs_rwsem curseg_lock;	/* for preventing curseg change */

	block_t seg0_blkaddr;		/* block address of 0'th segment */
	block_t main_blkaddr;		/* start block address of main area */
	block_t ssa_blkaddr;		/* start block address of SSA area */

	unsigned int segment_count;	/* total # of segments */
	unsigned int main_segments;	/* # of segments in main area */
	unsigned int reserved_segments;	/* # of reserved segments */
	unsigned int additional_reserved_segments;/* reserved segs for IO align feature */
	unsigned int ovp_segments;	/* # of overprovision segments */

	/* a threshold to reclaim prefree segments */
	unsigned int rec_prefree_segments;

	struct list_head sit_entry_set;	/* sit entry set list */

	unsigned int ipu_policy;	/* in-place-update policy */
	unsigned int min_ipu_util;	/* in-place-update threshold */
	unsigned int min_fsync_blocks;	/* threshold for fsync */
	unsigned int min_seq_blocks;	/* threshold for sequential blocks */
	unsigned int min_hot_blocks;	/* threshold for hot block allocation */
	unsigned int min_ssr_sections;	/* threshold to trigger SSR allocation */

	/* for flush command control */
	struct flush_cmd_control *fcc_info;

	/* for discard command control */
	struct discard_cmd_control *dcc_info;
};
 (4) NAT

        NAT(Segment Information Table)区域记录了node id 与真实地址的关系,其本质是一个中间层,通过该区域,可以避免索引地址,而是索引id号(每个node都有一个nid),NAT的主要作用就是将nid翻译成Main Area中的地址信息,之前的wandering tree问题也是利用了这个区域解决的

        在传统的 LFS中,由于使用直接地址索引,当某个数据块被修改后,导致该数据块的管理块递归修改。例如,在A1 -> B1 -> C1 ->D1的索引树中

a.当D1被修改后,会写入新地址D2
b.而C1索引的是D1的地址,此时该地址是invalid的,所以需要更新C1中存储的值,写入C2
c.以此类推,直到A1被写入A2快中,这就是滚雪球效应,修改一个数据引起连锁反应

A1、B1、C1---管理快
D1---数据块

        引起此问题的根因是采用直接地址作为索引,F2FS解决该问题的思路是引入一个中间层,即NAT表,负责做地址翻译,避免直接索引地址

a.A1中存储B1的id号,B1存储C1的id号
b.C1直接索引D1的地址
c.当D1被修改后,只需要修改C1和NAT表中C1的地址索引即可(NAT表是inplace更新,先擦后写)
d.由于C1的id号保持不变,所以A1和B1都不需要修改

struct f2fs_nm_info {
	block_t nat_blkaddr;		/* base disk address of NAT */
	nid_t max_nid;			/* maximum possible node ids */
	nid_t available_nids;		/* # of available node ids */
	nid_t next_scan_nid;		/* the next nid to be scanned */
	nid_t max_rf_node_blocks;	/* max # of nodes for recovery */
	unsigned int ram_thresh;	/* control the memory footprint */
	unsigned int ra_nid_pages;	/* # of nid pages to be readaheaded */
	unsigned int dirty_nats_ratio;	/* control dirty nats ratio threshold */

	/* NAT cache management */
	struct radix_tree_root nat_root;/* root of the nat entry cache */
	struct radix_tree_root nat_set_root;/* root of the nat set cache */
	struct f2fs_rwsem nat_tree_lock;	/* protect nat entry tree */
	struct list_head nat_entries;	/* cached nat entry list (clean) */
	spinlock_t nat_list_lock;	/* protect clean nat entry list */
	unsigned int nat_cnt[MAX_NAT_STATE]; /* the # of cached nat entries */
	unsigned int nat_blocks;	/* # of nat blocks */

	/* free node ids management */
	struct radix_tree_root free_nid_root;/* root of the free_nid cache */
	struct list_head free_nid_list;		/* list for free nids excluding preallocated nids */
	unsigned int nid_cnt[MAX_NID_STATE];	/* the number of free node id */
	spinlock_t nid_list_lock;	/* protect nid lists ops */
	struct mutex build_lock;	/* lock for build free nids */
	unsigned char **free_nid_bitmap;
	unsigned char *nat_block_bitmap;
	unsigned short *free_nid_count;	/* free nid count of NAT block */

	/* for checkpoint */
	char *nat_bitmap;		/* NAT bitmap pointer */

	unsigned int nat_bits_blocks;	/* # of nat bits blocks */
	unsigned char *nat_bits;	/* NAT bits blocks */
	unsigned char *full_nat_bits;	/* full NAT pages */
	unsigned char *empty_nat_bits;	/* empty NAT pages */
#ifdef CONFIG_F2FS_CHECK_FS
	char *nat_bitmap_mir;		/* NAT bitmap mirror */
#endif
	int bitmap_size;		/* bitmap size */
};
 (5) SSA

        SSA(Segment Summary Area)区域主要保存了journal(SIT/NAT临时的修改信息)以及summary(记录逻辑地址和物理地址关系的结构),这个区域主要用于反向索引, 记录了block所属的node信息

/* 4KB-sized summary block structure */
struct f2fs_summary_block {
	struct f2fs_summary entries[ENTRIES_IN_SUM];
	struct f2fs_journal journal;
	struct summary_footer footer;
} __packed;
 (6) Main Area

        在Main Area中的一个Segment,要么存储的是Node数据,要么存储的是data数据,不能既存node又存data

【参考博客】

[1] [论文阅读] F2FS: A New Filesystem for Flash Storage | Caturra's Blog 

[2]  f2fs文件系统(一)总体介绍 - 知乎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1608347.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【DL水记】循环神经网络RNN的前世今生,Transformer的崛起,Mamba模型

文章目录 RNN网络简介传统RNN网络结构RNN的分类 长-短期记忆网络 (LSTM)GRU网络横空出世的Transformer网络Self-AttentionVisionTransformer Mamba模型Reference: RNN网络简介 “当人类接触新事物时,他们不会从头开始思考。就像你在阅读这篇文章时,你会根…

最新版的GPT-4.5-Turbo有多强

OpenAI再次用实力证明了,GPT依然是AI世界最强的玩家!在最新的AI基准测试中,OpenAI几天前刚刚发布的GPT-4-Turbo-2024-04-09版本,大幅超越了Claude3 Opus,重新夺回了全球第一的AI王座: 值得一提的是&#xf…

Assign Memory Resources to Containers and Pods

minikube addons enable metrics-server minikube addons enable metrics-server 是一个命令,用于在 Minikube 环境中启用 metrics-server 插件。 Minikube 是一个工具,可以在本地轻松创建和管理单节点 Kubernetes 集群,适合开发和测试。Mini…

二叉树进阶题目

1还原二叉树 #include<bits/stdc.h> using namespace std; const int N1e310; char pre[N],mid[N]; int w[N]; int ans; struct node{int l,r; }t[N]; int build(int prel,int prer,int midl,int midr){int ascpre[prel];int posw[asc];if(midl<pos)t[asc].lbuild(pre…

从 Elastic 的 Go APM 代理迁移到 OpenTelemetry Go SDK

作者&#xff1a;来自 Elastic Damien Mathieu 正如我们之前所分享的&#xff0c;Elastic 致力于帮助 OpenTelemetry&#xff08;OTel&#xff09;取得成功&#xff0c;这意味着在某些情况下构建语言 SDK 的分发版本。 Elastic 在观察性和安全数据收集方面战略性地选择了 OTel…

深入挖掘C语言 ----动态内存分配

开篇备忘录: "自给自足的光, 永远都不会暗" 目录 1. malloc和free1.1 malloc1.2 free 2. calloc和realloc2.1 calloc2.2 realloc 3. 总结C/C中程序内存区域划分 正文开始 1. malloc和free 1.1 malloc C语言提供了一个动态开辟内存的函数; void* malloc (size_t s…

Python中的迭代器:深入理解与实用指南

文章目录 1. 迭代器的基本概念2. Python中的迭代器实例3. 自定义迭代器3.1 例子3.2 详细过程 4. 迭代器的高级应用5. 常见问题与解答 迭代器是Python中非常核心的概念之一&#xff0c;在面试中也会被问到。下面我会详细介绍什么是迭代器&#xff0c;使用方法&#xff0c;以及使…

爬虫 | 基于 requests 实现加密 POST 请求发送与身份验证

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目旨在实现一个简单的 Python 脚本&#xff0c;用于向指定的 URL 发送 POST 请求&#xff0c;并通过特定的加密算法生成请求头中的签名信息。这个脚本的背后是与某个特定的网络服务交互&#xff0c;发送特定格式的 JSON 数据…

vi编辑器的用法linux中的vim编辑器大全

vim的介绍 vi 和 vim 命令是linux中强⼤的⽂本编辑器, 由于Linux系统⼀切皆⽂件&#xff0c;⽽配置⼀个服务就是在修改其配置⽂件的参数。 vim 编辑器是运维⼯程师必须掌握的⼀个⼯具, 没有它很多⼯作都⽆法完成。 其中有vi和vim两种 vi和vim的区别 Vim是Vi的升级版本&#…

source map 开发优化工具

什么是 Source map 简单来说 Source map 就是一个存储信息的文件&#xff0c;里面储存着位置信息。 Source map 英文释义&#xff1a;源程序映射。 位置信息&#xff1a;转换后的代码 对应的 转换前的代码 位置映射关系。 有了 Source map&#xff0c;就算线上运行的是转换…

el-menu 该有的页面显示不出来第一个应该想到的问题首先就算检查是否多写了一个 , 导致显示不出来原有的页面

问题描述 el-menu 该有的页面显示不出来第一个应该想到的问题首先就算检查是否多写了一个 , 导致显示不出来原有的页面 如图所示多写了一个&#xff0c;就会导致该有的页面显示不出来。

nVisual在线网络规划设计软件

●01● nVisual在线网络规划设计软件 在信息化快速发展的今天&#xff0c;网络基础设施的建设与优化变得尤为关键。为了满足现代通信行业对高效、精准的网络规划需求&#xff0c;nVisual在线网络规划设计软件应运而生&#xff0c;它通过集成先进的GIS技术和网络规划工具&#…

OpenHarmony鸿蒙南向开发案例:【智能门铃】

样例简介 智能门铃通过监控来访者信息&#xff0c;告诉主人门外是否有人按铃、有陌生人靠近或者无人状态。主人可以在数字管家中远程接收消息&#xff0c;并根据需要进行远程取消报警和一键开锁。同时&#xff0c;也可以通过室内屏幕获取门外状态。室内屏幕显示界面使用DevEco…

人工智能,如何走好下一步

以下文章来源&#xff1a;金台资讯 2023年&#xff0c;生成式人工智能在全球范围爆火&#xff0c;引发了人工智能领域新一轮的科技竞赛。眼下&#xff0c;人工智能不仅能辅助科学研究与艺术创作&#xff0c;还能实现自动驾驶、打造“无人农场”和“黑灯工厂”&#xff0c;成为解…

数据很重要,ASM磁盘组损坏,使用AMDU来抢救

欢迎关注“数据库运维之道”公众号&#xff0c;一起学习数据库技术! 本期将为大家分享“数据很重要&#xff0c;ASM磁盘组损坏&#xff0c;使用AMDU来抢救”的处置案例。这个案例对个人来说比较经典&#xff0c;下面我将把自己的处理思路进行整理与总结。 环境信息&#xff1…

户用光伏业务解决方案

一、光伏户用痛点 1、推广难 没有成熟的推广与拓客能力&#xff0c;造成时间和金钱大量浪费。 2、管理难 有内部和外部几十或者上百推广人员&#xff0c;管理纷杂&#xff0c;效率低下。 3、无制度 缺少有效的人员管理制度与系统&#xff0c;分辨不出优秀人才&#xff0c…

Let‘s Forkin‘ Dance!Tanssi 激励测试网活动全面启动

作者&#xff1a;Tanssi 编译&#xff1a;OneBlock 作为 Tanssi 社区和生态系统发展的重要推手&#xff0c;Tanssi 基金会推出了 Incentivized TestNet 活动 —— Let’s Forkin’ Dance。该活动旨在激励顶尖参与者&#xff0c;推动社区增长和网络活动&#xff0c;为今年晚些时…

c语言-快速排序

文章目录 代码工程运行结果 这个是升序排列&#xff0c;如果想降序排列,将下面两行的符号反过来即可; arr[right] < arr[key] arr[left] > arr[key]代码工程 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h>void swap(int *v1, int *v2) {int temp *v1;*v1 …

【VTKExamples::Meshes】第 十四期 ExtractEdges

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例ExtractEdges,并解析接口vtkExtractEdges,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~…

如何高效建立企业绩效评估体系?这家世界500强企业用BI工具这么做

在目前经济下行&#xff0c;竞争激烈&#xff0c;向精细化管理要效益的社会背景下&#xff0c;如何对资金结算部门做好绩效管理&#xff0c;以保障组织的正常运作&#xff0c;是各大企业面对的重要痛点。 本文将基于某世界500强公司的财务共享资金结算部门的绩效管理办法&…