F2FS源码分析-1.2 [F2FS 元数据布局部分] Superblock结构

F2FS源码分析系列文章
主目录
一、文件系统布局以及元数据结构
  1. 总体结构
  2. Superblock区域
  3. Checkpoint区域
  4. Segment Infomation Table区域(SIT)
  5. Node Address Table区域(NAT)
  6. Segment Summary Area区域(SSA)
二、文件数据的存储以及读写
三、文件与目录的创建以及删除(未完成)
四、垃圾回收机制
五、数据恢复机制
六、重要数据结构或者函数的分析

Superblock区域

Superblock保存了F2FS的核心元数据的结构,包括磁盘大小,元区域的各个部分的起始地址等。

Superblock在元数据区域的物理结构

在这里插入图片描述

Superblock区域是由两个struct f2fs_super_block结构组成,互为备份。

Superblock物理存放区域结构

struct f2fs_super_block是F2FS对Superblock的具体数据结构实现,它保存在磁盘的最开始的位置,F2FS进行挂载时从磁盘的前端直接读取出来,然后转换为struct f2fs_super_block结构。它的定义如下:


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 一般是3,因为1<<3 = 8 */
	__le32 log_blocksize;		/* log2 block size in bytes 一般是12,因为 1<<12 = 4096 */
	__le32 log_blocks_per_seg;	/* log2 # of blocks per segment 一般是8,因为 1<<8 = 512 */
	__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 */
	__u8 reserved[314];		/* valid reserved region */
} __packed;

对于一个50MB大小的磁盘,格式化后的f2fs_super_block 的信息如下:

magic = -218816496
major_ver = 1
minor_ver = 10
log_sectorsize = 9
log_sectors_per_block = 3
log_blocksize = 12
log_blocks_per_seg = 9
segs_per_sec = 1
secs_per_zone = 1
checksum_offset = 0
block_count = 12800 # 50MB / 4KB = 12800
section_count = 17     # section只在main area应用,因此和main area一样
segment_count = 24
segment_count_ckpt = 2 # checkpoint用了2个segment
segment_count_sit = 2  # SIT也用了2个segment
segment_count_nat = 2  # NAT也用了2个segment
segment_count_ssa = 1  # SSA用了1个segment
segment_count_main = 17 # main area一共有17个可用的segment
segment0_blkaddr = 512
cp_blkaddr = 512       # checkpoint的地址
sit_blkaddr = 1536     # sit的地址
nat_blkaddr = 2560	   # nat的地址
ssa_blkaddr = 3584     # ssa的地址
main_blkaddr = 4096    # main area的地址
root_ino = 3
node_ino = 1
meta_ino = 2
extension_count = 27
cp_payload = 0
feature = 0
encryption_level = 

Superblock内存管理结构

如上一节所述,f2fs_super_block在内存中的对应的结构是struct f2fs_sb_info,它除了包含了struct f2fs_super_block的信息以外,还包含了一些额外的功能,如锁、SIT、NAT对应的内存管理结构等,简单如下所述:

struct f2fs_sb_info {
	struct super_block *sb;			/* pointer to VFS super block */
	struct f2fs_super_block *raw_super;	/* raw super block pointer */
	struct rw_semaphore sb_lock;		/* lock for raw super block */

	/* for node-related operations */
	struct f2fs_nm_info *nm_info;		/* node manager */
	struct inode *node_inode;		/* cache node blocks */

	/* for segment-related operations */
	struct f2fs_sm_info *sm_info;		/* segment manager */

	/* for checkpoint */
	struct f2fs_checkpoint *ckpt;		/* raw checkpoint pointer */

	/* for orphan inode, use 0'th array */
	unsigned int max_orphans;		/* max orphan inodes */

	struct f2fs_mount_info mount_opt;	/* mount options */

