1.前言
初始流程主要包含f2fs文件系统初始化,以及f2fs文件系统mount
2. init_f2fs_fs
- init_inodecache
创建f2fs_inode_cache slab描述符 - create_node_manager_caches
创建nat_entry,free_nid的slab描述符 - create_gc_caches
创建f2fs_gc_inodes的 slab描述符 - create_checkpoint_caches
创建f2fs_orphan_entry,f2fs_dirty_dir_entry的slab描述符 - register_filesystem
注册f2fs文件系统
3. f2fs_fill_super
f2fs_mount
|--mount_bdev
|--blkdev_get_by_path
|--sget
|--f2fs_fill_super
f2fs_fill_super主要包含如下几个步骤:
- 从磁盘读取raw super block;
- 初始化vfs的super block;
- 初始化f2fs的super block info, 通过sb与vfs的super block关联;
- 读取有效的cp block
- 创建f2fs内部模块,包括segment manager, node manager, gc manager
(1)构建segment manager
构建main area info, sit info, cp info, ssa info
为main area构建free segment信息
为main area构建current segment信息,包含6个current segment
为main area创建sit entries
(2)构建node manager
(3)构建gc manager - 为meta_inode, node, root分别创建inode,通过d_make_root创建根dentry
7.如果是非正常卸载!(sbi->ckpt->ckpt_flags & CP_UMOUNT_FLAG),则需要recover_fsync_data执行磁盘恢复
8.执行start_gc_thread
3.1 从磁盘读取raw super block
- kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL)
为f2fs_sb_info分配空间 - sb_set_blocksize(sb, F2FS_BLKSIZE)
block大小设置为4096 - sb_bread(sb, 0)
读取磁盘上的super_block - 初始化一些super block info变量
(1)active_logs
(2) 设置mount参数为EXT2_MOUNT_BG_GC
(3)parse_options:解析 mount 参数
(4) 初始化sb->s_op = &f2fs_sops - sanity_check_raw_super
检查super block的参数 - sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi))
获取一个inode给meta inode
(1)iget_locked(sb, ino)获取一个inode
(2) inode->i_mapping->a_ops = &f2fs_meta_aops
通过inode的针对不同的inode类型,给不同的inode->i_mapping->a_ops初始化。
主要分为:node, meta, regular, dir, slink, char
meta data则被初始化为f2fs_meta_aops
(3)mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO) - get_valid_checkpoint
获取cp - sanity_check_ckpt(raw_super, sbi->ckpt)
检测cp - init super block
sb_set_blocksize - init_orphan_info
INIT_LIST_HEAD(&sbi->orphan_inode_list);
sbi->n_orphans = 0
3.2 build_segment_manager(sbi)
- 初始化segment manager info
sm_info->seg0_blkaddr:cp区域的第0个block的地址
sm_info->main_blkaddr:main area的 block地址
sm_info->segment_count:始化segment count的数目, 它不包含sb所占用的segment
sm_info->reserved_segments:main区域中保留的segment的个数
sm_info->ovp_segments:main区域中over provision的segment的个数
sm_info->main_segments:main区域的segment的个数 - build_sit_info
最重要的是为每个segment创建描述符segment entry, seg_entry记录了一个segment的有效块数,有效块的bitmap等信息 ,为main area分配dirty segment entry bitmap空间,为main area的所有segment分配valid block bitmap - build_free_segmap
构建free_segmap_info, 最主要的是构建了free bit map - build_curseg
当前有效的segment创建summary block, 并通过cp区域存放的当前有效segment summary block初始化,由于镜像采用了compacted summaries,因此将nat journal存放到current hot data的summary block, 将sit journal存放到current cold data的summary block - build_sit_entries
始化内存中的sit entries,如果segment在sit jornal entry中没有对应的seg entry,则需要从磁盘的sit区域获取, 如果有则直接用以初始化内存中的sit entry, 此处也会 - init_free_segmap
根据main area的segment是否有valid block,初始化free segmap, 清零/置位free_segmap_info->free_segmap - build_dirty_segmap
基于free_segmap_info初始化dirty_seglist_info,因为free_segmap_info中bitmap中bit为1表示dirty
3.3 build_node_manager
初始化node manager info, 重点初始化了nat_bitmap, 它来源于cp
3.4 build_gc_manager
get_victim_by_default
3.5 recover_fsync_data
TODO
3.6 start_gc_thread
TODO