Ext4文件系统介绍 - 理论篇

news2024/12/25 4:10:28
Overview

ext4文件系统分割成多个block groups,为了解决碎片化问题,block allocator尽量将一个文件的block放在一个group中。block groups的size通过sb.s_blocks_per_group指定,同样也可以通过8*block_size_in_bytes计算得到。block默认大小是4KB,每个group包含32768个blocks,一个block group所有的block data大小是8*4K*4K=128M。

ext4在磁盘上是little-endian order。然后 jbd2(the journal)是big-endian order.

Layout

如上图,磁盘分割成多个block Group,每个Block Group都有相似的结构(之所以有不同,是因为收到sparse_super/flex_bg等feature影响)。每个block group引用ext4 spec如下:

super block:记录文件系统的整体信息。dumpe2fs命令最开始的输出部分就是superblock的信息

Group Descriptors: 块组描述符,每个block group对一个一个描述信息,由ext4_group_desc数据结构表示,其中描述块block bitmap的block号,inode bitmap的block号,空闲的block数目,空闲的inode数目等信息。dumpe2fs打印如下:

Data Block Bitmap: 数据块位图,记录数据块(data blocks)的使用情况。

Inode bitmap: inode位图,记录inode的使用情况。

Inode Table:inode表,存放inode数据结构的表格。磁盘数据的每个inode通过ext4_inode数据结构表示。

Data Blocks:存放文件数据的部分。

Flexible Block Groups

ext4引入了flexible block groups新特性,把相邻的几个block group组成一组(logic block group),称之为flex_bg。如上图,flex_bg中block group会把bitmaps(data block bitmap和inode bitmap)和inode table都放在了第一个group中,除了第一个group,其他group可以可以只包含data block(也有一些block存放了superblock和group desc的冗余数据)。这样将metadata紧凑存放加速了loading读取速度,同时有利于大文件的连续存放,提升访问性能。

Sparse_Super特性

由于文件系统metadata对于安全性非常重要,比如一个硬盘只保留一份superblock信息,如果恰好存放superblock的block损坏,那么将无法访问文件。所以如前文ext4 layout我们知道,每个block group都冗余存放了superblock和group desc,其实大可不必这么冗余,启用sparse_super特性就可以0,1以及3,5,7的整数次方(power of 3, 5 , 7)的block group存放冗余。

Bigalloc特性

block默认的大小是4K,如果一个文件系统大文件很多,那么以多个块(cluster)为单元管理磁盘可以减少碎片化,也可以减少metadata的空间占用,所以ext4引入bigalloc。格式化此片可以设置cluster size,data block bitmap的一位将表示一个cluster状态,当然申请数据块也是以一个cluster为单位。cluster size存储在sb.s_log_cluster_size

Block and Inode Allocation Policy

数据块分配分配核心要解决碎片化(fragment)问题。ext4如下方法避免:

  • multi-block allocator
  • delayed allocation
  • keep a file's data blocks in the same block group as its inode
  •  all the inodes in a directory are placed in the same block group
  • e4defrag碎片整理工具
Inline Data特性

主要是为了处理tiny file,比如一个文件小于60字节,完全可以嵌入文件的inode里面存储。

Meta Block Groups(META_BG)特性

磁盘数据结构 

dumpe2fs之所以能打印磁盘信息,就是因为磁盘上的数据按特定协议或者格式存储,跟ELF是类似的,这种二进制文件都必然有一定的格式,而ext4也定义几种数据结构分别对应这种格式或者协议。

ext4_super_block : 描述磁盘上super block格式的数据结构。

ext4_group_desc : 描述磁盘上group descriptor格式的数据结构。

ext4_inode:描述述磁盘上inode格式的数据结构。block group中的ext4_inode以数组的形式存放在inode table中,即inode table数组中每一项都是ext4_inode。

ext4_super_block数据结构

具体看参考文章ext4 Disk Layout,截取部分如下:

ext4_group_desc 数据结构

具体看参考文章ext4 Disk Layout,截取部分如下:

ext4_inode数据结构

内存数据结构 

前面介绍了磁盘数据结构,linux操作按照磁盘数据结构解析了磁盘数据,在内存中同样需要结构体存储这些信息。对应关系如下:

磁盘数据结构内存数据结构
ext4_super_blockext4_sb_info(总是缓存在RAMneicun中)
ext4_group_descext4_group_info(总是缓存在RAMneicun中)
ext4_inodeext4_inode_info(动态缓存,如文件删除会从高速缓存中动态删除)
data block bitmap缓冲区中的位数组
inode bitmap缓冲区中的位数组
block(数据块)VFS缓冲区

ext4_sb_info

