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

一、基本介绍

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_FSchar *nat_bitmap_mir;		/* NAT bitmap mirror */
#endifint 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.rhkb.cn/news/311683.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Composer是什么?

Composer是PHP的一个依赖管理工具,它允许开发者声明项目所依赖的代码库,并在项目中自动安装这些依赖。它使用composer.json文件来定义项目的依赖关系,并使用composer.lock文件来锁定依赖的版本,以确保项目的稳定性和可重复性。 Co…

【Git教程】(十)版本库之间的依赖 —— 项目与子模块之间的依赖、与子树之间的依赖 ~

Git教程 版本库之间的依赖 1️⃣ 与子模块之间的依赖2️⃣ 与子树之间的依赖🌾 总结 在 Git 中,版本库是发行单位,代表的是一个版本,而分支或标签则只能被创建在版本库这个整体中。如果一个项目中包含了若干个子项目,…

雪亮工程视频联网综合管理/视频智能分析系统建设方案(一)

一、行业背景 雪亮工程主要是针对农村地区治安防控的监控项目,在乡村的主干道、路口、人群聚集地部署高清摄像头,通过三级综治中心和指挥平台,将视频图像信息系统纵向下延至县、乡、村,同时利用系统拓展在安防、社会治理、智慧交…

基于U-Net的图像分割算法介绍

U-Net是一种用于图像分割的深度学习架构,其设计初衷是用于生物医学图像分割,尤其是医学影像中的细胞分割任务。U-Net结构独特,具有编码器-解码器结构,能够有效地捕捉图像中的局部和全局信息,并在像素级别上进行精确的分割。 相关论文: U-Net: Convolutional Networks for…

记录一下我hive连不上DataGrip的问题

用户名和密码都没问题,但报如下这个错误 原因:是因为我在linux上没启hiveserver2服务 解决: [atguiguhadoop102 hadoop]$ hiveserver2 which: no hbase in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/opt/module/jdk1.8…

Spring Boot 统一功能处理(二)

本篇主要介绍Spring Boot统一功能处理中的统一数据返回格式。 目录 一、定义统一的返回类 二、配置统一数据格式 三、测试配置效果 四、统一格式返回的优点 五、源码角度解析String问题 一、定义统一的返回类 在我们的接口在处理请求时,返回的结果可以说是参…

Linux-进程控制

目录 1.进程创建 2. 进程终止 2.1 进程退出的场景 2.2 进程常见退出方法 2.3 return返回终止 2.4 exit()和_exit() 3. 进程等待 3.1 进程等待的原因 3.2 wait​编辑 3.3 waitpid 3.4 status 4. 进程替换 4.1 替换原理 4.2 exec函数系列 1.进程创建 在linux中for…

【学习笔记】rt-thread

任务 创建好任务,不管是动态还是静态创建,任务的状态是init ,通过start方法来启动任务;线程大小 设置小了,无法正常工作?显示占空间100% 启动过程 TODO 这是编译器特性? 因为RT-Thread使用编…

代码随想录-算法训练营day14【二叉树01:理论基础、递归遍历、迭代遍历、统一迭代】

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客 第六章 二叉树part01今日内容: ● 理论基础 ● 递归遍历 ● 迭代遍历 ● 统一迭代详细布置 理论基础 需要了解 二叉树的种类,存储方式,遍历方式 以及二叉树的定义 文章讲解&#x…

ARM_day7:实现三个按键中断

程序代码: mykey.h: #ifndef __MYKEY_H__ #define __MYKEY_H__ #include "stm32mp1xx_rcc.h" #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_exti.h" #include "stm32mp1xx_gic.h" extern void printf(const char …

03_信号和槽

信号和槽 系统的信号和槽自定义信号和槽Lambda表达式 系统的信号和槽 下面我们完成一个小功能,上面我们已经学习了按钮的创建,但是还没有体现出按钮的功能,按钮最大的功能也就是点击后触发一些事情,比如我们点击按钮,…

FAGLL03H 新增自定义字段

1、SGLPOS_N_GL_CT、SGLPOS_N_CT两个结构新增自定义字段 2、执行t-code:HDBVIEWS 3、实施增强 FAGL_LIB 4、使用select data方法 5、代码示例: method IF_FAGL_LIB~SELECT_DATA.FIELD-SYMBOLS: <fs> TYPE any.FIELD-SYMBOLS <ls_data> TYPE any.F…

ctf.show_web13

上传一句话木马 1.php文件&#xff0c;显示 再改后缀为.jpg&#xff0c;显示错误文件大小 用dirsearch扫一下 备份文件.bak 下载文件源码 <?php header("content-type:text/html;charsetutf-8");$filename $_FILES[file][name];$temp_name $_FILES[file][tm…

腾讯清华联合提出图像到视频生成方法-Follow-Your-Click:点击图像并加上简单提示词就可让图像动起来!

Follow-Your-Click只需单击一次和简短的提示就可以让图像的某一部分动起来&#xff0c;还支持不同的动作表达&#xff0c;比如微笑&#xff0c;悲伤&#xff0c;跳舞…… 相关链接 论文链接&#xff1a;https://arxiv.org/abs/2403.08268 项目链接&#xff1a;https://github…

html 引入vue Element ui 的方式

第一种&#xff1a;使用CDN的方式引入 <!--引入 element-ui 的样式&#xff0c;--> <link rel"stylesheet" href"https://unpkg.com/element-ui/lib/theme-chalk/index.css"> <!-- 必须先引入vue&#xff0c; 后使用element-ui --> <…

基于Docker构建CI/CD工具链(六)使用Apifox进行自动化测试

添加测试接口 在Spring Boot Demo项目里实现一个简单的用户管理系统的后端功能。具体需求如下&#xff1a; 实现了一个RESTful API&#xff0c;提供了以下两个接口 &#xff1a; POST请求 /users&#xff1a;用于创建新的用户。GET请求 /users&#xff1a;用于获取所有用户的列…

凡泰极客亮相2024 亚马逊云科技出海全球化论坛,为企业数字化出海赋能

随着「不出海&#xff0c;即出局」登上热搜榜单&#xff0c;企业出海已成燎原之势&#xff0c;3月29日&#xff0c;2024 亚马逊云科技出海全球化论坛在深圳成功举办&#xff0c;凡泰极客创始人梁启鸿受邀出席&#xff0c;并以 「App 2.0&#xff1a;以SuperApp构建智能数字生态…

HADOOP大数据处理技术8-JavaSe

投入地跳舞 就像没有人在一旁看着你一样 2024/4/8 5&#xff09;方法重载&#xff1a;在方法中 方法名称相同 但参数列表不同 方法名称相同 但是参数类型或个数不一样 好处&#xff1a;好记 6&#xff09;super &#xff08;只在具有继承关系的子类中使用&#xff09; 作用&a…

JAVA基础07-封装,类加载原理以及分析(内有练习代码)

目录 封装的理解 概念 目的 权限修饰符 访问权限从大到小 如何快速定义一个标准的Java类 1.普通方法 2.快捷键 练习 static 定义 静态与非静态区分 使用静态与非静态的场合 成员变量和局部变量 成员变量 局部变量 例子讲解&#xff1a;两数交换 解决方法 变…

研发岗-统信UOS系统配置npm git等前端常用配置

第一步 获取root权限 配置环境等都需要用到root权限&#xff0c;所以我们先获取到root权限&#xff0c;方便下面的操作 下载软件 在UOS应用商店下载的所需应用 版本都比较低 安装node 官网下载了【arm64】的包&#xff0c;解压到指定文件夹&#xff0c;设置链接&#xff0…