	/* for cleaning operations */
	struct mutex gc_mutex;			/* mutex for GC */
	struct f2fs_gc_kthread	*gc_thread;	/* GC thread */
	unsigned int cur_victim_sec;		/* current victim section num */
	unsigned int gc_mode;			/* current GC state */
};

它的初始化在init_sb_info函数完成:

static void init_sb_info(struct f2fs_sb_info *sbi)
{
    // raw_supaer就是F2FS在从磁盘读取出来的信息,再初始化对应的内存结构struct f2fs_sb_info
	struct f2fs_super_block *raw_super = sbi->raw_super; 
	int i, j;

	sbi->log_sectors_per_block =
		le32_to_cpu(raw_super->log_sectors_per_block);
	sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize);
	sbi->blocksize = 1 << sbi->log_blocksize;
	sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
	sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg;
	sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
	sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
	sbi->total_sections = le32_to_cpu(raw_super->section_count);
	sbi->total_node_count =
		(le32_to_cpu(raw_super->segment_count_nat) / 2)
			* sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK;
	sbi->root_ino_num = le32_to_cpu(raw_super->root_ino);
	sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
	sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
	sbi->cur_victim_sec = NULL_SECNO;
	sbi->max_victim_search = DEF_MAX_VICTIM_SEARCH;

	sbi->dir_level = DEF_DIR_LEVEL;
	sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
	sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL;
	clear_sbi_flag(sbi, SBI_NEED_FSCK);

	for (i = 0; i < NR_COUNT_TYPE; i++)
		atomic_set(&sbi->nr_pages[i], 0);

	for (i = 0; i < META; i++)
		atomic_set(&sbi->wb_sync_req[i], 0);

	INIT_LIST_HEAD(&sbi->s_list);
	mutex_init(&sbi->umount_mutex);
	for (i = 0; i < NR_PAGE_TYPE - 1; i++)
		for (j = HOT; j < NR_TEMP_TYPE; j++)
			mutex_init(&sbi->wio_mutex[i][j]);
	init_rwsem(&sbi->io_order_lock);
	spin_lock_init(&sbi->cp_lock);

	sbi->dirty_device = 0;
	spin_lock_init(&sbi->dev_lock);

	init_rwsem(&sbi->sb_lock);
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
F2FS是专为闪存设备设计的文件系统,具有出色的性能和可靠性。下面对F2FS的代码进行简要的分析: 1. 超级块(superblock):超级块是F2FS存储文件系统元数据结构体,包含文件系统的基本信息,如版本号、块大小、节点大小、块位图、节点位图、inode表、日志区域等。 2. inode(index node):inode是F2FS存储文件和目录元数据结构体,每个文件和目录都会对应一个inode节点。inode包含文件类型、权限、大小、数据块指针等信息。 3. 数据块(data block):数据块是F2FS存储文件数据的结构体,每个数据块大小为4KB,可以存储文件数据、索引节点数据、日志数据等。 4. 日志(journal):F2FS的写操作都会先写入日志,然后再同步到数据块。日志大小为1MB,用于记录文件系统的变化情况,以便在系统重启后恢复数据的一致性。 5. 垃圾回收(garbage collection):由于闪存设备的写入操作是有限制的,因此需要定期进行垃圾回收以释放已经不再使用的空间。F2FS的垃圾回收机制采用了段式管理的思路,即将整个闪存设备分成多个段,每个段独立进行垃圾回收。 6. 压缩(compression):F2FS的压缩机制采用了zlib压缩算法,可以将文件数据进行压缩以节省存储空间和提高读写性能。 7. 加密(encryption):F2FS的加密机制采用了AES加密算法,可以对文件和数据进行加密和解密以保护用户数据的安全性。 总之,F2FS是一种高效、可靠的文件系统,它的代码实现非常精细和模块化,各个模块之间相互独立,并且有很好的扩展性和灵活性。F2FS的设计思路和数据结构也非常有特色,可以更好地充分利用闪存设备的性能和寿命。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值