定义在fs/ext4/ext4.h中,关联了VFS的super_block和ext4_super_block,同时保存了文件系统的通用信息,比如:

  • 磁盘超级块中大部分字段
  • buffer_head * s_sbh指针:指向包含磁盘超级块所在的缓冲区的缓冲区首部。
  • ext4_super_block *s_es:指向磁盘超级块缓冲区
  • super_block *s_sb:指向vfs super block。
  • 组描述符的个数s_desc_per_block
  • s_group_desc指针,指向缓冲区首部。

代码截取部分信息如下(详细字段可以查看fs/ext4/ext4.h内核代码)中ext4_sb_info结构体定义

/*
 * fourth extended-fs super-block data in memory
 */
struct ext4_sb_info {
	unsigned long s_desc_size;	/* Size of a group descriptor in bytes */
	unsigned long s_inodes_per_block;/* Number of inodes per block */
	unsigned long s_blocks_per_group;/* Number of blocks in a group */
	unsigned long s_clusters_per_group; /* Number of clusters in a group */
	unsigned long s_inodes_per_group;/* Number of inodes in a group */
	unsigned long s_itb_per_group;	/* Number of inode table blocks per group */
	unsigned long s_gdb_count;	/* Number of group descriptor blocks */
	unsigned long s_desc_per_block;	/* Number of group descriptors per block */
	ext4_group_t s_groups_count;	/* Number of groups in the fs */
	ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
	unsigned long s_overhead;  /* # of fs overhead clusters */
	unsigned int s_cluster_ratio;	/* Number of blocks per cluster */
	unsigned int s_cluster_bits;	/* log2 of s_cluster_ratio */
	loff_t s_bitmap_maxbytes;	/* max bytes for bitmap files */
	struct buffer_head * s_sbh;	/* Buffer containing the super block */
	struct ext4_super_block *s_es;	/* Pointer to the super block in the buffer */
	struct buffer_head * __rcu *s_group_desc;
    ...
	struct super_block *s_sb;
    ...
};

ext4_sb_info和ext4_super_block中的很多字段相似,但也有区别,ext4_sb_info中的很多字段是根据ext4_super_block的字段计算而得,虽然可以通过 ext4_super_block计算而得到,但是定义在ext4_sb_info定义可以省去重复计算的时间。

super_block的结构提s_fs_info字段指向了ext4_sb_info,EXT4_SB宏就是通过该字段获取ext4_sb_info。内核代码举例:

int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                  struct ext4_group_desc *gdp,
                  struct buffer_head *bh, int sz)
{
    __u32 hi;
    __u32 provided, calculated;
    struct ext4_sb_info *sbi = EXT4_SB(sb);
    ...
}

ext4_inode_info

VFS的inode结构体与磁盘数据结构ext4_inode结构体之间也需要一座桥梁,就是ext4_inode_info,截取内核重要的字段如下:


/*
 * fourth extended file system inode data in memory
 */
struct ext4_inode_info {
	__le32	i_data[15];	/* unconverted */
	__u32	i_dtime;
	ext4_fsblk_t	i_file_acl;

	/*
	 * i_block_group is the number of the block group which contains
	 * this file's inode.  Constant across the lifetime of the inode,
	 * it is used for making block allocation decisions - we try to
	 * place a file's data blocks near its inode block, and new inodes
	 * near to their parent directory's inode.
	 */
	ext4_group_t	i_block_group;
	ext4_lblk_t	i_dir_start_lookup;

	unsigned long	i_flags;


	/*
	 * i_disksize keeps track of what the inode size is ON DISK, not
	 * in memory.  During truncate, i_size is set to the new size by
	 * the VFS prior to calling ext4_truncate(), but the filesystem won't
	 * set i_disksize to 0 until the truncate is actually under way.
	 *
	 * The intent is that i_disksize always represents the blocks which
	 * are used by this file.  This allows recovery to restart truncate
	 * on orphans if we crash during truncate.  We actually write i_disksize
	 * into the on-disk inode when writing inodes out, instead of i_size.
	 *
	 * The only time when i_disksize and i_size may be different is when
	 * a truncate is in progress.  The only things which change i_disksize
	 * are ext4_get_block (growth) and ext4_truncate (shrinkth).
	 */
	loff_t	i_disksize;
    ...
	struct inode vfs_inode;
	struct jbd2_inode *jinode;
    ...

}

ext4_inode_info内嵌了inode,可以通过传递inode对象到EXT4_I宏来获得ext4_inode_info,内核代码: 

void ext4_discard_preallocations(struct inode *inode)
{
    struct ext4_inode_info *ei = EXT4_I(inode);
    ...
}

 但是,ext4_inode_info没有定义指向ext4_inode的字段,只是拷贝了ext4_inode的i_block,i_flags等字段;同时inode结构体也包含了与ext4_inode类似的字段,比如i_atime,i_mtime,i_ctime等,所以三者的关系是:ext4_inode_info内嵌了vfs的inode,这两者一起“瓜分”了ext4_inode的信息。

ext4_group_info

struct ext4_group_info {
	unsigned long   bb_state;
	struct rb_root  bb_free_root;
    //第一个空闲的block号
	ext4_grpblk_t	bb_first_free;	/* first free block */
    //空闲block总数
	ext4_grpblk_t	bb_free;	/* total free blocks */
    //碎片的数量
	ext4_grpblk_t	bb_fragments;	/* nr of freespace fragments */
    //最大空闲的order(cat /proc/fs/ext4/mb_groups可看到)
	ext4_grpblk_t	bb_largest_free_order;/* order of largest frag in BG */
	struct          list_head bb_prealloc_list;
#ifdef DOUBLE_CHECK
	void            *bb_bitmap;
#endif
	struct rw_semaphore alloc_sem;
	ext4_grpblk_t	bb_counters[];	/* Nr of free power-of-two-block
					 * regions, index is order.
					 * bb_counters[3] = 5 means
					 * 5 free 8-block regions. */
};

内核多块分配mballoc中ext4_group_info使用的很频繁,比如bb_largest_free_order的计算逻辑:


/*
 * Cache the order of the largest free extent we have available in this block
 * group.
 */
static void
mb_set_largest_free_order(struct super_block *sb, struct ext4_group_info *grp)
{
    int i;
    int bits;

    grp->bb_largest_free_order = -1; /* uninit */

    bits = sb->s_blocksize_bits + 1;
    for (i = bits; i >= 0; i--) {
        if (grp->bb_counters[i] > 0) {
            grp->bb_largest_free_order = i;                                                                                                                              
            break;
        }
    }
}

 mballoc为了解决block分配碎片化问题,使用memory buddy思想,将块按order组织成各种大小的,bb_largest_free_order就是还有剩余空间的最大order。

参考文章

Ext4 Disk Layout - Ext4

.ext4的新特性-bigalloc.pdf

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

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

相关文章

【Zookeeper】终端操作常用命令

文章目录 服务端常用命令客户端常用命令 zookeeper版本3.7.1 Zookeeper是一个开源的分布式协调服务。 Zookeeper是Apache软件基金会的一个项目,它提供了分布式应用程序协调的通用服务,如分布式同步、命名服务、集群维护等,以简化分布式应用协…

【计算机组成与体系结构Ⅰ】实验6 熟悉Vivado及MINISYS-1实验系统

一、实验目的 1:熟悉Vivado的开发环境及开发流程,掌握Vivado中Verilog HDL文本输入设计方法,包括仿真、综合、实现与下载。熟悉Minisys开发板的功能和使用方法。 2:学会可配置IP核的设计与封装方法,深入理解与门逻辑…

Linux驱动入门(五)——简单的字符设备驱动程序

文章目录 前言字符设备驱动程序框架字符设备和块设备主设备号和次设备号申请和释放设备号 初识cdev结构cdev结构体file_operations结构体cdev和file_operation结构体的关系inode结构体 字符设备驱动的组成字符设备加载和卸载函数file_operations结构体和其他成员函数驱动程序与…

Tomcat面试题

江湖无名 安心练剑 关注微信公众号:程序三两行 获取最新版面试资料、java学习路线 1、Tomcat 的缺省端口是多少,怎么修改? 1)找到 Tomcat 目录下的 conf 文件夹 2)进入 conf 文件夹里面找到 server.xml 文件 3&…

Elasticsearch】文档操作

目录 3.文档操作 3.1.新增文档 3.2.查询文档 3.3.删除文档 3.4.修改文档 3.4.1.全量修改 3.4.2.增量修改 3.5.总结 3.文档操作 3.1.新增文档 语法: POST /索引库名/_doc/文档id {"字段1": "值1","字段2": "值2"…

AUTOSAR CP标准的RTE和BSW各模块的设计及开发工作

AUTOSAR(Automotive Open System Architecture)是一种开放的汽车电子系统架构标准,旨在提供一种统一的软件架构,以实现汽车电子系统的模块化和可重用性。 AUTOSAR标准中的两个重要模块是RTE(Runtime Environment&…

YOLOV5/V7动态多Batch推理,GPU预处理、后处理C++源码

YOLO系列多batch处理后处理代码,C代码,结构清晰,自己后期会继续发布真实场景项目;关注公众号欢迎下载。 一、获取链接 所有源码获取方法,链接:https://www.cnblogs.com/shenduxuexizahuopu/p/17538815.htm…

【LeetCode】HOT 100(22)

题单介绍: 精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

【Python】Python实现串口通信(Python+Stm32)

🎉欢迎来到Python专栏~Python实现串口通信 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒🍹 ✨博客主页:小夏与酒的博客 🎈该系列文章专栏:Python学习专栏 文章作者技术和水平有限,如果文中出现错误,希望…

在linux中安装HAProxy

使用xfrp将压缩包上传到linux的opt目录下 1.解压HAProxy安装包 tar -zxvf haproxy-1.8.12.tar.gz 2. 查看点钱的内核及版本: uname -r 3. 根据内核版本选择编译参数 cd haproxy-1.8.12 cat README 4. 编译安装HAProxy make TARGETlinux2628 ARCHx86_64 PREFIX/usr/local…

测试,写用例!真有必要?

今天的文章是想跟所有小伙伴讨论软件测试工作中必不可少的一项工作:写测试用例,但目前还有很多公司并不重视写测试用例,觉得写测试用例是浪费时间,还不如拿这些时间来执行测试,那我们真的有必要写测试用例么&#xff1…

算法与数据结构-递归

文章目录 什么是递归递归需要满足的三个条件递归可能存在的问题堆栈溢出重复计算 总结 什么是递归 递归是一种直接或者间接调用自身函数或者方法的算法(或者编程技巧),应用非常广泛。我们举个例子来说明什么是递归: 推荐注册返佣金…

join的作用【A中调用B.join表示 B先完成后A再继续】【b.join 表示b先完成】

★ 2.5 等待一个线程-join() ★★★A中调用B.join表示 B先完成后A再继续 有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作。例如,张三只有等李四转账成功,才决定是否存钱,这时我们需要一个方法明确…

maya粒子碰撞(碰撞几何体索引)

全部下滑了 nParticleShape1.rgbPP<<1,0,0>>; 碰撞层 int $yase nParticleShape1.collisionGeometryIndex; if ($yase 0 ) nParticleShape1.rgbPP<<0,1,0>>; int $yase nParticleShape1.collisionGeometryIndex; if ($yase 0 ) nParticleShape1.…

【Linux】网络基础和网络套接字的概念

文章目录 前言一、网络的发展及其网络中的概念总结 一、网络的发展及其网络中的概念 刚开始的计算机大多处于独立模式&#xff0c;也就是说计算机之间相互独立。等到网络出现的时候就出现了网络互联&#xff0c;多台计算机连接在一起完成数据共享。随着发展计算机越多越多就出…

选购云主机

目录 一、购买云主机 二、SSH连接云主机 三、在云主机上面开放端口 一、购买云主机 云服务商有很多&#xff0c;但是我推荐大家使用腾讯云。之前我讲过阿里云超卖的事情&#xff0c;云主机IO性能非常差劲&#xff0c;我们要在云主机上面安装MySQL、MongoDB这样的数据库&…

TortoiseGit 入门指南01:环境搭建和软件设置

在我的博文Keil MDK环境下Git入门指南的最后&#xff0c;我这样写道&#xff1a; 目前使用 TortoiseGit 管理工程&#xff0c;用 Gitee 作为远程仓库。 命令行 Git 已经不再使用。 当时我并没有介绍软件 TortoiseGit 的使用方法&#xff0c;这个系列补上。如果你还没有看过《Ke…

Linux开发工具【gcc/g++】

Linux开发工具之【gcc/g】 上文我们已经学习了vim编辑器的相关操作和使用&#xff0c;已经可以在Linux下编写代码了&#xff0c;有了代码就需要编译运行&#xff0c;此时就需要用到Linux中的编译工具gcc/g了&#xff0c;其中gcc是C语言的编译器&#xff0c;g是C的编译器&#…

RabbitMQ系列(29)--RabbitMQ搭建Shovel

前言&#xff1a; Federation具备的数据转发功能类似&#xff0c;Shovel能够可靠、持续地从一个Broker中的队列(作为源端&#xff0c;即source)拉取数据并转发至另一个Broker中的交换器(作为目的端&#xff0c;即destination)。作为源端的队列和作为目的端的交换器可以同时位于…

SGM58031与单片机驱动实现

SGM58031与单片机驱动实现 文章目录 SGM58031与单片机驱动实现CUBEIDE设置I2C通讯封装SGM58031通讯实现 CUBEIDE设置 使用硬件I2C与sgm芯片通讯&#xff0c;上面即配置硬件I2C,其他参数默认即可。 I2C通讯封装 封装实现 /*** brief Manages error callback by re-initializ…