Ext2数据块分配
ext2文件的逻辑结构和物理结构的映射过程
标题:深入探讨ext2文件的逻辑结构和物理结构的映射过程在计算机科学领域,文件系统是操作系统中的重要组成部分,用于管理文件的存储和检索。
而ext2文件系统是Linux操作系统中常见的文件系统之一,其结构复杂、功能强大。
在本文中,我将深入探讨ext2文件系统的逻辑结构和物理结构的映射过程,以便更好地理解这一主题。
一、理解ext2文件系统1. ext2文件系统的基本概念在开始深入讨论ext2文件系统的逻辑结构和物理结构的映射之前,需要首先理解ext2文件系统的基本概念。
ext2是Linux操作系统中常见的文件系统类型,它采用了类Unix文件系统的基本概念,包括inode、超级块、块组描述符等重要概念。
2. ext2文件系统的特点ext2文件系统具有一些独特的特点,如支持大容量的文件系统、高效地组织和管理磁盘空间、高速的文件读写性能等。
这些特点使得ext2文件系统在Linux系统中得到了广泛的应用。
二、逻辑结构和物理结构的映射过程1. 磁盘空间的组织ext2文件系统的逻辑结构和物理结构的映射过程首先涉及到磁盘空间的组织。
磁盘空间被组织成多个块组,每个块组包含若干个数据块,用于存储文件数据;同时还包含若干个inode块,用于存储文件的元数据信息。
2. inode与文件的映射在ext2文件系统中,每个文件都对应一个唯一的inode,该inode记录了文件的元数据信息,如文件大小、权限、所有者等。
逻辑上,文件可以通过inode进行标识和管理,而物理上,inode则映射到具体的磁盘块中。
3. 数据块的映射文件的实际数据则存储在数据块中。
数据块的映射过程是ext2文件系统逻辑结构和物理结构的重要部分,它涉及到磁盘空间的分配和管理,以及文件数据与磁盘块的对应关系。
三、个人观点和总结通过对ext2文件系统的逻辑结构和物理结构的映射过程进行深入探讨,我对文件系统的工作原理有了更深入的理解。
在实际应用中,对文件系统的深入理解能够帮助我们更好地进行文件管理和存储空间的优化,提高系统的性能和稳定性。
Linux系统ext2与ext3文件系统的区别与转换
ext2和ext3是Linux比较旧的文件系统, 在Linux 7中支持的文件系统已经是 “xfs”,但是为了知识的衔接性,也为 了更深的认识文件系统之间的差别有必 要认识一下这两个文件系统。 这两个文件系统的格式是相同的,不 同的是在ext3文件系统中在硬盘的后面 留出一块磁盘空间来存放日志(journal) 记录。
全部消失。 如果你接手一个很重要的Linux系统, 而这个Linux系统的文件系统还是很老的 ext2,而为了提高性能还要保留原来的 数据就只能使用命令tune2fs命令(在线 转换文件系统ext2→ext3)了。
除了使用“-j”选项创建ext3文件系 统之外,可以直接使用mkfs.ext3 设备名
在开机时Linux系统都会检查每个文件 系统的Valid bit,值如为1则直接挂载该 文件系统,而如果为0值,则系统会扫描 这个文件系统(硬盘分区)查找损坏的 数据,如果这个硬盘分区很大,扫描时 间会很长。 1扫描
0不扫描 由于ext3文件系统有日志机制,开机 时系统会先检查日志中的信息,检查日
创建ext3文件系统。
journal=”日志”
使用命令dumpe2fs /dev/sdc1 | more 可以看到成功创建ext3文件系统。
二、在ext3格式文件系统上,数据写 入硬盘的操作过程为: ⑴数据同样先写 入缓冲区 ① ⑵当数据写入 缓冲区 (内存) 缓冲区满时,先通知 ③ 日志 ext3 文件 ⑶通知日志之后 ② ④ 系统 数据才会写入硬盘中 日志 ⑷数据写入硬盘后,系统 再通知日志数据已经写入硬盘。
三、日志机制 在ext2和ext3中,文件系统的格式是 一样的,不一样的地方是ext2没有日志 机制,而ext3有日志机制。 对于ext2,由于它没有日志机制,在 Linux使用Valid bit标志位来记录系统在 关机之前该文件系统是否已经卸载。因 每一个文件系统都有一个自己的Valid bit 。并且,Valid bit的值为1,则表示这个 文件系统已经卸载,而其值为0,则表示 这个文件系统没有正常关机。
Ext2文件系统
ext2的索引结点中使用了组合索引方式。
前12项用作直接索引 第13项用作间接索引 第14项用作二次间接索引 第15项用作三次间接索引
EXT2文件系统中的每个文件由一个inode描述,且只能由一个 inode描述。 inode与文件一起存放在外存,系统运行时,把inode写入内存建 立映像,加快文件系统速度。
Ext2文件系统简介
EXT2文件系统是EXT文件系统的升级, 在Linux中得到了广泛的使用。
Linux最常见的根文件系统
介绍EXT2文件系统的
磁盘组织 目录项和支持的文件类型
一个文件系统一般使用块设备上一个独立的逻 辑分区; 文件逻辑分区中除了有表示文件内容的逻辑 块(称为数据块)外,还设置了包含管理和控制 信息的逻辑块。 磁盘上可能有多个逻辑分区,每个分区可以 使用不同的文件子系统。
块组描述符
块组描述符用来描述一个磁盘块组的相关信息 块组描述符组由若干块组描述符组成,描述了文件系 统中所有块组的属性,存放于超级块所在块的下一个 块中。
一个块组描述符的结构如下 :
数据块位图和索引结点块位图
EXT2的空闲盘块分配算法采用了位图法 位图: 为便于查找数据块或索引结点的分配信息 每个位(bit)都对应了一个磁盘块:
2个位图分别占用一个专门的磁盘块;位于组描述符表 之后 根据磁盘块的大小,可以计算出每个块组中最多能容 纳的数据块个数和索引节点块个数
0,表示对应的磁盘块(或索引结点)空闲 1,表示占用。
索引结点
EXT2中所有的索引结点大小相同,都是128个字节。 一个inode的结构如下:
genext2fs参数
genext2fs参数摘要:1.什么是genext2fs 参数2.genext2fs 参数的作用3.如何设置genext2fs 参数4.设置genext2fs 参数的注意事项正文:genext2fs 参数是用于配置Linux 系统中ext2 文件系统的参数。
它可以修改文件系统的各种设置,如文件分配表大小、簇大小、日志文件大小等,以提高文件系统的性能和稳定性。
在设置genext2fs 参数时,需要了解各个参数的含义和作用,以便正确配置文件系统。
1.什么是genext2fs 参数genext2fs 是一个用于配置ext2 文件系统的工具,它可以设置文件系统的各种参数,以满足不同场景的需求。
这些参数包括文件分配表大小、簇大小、日志文件大小、最大文件大小等。
通过调整这些参数,可以提高文件系统的性能、稳定性和兼容性。
2.genext2fs 参数的作用genext2fs 参数主要用于以下几个方面:- 优化文件系统性能:通过调整文件分配表大小、簇大小等参数,可以提高文件系统的读写速度,降低磁盘I/O 负载。
- 提高文件系统稳定性:设置日志文件大小和最大文件大小等参数,可以增加文件系统的容错能力,防止因磁盘空间不足或文件过大导致系统崩溃。
- 兼容不同场景需求:根据不同的应用场景,可以通过设置genext2fs 参数,使文件系统更好地适应特定需求,如服务器、嵌入式设备等。
3.如何设置genext2fs 参数设置genext2fs 参数通常需要使用以下命令:```genext2fs -O <options> <device>```其中,`<options>`表示需要设置的参数,`<device>`表示文件系统所在的设备。
常用的genext2fs 参数选项包括:- `-O`:表示使用扩展选项,其后跟具体的参数。
- `-m`:设置文件分配表大小。
- `-M`:设置簇大小。
EXT2、EXT3、EXT4、XFS、GPT详解
EXT2、EXT3、EXT4、XFS、GPT详解原创:运维老司机小柒博客7月18日EXT2与EXT3区别Linux之前缺省情况下使用的文件系统为Ext2,ext2文件系统的确高效稳定。
但是,随着Linux系统在关键业务中的应用,Linux文件系统的弱点也渐渐显露出来了:其中系统缺省使用的ext2文件系统是非日志文件系统。
这在关键行业的应用是一个致命的弱点,Ext3文件系统是直接从Ext2文件系统发展而来,目前ext3文件系统已经非常稳定可靠。
它完全兼容ext2文件系统。
用户可以平滑地过渡到一个日志功能健全的文件系统中来。
这实际上了也是ext3日志文件系统初始设计的初衷。
1) ext3和ext2的主要区别在于,ext3引入Journal(日志)机制,Linux内核从2.4.15开始支持ext3,它是从文件系统过渡到日志式文件系统最为简单的一种选择,ext3提供了数据完整性和可用性保证。
2) ext2和ext3的格式完全相同,只是在ext3硬盘最后面有一部分空间用来存放Journal的记录;3) 在ext2中,写文件到硬盘中时,先将文件写入缓存中,当缓存写满时才会写入硬盘中;4) 在ext3中,写文件到硬盘中时,先将文件写入缓存中,待缓存写满时系统先通知Journal,再将文件写入硬盘,完成后再通知Journal,资料已完成写入工作;5) 在ext3中,也就是有Journal机制里,系统开机时检查Journal的内容,来查看是否有错误产生,这样就加快了开机速度;EXT3日志文件系统的特点1、高可用性系统使用了ext3文件系统后,即使在非正常关机后,系统也不需要检查文件系统。
宕机发生后,恢复ext3文件系统的时间只要数十秒钟。
2、数据的完整性ext3文件系统能够极大地提高文件系统的完整性,避免了意外宕机对文件系统的破坏。
在保证数据完整性方面,ext3文件系统有2种模式可供选择。
其中之一就是"同时保持文件系统及数据的一致性"模式。
Linux ext2
Linux ext2ext2文件系统是早期Linux发布版的基础,Linux默认直接支持的文件系统。
该文件系统非常优势,也是ext3文件系统的基础。
ext2文件系统和其他现代Unix 使用的文件系统非常相似,但更接近于BSD(Berkeley Software Distribution:Berkeley 软件分发版)系统所用的Berkeley Fast Filesystem。
ext2文件系统除了具有标准功能外,还支持一般Unix文件系统中所没有的高级功能,如设置文件属性、支持数据更新时同步写入、允许磁盘管理员在创建文件系统时选择逻辑数据块的大小、实现快速符号链接以及提供两种定期强迫进行文件系统工具等。
1.ext2文件系统的物理结构ext2文件系统像多数文件系统一样,建立在文件数据存放在数据中的前提下。
ext2文件系统中的数据块具有相同的长度,虽然不同的ext2文件系统的块长度可以不同,但是对于某个特定的ext2文件系统,它的块长度在创建的时候就已经确定了。
每一个文件的长度都会按照块取整,例如,存在一个文件1025字节,而一个块的大小为1024字节时,该文件就会占用两个1024字节的块,这就意味着平均每一个文件都有可能浪费一部分磁盘空间。
每个块包含了相同的信息如:超级块、块组描述结构、块位图索引节点、索引点表和数据块等内容,图4-2演示了ext2文件系统的物理结构。
图4-2 ext2物理结构2.块组的构造从图4-2中可看到每一个块组都重复保存着一些有关整个文件系统的关键信息,以及真正的文件和目录的数据块。
超级块包含有文件系统本身的大小和形式的基本信息,系统管理员可以利用这些信息使用和维护文件系统。
在安装文件系统时,系统只读取数据块组1中的超级块,将其放入内存直到该文件系统被卸载,超级块中包含了以下内容。
●块数用于确认安装的文件系统是否为ext2的超级块。
●修订级别这是文件系统的主版本号和次版本号。
ext文件系统分析
日志文件系统配置 Journal:将元数据和数据写操作涉及数据都写 入日志。 Ordered(省缺模式):日志只记录元数据写。 系统确保文件数据写盘后才进行元数据写操作, 减少文件数据损坏的机会 。 Writeback(最快模式):日志只记录元数据写。
17.8Ext4文件系统新特性
ext4 支持更大的文件系统、文件和子目录。最大
17.5 ext2与VFS层的接口函数 ext2_sops指针数组存放了super_operations 结构类型的一组操作函数指针;
ext2_file_inode_operations/ext2_dir_inod e_operations指针数组存放了inode_operations 结构类型的一组操作函数指针;(2.4版后将 ext2_file_inode_operations的大部分函数移到 ext2_aops中) ext2_file_operations指针数组存放了 file_operations结构类型的一组file操作函数 指针;
Inode及数据块区的bitmap表因为太大不可能同 时存于内核空间,需要部分缓冲处理;
17.4文件系统分区建立
利用/sbin/mke2fs实用程序建立ext2文件系统分 区。生成盘上相关数据结构、建根目录文件等。
如果系统断电等突然停机,e2fsck实用程序必须 在系统重启时运行以保证磁盘数据一致性。
ext2目录文件inode操作表: struct inode_operations ext2_dir_inode_operations = { create: ext2_create, lookup: ext2_lookup, link: ext2_link, unlink: ext2_unlink, symlink: ext2_symlink, mkdir: ext2_mkdir, rmdir: ext2_rmdir, mknod: ext2_mknod, rename: ext2_rename, };
linux分区格式说明
Linux分区格式主要包括以下几种:1. Ext2:Ext2是GNU/Linux系统中标准的文件系统,适用于标准的块设备(如硬盘)和移动存储设备(如软盘)。
它具有极快的速度和极小的CPU占用率。
2. Ext3:Ext3是Ext2的下一代,它在Ext2的基础上增加了日志功能。
Ext3是一种日志式文件系统(Journal File System),能够将整个磁盘的写入动作完整地记录在磁盘的某个区域上,以便有需要时回溯追踪。
当在某个过程中断时,系统可以根据这些记录直接回溯并重整被中断的部分,重整速度相当快。
该分区格式被广泛应用在Linux系统中。
3. Linux swap:Linux swap是Linux中一种专门用于交换分区的文件系统。
整个分区被用作交换空间,一般大小为主内存的2倍。
在内存不够时,Linux会将部分数据写到交换分区上。
4. VFAT:VFAT叫长文件名系统,这是一个与Windows系统兼容的Linux文件系统,支持长文件名,可以作为Windows 与Linux交换文件的分区。
5. XFS:XFS是一种高性能的文件系统,适用于大型文件和大量并发操作的场景。
它具有很高的性能和可扩展性,支持高达100PB的文件系统容量。
6. BtrFS:BtrFS(B-Tree Filesystem)是一种先进的文件系统,具有优秀的性能、可靠性和可扩展性。
它采用B树数据结构进行文件和目录的组织,支持高达1YB的文件系统容量。
7. GlusterFS:GlusterFS是一种分布式文件系统,适用于大数据处理和云计算场景。
它将文件分布在多个物理节点上,提供高可用性、高性能和可扩展性。
以上就是Linux常见的分区格式,不同的分区格式具有不同的特点和应用场景。
在实际使用中,可以根据需求选择合适的分区格式。
Linux的Ext2文件系统详解
前述:Linux系统管理员很重要的任务之一就是管理好自己的磁盘文件系统,每个分区不可太大也不可以太小,太大会导致磁盘容量的浪费,太小会导致产生的文件无法存储的问题。
在Linux里面文件是由两部分数据组成,一部分是metadata,另一部分是data。
那么这些数据都存放在文件系统的什么地方呢?这就让我们必须得了解文件系统的Inode与Block 的基本原理了,而Linux最传统的磁盘文件系统使用的是Ext2,所以我们了解下它的内部原理。
第一部分:磁盘的组成和分区(基础)磁盘的机械部分:1、圆形的盘片(主要记录数据的部分)2、机械手臂与机械手臂上的磁头(可读写盘片上的数据)3、主轴马达,可以转动盘片,让机械手臂的磁头在盘片上读写数据磁盘的基本概念1、扇区是最小的物理存储单元(512bytes)2、将扇区组成一个园,那就是柱面,柱面是分区的最小单位3、第一个扇区最重要,里面有硬盘的主引导程序(MBR)占446bytes和分区表(partision tables)占64bytes。
4、目前流行的家用硬盘接口SATA和服务器硬盘接口SAS。
磁盘分区部分:1、主分区和扩展分区最多可以有4个(硬盘的限制)2、扩展分区最多只能有一个(操作系统限制)3、逻辑分区是由扩展分区分化出来的分区4、主分区和逻辑分区的内容可以被格式化,而扩展分区无法格式化第二部分:文件系统的基本特性我们都知道硬盘分区后都是需要格式化,之后操作系统才能使用该分区,为什么呢?这是因为各种操作系统的文件的属性和权限并不相同的,为了能够存放这些文件,因此将分区格式化,以成为操作系统能利用的系统格式。
文件系统通常会将两部分的数据分别放在不同的块,权限与属性放置到inode中,实际的数据放置到data block块中,另外还有一个超级块(superblock)会记录整个文件系统的整体信息,包括inode和block的总量、使用量、剩余量,以及文件系统的格式与信息。
MINIX, EXT2,FAT文件系统概要分析
MINIX, EXT2,FAT文件系统概要分析关键词:MINIX EXT2FAT FAT32分析Title: 概述了MINIX,EXT2,FAT文件系统,看完应该有一个全局的了解Author: QuanDate: 18.04.2006====================MINIX:====================Minix的文件系统主要包括一下6个部分:引导块,超级块,i节点位图,区段位图,真正的i节点信息,数据。
引导块:一般来将,每一个文件分区里面,都必须包含一个引导块。
虽然并不是每一个设备的分区都是用来引导的,但是,出于结构的统一以及兼容性方面的考虑,一般文件系统需要将分区的第一个块保留为引导块。
因此,我以前曾经犯过的一个错误就是,认为启动盘在windows里面是不能够被识别的,会提示磁盘未格式化。
看来我真的是错了,只能将那个启动盘上的系统,windows不能够识别。
但是,启动盘里面确实也装载着完整的文件系统。
超级块:之所以称之为超级块,就是因为这个块是整个文件系统的龙头!从它,可以推算出整个文件系统的信息。
在minix中,它包含了i节点数,区段数,块/区段比,最大文件长度,magic number等等信息。
这样,整个文件系统中,上面所涉及到的6个部分的分布就清楚了。
位图:常用的一个数据结构。
使用一个bit来代表一个有序逻辑单位,如这里的一个i节点,一个区段,或者是内存中的一页等等。
这里,使用位图来表示哪些i节点是可以的或者是不可用的,对于区段的使用方式也是相同的。
这样,就是对有序的逻辑单位进行了标记,而且这样的标记是写入磁盘的因此可以长期的保存。
所以,必须要确保文件系统的一致性(consistency),因为标记和真正的逻辑单位并不是同时写入磁盘的。
这一点,相当的重要。
i节点:这个结构和UNIX下的文件系统应该说是一样的。
这里保存着对应于每个文件的具体的信息,如文件类型,访问权限,链接信息,文件大小,时间信息,区段号(包括一次间接块和二次间接块)等等与文件密切相关的信息。
EXT2文件系统的分析与研究
第 2 卷第 3 2 期 20 07年 6月
成
都
信
息
工
程ห้องสมุดไป่ตู้
学
院
学 报
Vl . 2No 3 0 2 1 .
J RNA HEN U VE S T OFI 1R A I C NOL Y OU LOFC GD UNI R I Y D M T ON TE H NF OG
下:
图 1 E T2文件系统的磁盘布 局 X
收 稿 日期 :0 61 .7 修 订 日期 :0 61 .2 2 0 .11 ; 2 0 .12
基金项 目: 成都信息工 程学 院科研基金资助项 目( R 2 0 0 ) C F 0 4 9
维普资讯
第 3期
徐 虹 等 : X 2文件 系统 的分 析与研 究 E T
31 3
Ma iN m e 文件系统安装软件用来检验是否是一个真正的 E T 文件系统超块。当前 E T 版本中为 g u br: c X2 X2
0 EF 3 x 5 。
Bok i 以字节记数的文件系统块大小 , 12 l z c S e: 如 04字节。 Bok e G op: l s r ru 每个组 中块数 目。当文件系统创建时此块大小被固定下来。 c p Fe l k 文件系统中的空闲块数。 r Bo s: e c Fe o e 文件系统中空闲 Ioe 。 r Id s: en n 数 d Fr o e: it n sI d 文件系统 中第一个 Ioe 。E T n 号 d X 2根文件系统中第一个 I e n 将是指 向‘’ d o / 目录的人 口。
11 E T . X 2的磁盘 布局
个文件系统如何在磁盘上布局 , 要考虑到数据的安全性 ; 数据结构要能高效地支持所有的操作 ; 应使数据 查找的时间尽量短以及磁盘空间的利用率。 E T 文件系统将它所 占用设备 的逻辑分区分成 了多个数据块组。每一个数据块组都包含一些有关整个文 X2 件系统的描述信息以及数据块 , 如关键的文件控制信息 ( 超级块 和文件 系统描述符和组描述符) 的副本 , 块位 图、 索引节点位图、 索引节点表以及数据区等。 引导块中含有可执行代码 , 启动计算机时 , 硬件从引导设备将引导块读人内存 , 然后执行引导程序。系统启 动后 , 引导块不再使用 。因此 , 引导块不属于文件系统管理。图 1 给出了磁盘上 的 E T 文件系统的磁盘布局。 X2 E T X 2文件 系统 中 的数 据 是 以数 据 块 的方式存储在文件中。这些数据块长度相 Sa e f m or ever gr y oup D i t nct f ever gr si or y oup 等且这个 长度可 以变化 , 一个 E T X 2文件 系统的块大小是在创建( 使用 m ef 时设 k2 ) s 置, 每个文 件 的大小 是块大小 的整数倍 。 体现了 E T X 2的灵活性和可扩展性。
EXT2文件系统
ext2 文件系统格式The Second Extended File System(ext2)文件系统是 Linux 系统中的标准 文件系统,是通过对 Minix 的文件系统进行扩展而得到的,其存取文件的性能 极好。
在 ext2 文件系统中,文件由 inode(包含有文件的所有信息)进行唯一标识。
一个文件可能对应多个文件名,只有在所有文件名都被删除后,该文件才会被 删除。
此外,同一文件在磁盘中存放和被打开时所对应的 inode 是不同的,并 由内核负责同步。
ext2 文件系统采用三级间接块来存储数据块指针,并以块 (block,默认为 1KB)为单位分配空间。
其磁盘分配策略是尽可能将逻辑相 邻的文件分配到磁盘上物理相邻的块中, 并尽可能将碎片分配给尽量少的文件, 以从全局上提高性能。
ext2 文件系统将同一目录下的文件(包括目录)尽可能 的放在同一个块组中,但目录则分布在各个块组中以实现负载均衡。
在扩展文 件时,会尽量一次性扩展 8 个连续块给文件(以预留空间的形式实现)。
2.1. 总体存储布局 请点评我们知道,一个磁盘可以划分成多个分区,每个分区必须先用格式化工具(例 如某种 mkfs 命令)格式化成某种格式的文件系统,然后才能存储文件,格式 化的过程会在磁盘上写一些管理存储布局的信息。
下图是一个磁盘分区格式化 成 ext2 文件系统后的存储布局。
图 1. ext2 文件系统的总体存储布局文件系统中存储的最小单位是块(Block),一个块究竟多大是在格式化时确 定的,例如 mke2fs 的-b 选项可以设定块大小为 1024、2048 或 4096 字节。
而上图中启动块(Boot Block)的大小是确定的,就是 1KB,启动块是由 PC 标准规定的,用来存储磁盘分区信息和启动信息,任何文件系统都不能使用启 动块。
启动块之后才是 ext2 文件系统的开始, ext2 文件系统将整个分区划成若干 个同样大小的块组(Block Group),每个块组都由以下部分组成。
Linux文件系统Ext2,Ext3,Ext4性能大比拼
Linux kernel 自2.6.28 开始正式支持新的文件系统Ext4。
Ext4 是Ext3 的改进版,修改了Ext3 中部分重要的数据结构,而不仅仅像Ext3 对Ext2 那样,只是增加了一个日志功能而已。
Ext4 可以提供更佳的性能和可靠性,还有更为丰富的功能:1. 与Ext3 兼容。
执行若干条命令,就能从Ext3 在线迁移到Ext4,而无须重新格式化磁盘或重新安装系统。
原有Ext3 数据结构照样保留,Ext4 作用于新数据,当然,整个文件系统因此也就获得了Ext4 所支持的更大容量。
2. 更大的文件系统和更大的文件。
较之Ext3 目前所支持的最大16TB 文件系统和最大2TB 文件,Ext4 分别支持1EB(1,048,576TB,1EB=1024PB,1PB=1024TB)的文件系统,以及16TB 的文件。
3. 无限数量的子目录。
Ext3 目前只支持32,000 个子目录,而Ext4 支持无限数量的子目录。
4. Extents。
Ext3 采用间接块映射,当操作大文件时,效率极其低下。
比如一个100MB 大小的文件,在Ext3 中要建立25,600 个数据块(每个数据块大小为4KB)的映射表。
而Ext4 引入了现代文件系统中流行的extents 概念,每个extent 为一组连续的数据块,上述文件则表示为“该文件数据保存在接下来的25,600 个数据块中”,提高了不少效率。
5. 多块分配。
当写入数据到Ext3 文件系统中时,Ext3 的数据块分配器每次只能分配一个4KB 的块,写一个100MB 文件就要调用25,600 次数据块分配器,而Ext4 的多块分配器“multiblock allocator”(mballoc)支持一次调用分配多个数据块。
6. 延迟分配。
Ext3 的数据块分配策略是尽快分配,而Ext4 和其它现代文件操作系统的策略是尽可能地延迟分配,直到文件在cache 中写完才开始分配数据块并写入磁盘,这样就能优化整个文件的数据块分配,与前两种特性搭配起来可以显著提升性能。
linux操作系统中EXT2文件的组成
_
l块 l块I块}块… 组 o组 l组 2组 N I
l
超级 块 组块 块位 图 引位图 索 索线 表 数据块 描述表 图 1 硬 盘 、 区 、 组 的 组 成 分 块
Fi .1 Co po ii n o r rve,Zo ng a l c r up g m sto fha d d i ni nd b o k g o
第 3 3卷第 4 期 21 0 1年 O 4月
武
汉
工
程
大
学
学
报
V ol 3 NO. _3 4 A Dr 2 . O11
J W u a I s. Teh . hn nt c.
文 章 编 号 :6 4—2 6 ( 0 1 0 17 8 9 2 1 ) 4—0 9 0 4—0 3
一
致性检查时 , 就会将块组 0中的超级 块拷贝到其他
标 准文 件 系统 也 得 到 了 广泛 的 支 持 和 考 验. 精 其
巧 、 活 的 设 计 , 存 取 中小 文 件 时 的 性 能 非 常 灵 在 好 , 大地 满 足 了人 们 对 数 据 存 储 的要 求 . 时 , 极 同 e t 文 件 系 统也 是 其 后 继 e t x2 x 3和 e t 日志文 件 x4 系统 的 基 础 . 析 e t 剖 x 2文 件 系 统 , 深 入 理 解 对
l u i x操作 系统 中 E T2 n X 文件的组成
朱 颂
( . 汉大 学计算机 学 院 , 北 武汉 4 0 7 ;. 1武 湖 3 0 2 2 孝感 学 院计 算机 与信 息科 学 学院 , 北 孝感 4 2 0 ) 湖 3 0 0
第九章_Ext2文件系统_ro机
第九章_Ext2文件系统_ro机第九章Ext2文件系统9.1基本概念在上一章中,我们把Ext2、Minix、Ext等实际可使用的文件系统称为具体文件系统.具体文件系统管理的是一个逻辑空间,这个逻辑空间就象一个大的数组,数组的每个元素就是文件系统操作的基本单位——逻辑块,逻辑块是从0开始编号的,而且,逻辑块是连续的.与逻辑块相对的是物理块,物理块是数据在磁盘上的存取单位,也就是每进行一次I/O操作,最小传输的数据大小.我们知道数据是存储在磁盘的扇区中的,那么扇区是不是物理块呢?或者物理块是多大呢?这涉及到文件系统效率的问题.如果物理块定的比较大,比如一个柱面大小,这时,即使是1个字节的文件都要占用整个一个柱面,假设Linux环境下文件的平均大小为1K,那么分配32K的柱面将浪费97%的磁盘空间,也就是说,大的存取单位将带来严重的磁盘空间浪费.另一方面,如果物理块过小,则意味着对一个文件的操作将进行更多次的寻道延迟和旋转延迟,因而读取由小的物理块组成的文件将非常缓慢!可见,时间效率和空间效率在本质上是相互冲突的.因此,最优的方法是计算出Linux环境下文件的平均大小,然后将物理块大小定为最接近扇区的整数倍大小.在Ext2中,物理块的大小是可变化的,这取决于你在创建文件系统时的选择,之所以不限制大小,也正体现了Ext2的灵活性和可扩充性,一是因为要适应近年来文件的平均长度缓慢增长的趋势,二是为了适应不同的需要.比如,如果一个文件系统主要用于BBS服务,考虑到BBS上的文章通常很短小,所以,物理块选的小一点是恰当的.通常,Ext2的物理块占一个或几个连续的扇区,显然,物理块的数目是由磁盘容量等硬件因素决定的.逻辑块与物理块的关系类似于虚拟内存中的页与物理内存中的页面的关系.具体文件系统所操作的基本单位是逻辑块,只在需要进行I/O操作时才进行逻辑块到物理块的映射,这显然避免了大量的I/O操作,因而文件系统能够变得高效.逻辑块作为一个抽象的概念,它必然要映射到具体的物理块上去,因此,逻辑块的大小必须是物理块大小的整数倍,一般说来,两者是一样大的.通常,一个文件占用的多个物理块在磁盘上是不连续存储的,因为如果连续存储,则经过频繁的删除、建立、移动文件等操作,最后磁盘上将形成大量的空洞,很快磁盘上将无空间可供使用.因此,必须提供一种方法将一个文件占用的多个逻辑块映射到对应的非连续存储的物理块上去,Ext2等类文件系统是用索引节点解决这个问题的,具体实现方法后面再予以介绍.为了更好的说明逻辑块和物理块的关系,我们来看一个例子.假设用户要对一个已有文件进行写操作,用户进程必须先打开这个文件,file结构记录了该文件的当前位置.然后用户把一个指向用户内存区的指针和请求写的字节数传送给系统,请求写操作,这时系统要进行两次映射.一组字节到逻辑块的映射.这个映射过程就是找到起始字节到结束字节所占用的所有逻辑块号.这是因为在逻辑空间,文件传输的基本单位是逻辑块而不是字节.逻辑块到物理块的映射.这个过程必须要用到索引节点结构,该结构中有一个物理块指针数组,以逻辑块号为索引,通过这些指针找到磁盘上的物理块,具体实现将在介绍Ext2索引节点时再进行介绍.图9.1是由一组请求的字节到物理块的映射过程示意图.图9.1一组字节映射到物理块的示意图有了逻辑块和物理块的概念,我们也就知道通常所说的数据块是指逻辑块,以下没有特别说明,块或数据块指的是逻辑块.在Ext2中,还有一个重要的概念:片,它的作用是什么? 每个文件必然占用整数个逻辑块,除非每个文件大小都恰好是逻辑块的整数倍,否则最后一个逻辑块必然有空间未被使用,实际上,每个文件的最后一个逻辑块平均要浪费一半的空间,显然最终浪费的还是物理块.在一个有很多文件的系统中,这种浪费是很大的.Ext2使用片来解决这个问题.片也是一个逻辑空间中的概念,其大小在1K至4K之间,但片的大小总是不大于逻辑块.假设逻辑块大小为4K,片大小为1K,物理块大小也是1K,当你要创建一个3K大小的文件时,实际上分配给你了3个片,而不会给你一个逻辑块,当文件大小增加到4K时,文件系统则分配一个逻辑块给你,而原来的四个片被清空.如果文件又增加到5K时,则占用1个逻辑块和1个片.上述三种情况下,所占用的物理块分别是3个、4个、5个,如果不采用片,则要用到4个、4个、8个物理块,可见,使用片,减少了磁盘空间的浪费.当然,在物理块和逻辑块大小一样时,片就没有意义了.由上面分析也可看出:物理块大小100>12,所以要用到一次间接块,在一次间接块中查找第88项,此项内容就是对应的物理块的地址.而如果要找第1000个逻辑块对应的物理块,由于1000>256+12,所以要用到二次间接块了.索引节点的标志取下列几个值的可能组合.EXT2_SECRM_FL0x00000001完全删除标志.设置这个标志后,删除文件时,随机数据会填充原来的数据块.EXT2_UNRM_FL0x00000002可恢复标志.设置这个标志后,删除文件时,文件系统会保留足够信息,以确保文件仍能恢复EXT2_COMR_FL0x00000004压缩标志.设置这个标志后,表明该文件被压缩过.当访问该文件时,文件系统必须采用解压缩算法进行解压.EXT2_SYNC_FL0x00000008同步更新标志.设置该标志后,则该文件必须和内存中的内容保持一致,对这种文件进行异步输入、输出操作是不允许的.这个标志仅用于节点本身和间接块.数据块总是异步写入磁盘的.除了这几个常用标志外,还有12个标志就不一一介绍了.索引节点在磁盘上是经过编号的.其中,有一些节点有特殊用途,用户不能使用.这些特殊节点也在include/Linux/ext2_fs.h中定义.#defineEXT2_BAD_INO1该节点所对应的文件中包含着该文件系统中坏块的链接表#defineEXT2_ROOT_INO2该文件系统的根目录所对应的节点#defineEXT2_IDX_INO3ACL节点#defineEXT2_DATA_INO4ACL节点#defineEXT2_BOOT_LOADER_INO5用于引导系统的文件所对应的节点#defineEXT2_UNDEL_DIR_INO6文件系统中可恢复的目录对应的节点没有特殊用途的第一个节点号为11#defineEXT2_FIRST_INO11文件的类型、访问权限、用户标识号、用户组标识号等将在后面介绍.与Ext2超级块类似,当磁盘上的索引节点调入内存后,除了要填写VFS的索引节点外,系统还要根据它填写另一个数据结构,该结构叫ext2_inode_info,其作用也是为了存储特定文件系统自己的特性,它在include/Linux/ext2_fs_i.h中定义如下:structext2_inode_info{__u32i_data[15]数据块指针数组*/__u32i_flags;打开文件的方式*/__u32i_faddr;片的地址*/__u8i_frag_no;如果用到片,则是第一个片号*/__u8i_frag_size;片大小*/__u16i_osync;同步*/__u32i_file_acl;文件访问控制链表*/__u32i_dir_acl;目录访问控制链表*/__u32i_dtime;文件的删除时间*/__u32i_block_group;索引节点所在的块组号*//******以下四个域是用于操作预分配块的*__u32i_next_alloc_block;__u32i_next_alloc_goal;__u32i_prealloc_block;__u32i_prealloc_count;__u32i_dir_start_lookupinti_new_inode:1/*Isafreshlyallocatedinode*/};VFS索引节点中是没有物理块指针数组的域,这个Ext2特有的域在调入内存后,就必须保存在ext2_inode_info这个结构中.此外,片作为Ext2比较特殊的地方,在ext2_inode_info中也保存了一些相关的域.另外,Ext2在分配一个块时通常还要预分配几个连续的块,因为它判断这些块很可能将要被访问,所以采用预分配的策略可以减少磁头的寻道时间.这些用于预分配操作的域也被保存在ext2_inode_info结构中.9.2.4组描述符块组中,紧跟在超级块后面的是组描述符表,其每一项称为组描述符,是一个叫ext2_group_desc的数据结构,共32字节.它是用来描述某个块组的整体信息的. structext2_group_desc{__u32bg_block_bitmap;/*组中块位图所在的块号*/__u32bg_inode_bitmap;组中索引节点位图所在块的块号*/__u32bg_inode_table;/*组中索引节点表的首块号*/__u16bg_free_blocks_count;/*组中空闲块数*/__u16bg_free_inodes_count;/*组中空闲索引节点数*/__u16bg_used_dirs_count;/*组中分配给目录的节点数*/__u16bg_pad;填充,对齐到字*/__u32[3]bg_reserved;用null填充12个字节*/}每个块组都有一个相应的组描述符来描述它,所有的组描述符形成一个组描述符表,组描述符表可能占多个数据块.组描述符就相当于每个块组的超级块,一旦某个组描述符遭到破坏,整个块组将无法使用,所以组描述符表也像超级块那样,在每个块组中进行备份,以防遭到破坏.组描述符表所占的块和普通的数据块一样,在使用时被调入块高速缓存.9.2.5位图在Ext2中,是采用位图来描述数据块和索引节点的使用情况的,每个块组中都有两个块,一个用来描述该组中数据块的使用情况,另一个描述该组中索引节点的使用情况.这两个块分别称为数据块位图块和索引节点位图块.数据位图块中的每一位表示该组中一个块的使用情况,如果为0,则表示相应数据块空闲,为1,则表示已分配,索引节点位图块的使用情况类似.Ext2在安装后,用两个高速缓存分别来管理这两种位图块.每个高速缓存最多同时只能装入Ext2_MAX_GROUP_LOADED个位图块或索引节点块,当前该值定义为8,所以也应该采用一些算法来管理这两个高速缓存,Ext2中采用的算法类似于LRU算法.前面说过,ext2_sp_info结构中有四个域用来管理这两个高速缓存,其中s_block_bitmap_number[]数组中存有进入高速缓存的位图块号,而s_block_bitmap[]数组则存储了相应的块在高速缓存中的地址.s_inode_bitmap_number[]和s_inode_bitmap[]数组的作用类似上面.我们通过一个具体的函数来看Ext2是如何通过这四个域管理位图块高速缓存的.在Linux/fs/ext2/balloc.c 中,有一个函数load__block_bitmap,它用来调入指定的数据块位图块,下面是它的执行过程:如果指定的块组号大于块组数,出错,结束;通过搜索s_block_bitmap_number[]数组可知位图块是否已进入高速缓存,如果已进入,则结束,否则,继续; 如果块组数不大于Ext2_MAX_GROUP_LOADED,高速缓存可以同时装入所有块组的数据块位图块,不用采用什么算法,只要找到s_block_bitmap_number[]数组中第一个空闲元素,将块组号写入,然后将位图块调入高速缓存,最后将它在高速缓存中的地址写入s_block_bitmap[]数组中;如果块组数大于Ext2_MAX_GROUP_LOADED,则需要采用以下算法;首先通过s_block_bitmap_number[]数组判断高速缓存是否已满,若未满,则操作过程类似上一步,不同之处在于需要将s_block_bitmap_number[]数组各元素依次后移一位,而用空出的第一个元素存储块组号,s_block_bitmap[]也要做相同处理;如果高速缓存已满,则将s_block_bitmap[]数组最后一项所指的位图块从高速缓存中交换出去,然后调入所指定的位图块,最后对这两个数组作和上面相同的操作;可以看出,这个算法很简单,就是对两个数组的简单操作,只是在块组数大于Ext2_MAX_GROUP_LOADED时,要求数组的元素按最近访问的先后次序排列,显然,这样也是为了更合理的进行高速缓存的替换操作.9.2.6索引节点表及实例分析在两个位图块后面,就是索引节点表了,每个块组中的索引节点都存储在各自的索引节点表中,并且按索引节点号依次存储.索引节点表通常占好几个数据块,索引节点表所占的块使用时也像普通的数据块一样被调入块高速缓存.有了以上几个概念和数据结构后,我们分析一个具体的例子,来看看这些数据结构是如何配合工作的.在fs/ext2/inode.c中,有一个ext2_read_inode,用来读取指定的索引节点信息.其代码如下:voidext2_read_inode{structbuffer_head*bh;structext2_inode*raw_inode; unsignedlongblock_group; unsignedlonggroup_desc; unsignedlongdesc; unsignedlongblock; unsignedlongoffset;structext2_group_desc *gdp;if)||inode->i_ino>le32_to_cpu){ext2_error;gotobad_inode;}block_group/EXT2_INODES_PER_GROUP;if{ext2_error;gotobad_inode;}group_desc=block_group>>EXT2_DESC_PER_BLOCK_BITS; desc=block_group&1);bh=inode->i_sb->u.ext2_sb.s_group_desc[group_desc]; if{ext2_error;gotobad_inode;}gdp=bh->b_data;/**Figureouttheoffsetwithintheblockgroupinodetable*/offset=%EXT2_INODES_PER_GROUP) *EXT2_INODE_SIZE;block=le32_to_cpu+);if)){ext2_error;gotobad_inode;}offset&=-1);raw_inode=;inode->i_mode =le16_to_cpu; inode->i_uid=le16_to_cpu;inode->i_gid =le16_to_cpu; if)){inode->i_uid |=le16_to_cpui_gid|=le16_to_cpui_nlink=le16_to_cpu; inode->i_size =le32_to_cpu; inode->i_atime =le32_to_cpu; inode->i_ctime =le32_to_cpu;inode->i_mtime=le32_to_cpu;inode->u.ext2_i.i_dtime =le32_to_cpu;/*Wenowhaveenoughfieldstocheckiftheinodewasactiveornot.Thisis needed because nfsd might tryto access dead inodes *the testisthat same one thate2fsck usesNeilBrown 1999oct15*/if){/*thisinodeisdeleted*/brelse;gotobad_inode;}inode->i_blksize =PAGE_SIZE;/*ThistheoptimalIOsize,notthefsblocksize*/inode->i_blocks=le32_to_cpu;inode->i_version=++event;inode->u.ext2_i.i_flags =le32_to_cpu;inode->u.ext2_i.i_faddrle32_to_cpu;inode->u.ext2_i.i_frag_no =raw_inode->i_frag;inode->u.ext2_i.i_frag_size =raw_inode->i_fsize; inode->u.ext2_i.i_file_acl =le32_to_cpu;if)inode->i_size|=le32_to_cpu)u.ext2_i.i_dir_acl=le32_to_cpu;inode->i_generation=le32_to_cpu;inode->u.ext2_i.i_prealloc_count =0;inode->u.ext2_i.i_block_group =block_group;/**NOTE!Thein-memoryinodei_dataarrayisinlittle-endianorder*evenonbig-endianmachines: wedoNOT byteswap theblock numbers! */for/* Nothingtodo*/;elseif){inode->i_op=&ext2_file_inode_operations; inode->i_fop=&ext2_file_operations;inode->i_mapping->a_ops=&ext2_aops;}elseif){inode->i_op=&ext2_dir_inode_operations; inode->i_fop=&ext2_dir_operations; inode->i_mapping->a_ops=&ext2_aops;}elseif){ifinode->i_op=&ext2_fast_symlink_inode_operations; else{inode->i_op=&page_symlink_inode_operations; inode->i_mapping->a_ops=&ext2_aops;}}elseinit_special_inode);brelse;inode->i_attr_flags=0;if{inode->i_attr_flags|=A TTR_FLAG_SYNCRONOUS; inode->i_flags|=S_SYNC;}if{inode->i_attr_flags|=A TTR_FLAG_APPEND;inode->i_flags|=S_APPEND;}if{inode->i_attr_flags|=A TTR_FLAG_IMMUTABLE; inode->i_flags|=S_IMMUTABLE;}if{inode->i_attr_flags|=A TTR_FLAG_NOA TIME; inode->i_flags|=S_NOATIME;}return;bad_inode:make_bad_inode;return;}这个函数的代码有200多行,为了突出重点,下面是对该函数主要内容的描述:如果指定的索引节点号是一个特殊的节点号,或者小于第一个非特殊用途的节点号,即EXT2_FIRST_INO ,或者大于该文件系统中索引节点总数,则输出错误信息,并返回;用索引节点号整除每组中索引节点数,计算出该索引节点所在的块组号;即block_group=/Ext2_INODES_PER_GROUP找到该组的组描述符在组描述符表中的位置.因为组描述符表可能占多个数据块,所以需要确定组描述符在组描述符表的哪一块以及是该块中第几个组描述符. 即:group_desc=block_group>>Ext2_DESC_PER_BLOCK_BITS表示块组号整除每块中组描述符数,计算出该组的组描述符在组描述符表中的哪一块.我们知道,每个组描述符是32字节大小,在一个1K大小的块中可存储32个组描述符.块组号与每块中组的描述符数进行”与”运算,得到这个组描述符具体是该块中第几个描述符.即desc=block_group&-1).有了group_desc和desc,接下来在高速缓存中找这个组描述符就比较容易了:即:bh=inode->i_sb->u.ext2_sb.s_group_desc[group_desc],首先通过s_group_desc[]数组找到这个组描述符所在块在高速缓存中的缓冲区首部;然后通过缓冲区首部找到数据区,即gdp=bh->b_data.找到组描述符后,就可以通过组描述符结构中的bg_inode_tabl找到索引节点表首块在高速缓存中的地址:offset=%Ext2_INODES_PER_GROUP)*Ext2_INODE_SIZE,计算该索引节点在块中的偏移位置;block=le32_to_cpu+),计算索引节点所在块的地址;代码中le32_to_cpu、le16_to_cpu按具体CPU的要求进行数据的排列,在i386处理器上访问Ext2文件系统时这些函数不做任何事情.因为不同的处理器在存取数据时在字节的排列次序上有所谓”bigending”和”littleending”之分.例如,i386就是”littleending”处理器,它在存储一个16位数据0x1234时,实际存储的却是0x3412,对32位数据也是如此.这里索引节点号与块的长度都作为32位或16位无符号整数存储在磁盘上,而同一磁盘既可以安装在采用”little ending”方式的CPU机器上,也可能安装在采用”big ending”方式的CPU机器上,所以要选择一种形式作为标准.事实上,Ext2采用的标准为”littleending”,所以,le32_to_cpu、le16_to_cpu函数不作任何转换.计算出索引节点所在块的地址后,就可以调用sb_bread通过设备驱动程序读入该块.从磁盘读入的索引节点为ext2_Inode数据结构,前面我们已经看到它的定义.磁盘上索引节点中的信息是原始的、未经加工的,所以代码中称之为raw_inode,即raw_inode=与磁盘索引节点ext2_inode相对照,内存中VFS的inode结构中的信息则分为两部分,一部分是属于VFS层的,适用于所有的文件系统;另一部份则属于具体的文件系统,这就是inode中的那个union,因具体文件系统的不同而赋予不同的解释.对Ext2来说,这部分数据就是前面介绍的ext2_inode_info结构.至于代表着符号链接的节点,则并没有文件内容,所以正好用这块空间来存储链接目标的路径名.ext2_inode_info结构的大小为60个字节.虽然节点名最长可达255个字节,但一般都不会太长,因此将符号链接目标的路径名限制在60个字节不至于引起问题.代码中inode->u.*设置的就是Ext2文件系统的特定信息.接着,根据索引节点所提供的信息设置inode结构中的inode_operations结构指针和file_operations结构指针,完成具体文件系统与虚拟文件系统VFS之间的连接.目前2.4版内核并不支持存取控制表ACL,因此,代码中只是为之留下了位置,而暂时没做任何处理.另外,通过检查inode结构中的mode域来确定该索引节点是常规文件、目录、符号链接还是其他特殊文件而作不同的设置或处理.例如,对Ext2文件系统的目录节点,就将i_op和i_fop分配设置为ext2_dir_inode_operations和ext2_dir_operations.而对于Ext2常规文件,则除i_op和i_fop以外,还设置了另一个指针a_ops,它指向一个address_apace_operation结构,用于文件到内存空间的映射或缓冲.对特殊文件,则通过init_special_inode函数加以检查和处理.从这个读索引节点的过程可以看出,首先要寻找指定的索引节点,要找索引节点,必须先找组描述符,然后通过组描述符找到索引节点表,最后才是在这个索引节点表中找索引节点.当从磁盘找到索引节点以后,就要把其读入内存,并存放在VFS索引节点相关的域中.从这个实例的分析,读者可以仔细体会前面所介绍的各种数据结构的具体应用.9.2.7Ext2的目录项及文件的定位文件系统一个很重要的问题就是文件的定位,如何通过一个路径来找到一个文件的具体位置,这就要依靠ext2_dir_entry这个结构.1.Ext2目录项结构在Ext2中,目录是一种特殊的文件,它是由ext2_dir_entry这个结构组成的列表.这个结构是变长的,这样可以减少磁盘空间的浪费,但是,它还是有一定的长度方面的限制,一是文件名最长只能为255个字符.二是尽管文件名长度可以不限,但系统自动将之变成4的整数倍,不足的地方用null字符填充.目录中有文件和子目录,每一项对应一个ext2_dir_entry.该结构在include/Linux/ext2_fs.h中定义如下:/**Structureofadirectoryentry*/#defineEXT2_NAME_LEN255structext2_dir_entry{__u32inode;Inodenumber*/__u16rec_len;Directoryentrylength*/__u16name_len;Namelength*/charname[EXT2_NAME_LEN]Filename*/};这是老版本的定义方式,在ext2_fs.h中还有一种新的定义方式:/**Thenewversionofthedirectory entry.SinceEXT2structures are*storedinintelbyteorder,andthename_lenfieldcouldneverbe*than255chars,it’ssafetoreclaimtheextrabyteforthe*file_typefield.*/structext2_dir_entry_2{__u32inode;Inode number*/__u16rec_len;Directorylength*/__u8name_len;Namelength*/__u8file_type;charname[EXT2_NAME_LEN]Filename*/};其二者的差异在于,一是新版中结构名改为ext2_dir_entry_2;二是老版本中ext2_dir_entry中的name_len为无符号短整数,而新版中则改为8位的无符号字符,腾出一半用作文件类型.目前已定义的文件类型为:**Ext2directorytypes.Onlythelow3bitsareused.The*otherbitsarereservedfornow.*/enum{EXT2_FT_UNKNOWN, /*未知*/EXT2_FT_REG_FILE,/*常规文件*/EXT2_FT_DIR,/*目录文件*/EXT2_FT_CHRDEV,/*字符设备文件*/EXT2_FT_BLKDEV,/*块设备文件*/EXT2_FT_FIFO,/*命名管道文件*/EXT2_FT_SOCK,/*套接字文件*/EXT2_FT_SYMLINK,/*符号连文件*/EXT2_FT_MAX/*文件类型的最大个数*/};2.各种文件类型如何使用数据块我们说,不管哪种类型的文件,每个文件都对应一个inode结构,在inode结构中有一个指向数据块的指针i_blaock,用来标识分配给文件的数据块.但是Ext2所定义的文件类型以不同的方式使用数据块.有些类型的文件不存放数据,因此,根本不需要数据块,下面对不同文件类型如何使用数据块给予说明.常规文件常规文件时最常用的文件.常规文件在刚创建时是空的,并不需要数据块,只有在开始有数据时才需要数据块;可以用系统调用truncate清空一个常规文件.目录文件Ext2以一种特殊的方式实现了目录,这种文件的数据块中存放的就是ext2_dir_entry_2结构.如前所述,这个结构的最后一个域是可变长度数组,因此该结构的长度是可变的.在ext2_dir_entry_2结构中,因为rec_len域是目录项的长度,把它与目录项的起始地址相加就得到下一个目录项的起始地址,因此说,rec_len可以被解释为指向下一个有效目录项的指针.为了删除一个目录项,把ext2_dir_entry_2的inode域置为0并适当增加前一个有效目录项rec_len域的值就可以了.符号连如果符号连的路径名小于60个字符,就把它存放在索引节点的i_blaock域,该域是由15个4字节整数组成的数组,因此无需数据块.但是,如果路径名大于60个字符,就需要一个单独的数据块.设备文件、管道和套接字这些类型的文件不需要数据块.所有必要的信息都存放在索引节点中.3.文件的定位文件的定位是一个复杂的过程,我们先看一个具体的例子,然后再结合上面的数据结构具体介绍一下如何找到一个目录项的过程.如果要找的文件为普通文件,则可通过文件所对应的索引节点找到文件的具体位置,如果是一个目录文件,则也可通过相应的索引节点找到目录文件具体所在,然后再从这个目录文件中进行下一步查找,来看一个具体的例子.假设路径为/home/user1/file1,home和user1是目录名,而file1为文件名.为了找到这个文件,有两种途径,一是从根目录开始查找,二是从当前目录开始查找.假设我们从根目录查找,则必须先找到根目录的节点,这个节点的位置在VFS中的超级块中已经给出,然后可找到根目录文件,其中必有home所对应的目录项,由此可先找到home节点,从而home的目录文件,然后依次是user1的节点和目录文件,最后,在该目录文件中的file1目录项中找到file1的节点,至此,已经可以找到file1文件的具体所在了.目录中还有两个特殊的子目录:”.”和”..”,分别代表当前目录和父目录.它们是无法被删除的,其作用就是用来进行相对路径的查找.现在,我们来分析一下fs/ext2/dir.c中的函数ext2_find_entry,该函数从磁盘上找到并读入当前节点的目录项,其代码及解释如下:/**ext2_find_entry**findsanentryinthespecifieddirectorywiththewantedname.It* returns the pagein which the entry was found, andthe entry itself*.Pageis returned mapped andunlocked.*Entryisguaranteedtobevalid.*/typedefstructext2_dir_entry_2ext2_dirent; structext2_dir_entry_2*ext2_find_entry{constchar*name=dentry->d_;/*目录项名*/intnamelen=dentry->d_name.len;/*目录项名的长度*/ unsignedreclen=EXT2_DIR_REC_LEN;/*目录项的长度*/ unsignedlongstart,n;unsignedlongnpages=dir_pages;/*把以字节为单位的文件大小转换为物理页面数*/。
EXT2文件系统
EXT2⽂件系统对⽂件系统⽽⾔,⽂件仅是⼀系列可读写的数据块。
⽂件系统并不需要了解数据块应该放到物理介质上什么位置。
这些都是设备驱动的任务。
⽆论何时,只要⽂件系统需要从包含它的块设备中读取信息或数据,它就将请求底层的设备驱动读取⼀个基本块⼤⼩整数倍的数据块。
EXT2⽂件系统将它所使⽤的逻辑分区划分成数据块组。
每个数据块组都将那些对⽂件系统完整性最重要的信息复制出来,同时将实际⽂件盒⽬录看做信息与数据块。
罗即⽂件系统管理的是⼀个逻辑空间,这个逻辑空间就像⼀个⼤的数组,数组的每个元素就是⽂件系统操作的基本单位——逻辑块。
逻辑块是从0开始编号的,⽽且,逻辑块是连续的,逻辑块相对的是物理块。
通常,EXT2的物理块占⼀个或⼏个连续的扇区。
⼀般⽽⾔,只有块组0的超级块才读⼊内存,其他块组的超级块仅仅作为备份。
在系统运⾏期间,要将超级块复制到内存系统缓冲区。
块位图和节点位图在EXT2⽂件系统中,采⽤位图描述数据块和索引节点的使⽤情况,每个块组中占⽤两个块,即⼀个⽤来描述该数据块的使⽤情况,另⼀个描述该组索引节点的使⽤情况。
这两个块分别称为数据位图块和索引节点位图块。
数据位图块中的每⼀位表⽰该块组中的每⼀个块的使⽤情况,如果为0,则表⽰相应数据块空闲,如果是1,则表⽰已分配。
索引节点表每个块组中的索引节点都存储在各⾃的索引节点表中,并且按索引节点号依次存储。
索引节点表通常占好⼏个数据块,索引节点表所占的块使⽤时也想普通的数据块⼀样被调⼊块⾼速缓存。
EXT2整个磁盘的逻辑结构如图所⽰:EXT2⽂件系统的⼏个数据结构1 EXT2超级块超级块中包含了描述⽂件系统基本尺⼨和形态的信息。
⽂件系统管理器利⽤他们来使⽤和维护⽂件系统。
EXT2超级块是⽤来描述EXT2⽂件系统整体信息的数据结构,是EXT2的核⼼所在。
超级块经函数ext2_fill_supter读⼊后,⼜在内存中建⽴⼀个映像super_block.u.ext2_sb_info结构。
Linux分区类型EXT2、EXT3、EXT4详解
Linux分区类型EXT2、EXT3、EXT4详解⼀、EXT2与EXT3Linux之前缺省情况下使⽤的⽂件系统为Ext2,ext2⽂件系统的确⾼效稳定。
但是,随着Linux系统在关键业务中的应⽤,Linux⽂件系统的弱点也渐渐显露出来了:其中系统缺省使⽤的ext2⽂件系统是⾮⽇志⽂件系统。
这在关键⾏业的应⽤是⼀个致命的弱点.Ext3⽂件系统是直接从Ext2⽂件系统发展⽽来,⽬前ext3⽂件系统已经⾮常稳定可靠。
它完全兼容ext2⽂件系统。
⽤户可以平滑地过渡到⼀个⽇志功能健全的⽂件系统中来。
这实际上了也是ext3⽇志⽂件系统初始设计的初衷。
⼆、EXT3⽇志⽂件系统的特点1、⾼可⽤性系统使⽤了ext3⽂件系统后,即使在⾮正常关机后,系统也不需要检查⽂件系统。
宕机发⽣后,恢复ext3⽂件系统的时间只要数⼗秒钟。
2、数据的完整性ext3⽂件系统能够极⼤地提⾼⽂件系统的完整性,避免了意外宕机对⽂件系统的破坏。
在保证数据完整性⽅⾯,ext3⽂件系统有2种模式可供选择。
其中之⼀就是“同时保持⽂件系统及数据的⼀致性”模式。
采⽤这种⽅式,你永远不再会看到由于⾮正常关机⽽存储在磁盘上的垃圾⽂件。
3、⽂件系统的速度尽管使⽤ext3⽂件系统时,有时在存储数据时可能要多次写数据,但是,从总体上看来,ext3⽐ext2的性能还要好⼀些。
这是因为ext3的⽇志功能对磁盘的驱动器读写头进⾏了优化。
所以,⽂件系统的读写性能较之Ext2⽂件系统并来说,性能并没有降低。
4、数据转换由ext2⽂件系统转换成ext3⽂件系统⾮常容易,只要简单地键⼊两条命令即可完成整个转换过程,⽤户不⽤花时间备份、恢复、格式化分区等。
⽤⼀个ext3⽂件系统提供的⼩⼯具tune2fs,它可以将ext2⽂件系统轻松转换为ext3⽇志⽂件系统。
另外,ext3⽂件系统可以不经任何更改,⽽直接加载成为ext2⽂件系统。
5、多种⽇志模式Ext3有多种⽇志模式,⼀种⼯作模式是对所有的⽂件数据及metadata(定义⽂件系统中数据的数据,即数据的数据)进⾏⽇志记录(data=journal模式);另⼀种⼯作模式则是只对metadata记录⽇志,⽽不对数据进⾏⽇志记录,也即所谓data=ordered或data=writeback模式。
利用Ext2文件系统的硬盘布局信息收集电子证据
区 中数 据块 个数 ( lc o n)分 区 中索引节 点 个 Bokcu t 、 数 (nd o n) 每 个块 组 数 据块 个 数 ( l k e Io ecu t, Bo s r c p gop 、 每 个 块 组 索 引 节 点 个 数 ru ) ( o e e I d sp r n
磁
、 主
妻季 芰 嚣
蔷
21 x2文件 系统的硬盘布局方式 . E t
E t 件 系统 中硬盘 分 区被划 分为 若干 个数 x 2文
建时, 系统便 根据 索引 节点 位 图 , 为其 分配 一个 未
被 使用 的索 引节 点 ,并 在 其 中填 入描 述新 文件 属
据 块 ( 称 bok ,每个 数据 块 由若 干物 理块 组 也 l ) c
性 的详 细信 息 ,同时 根据 数 据块 位 图 为其分 配 空
1 警 察 技 术 2 0 / 4 064
维普资讯
计 鼻 机 取 证 技 术 研 冤
闲数 据块 以存 放 真正 的文 件 内容 ;而 当有 文件 被 彻 底删 除 时 , 系统便 回收 其索 引节 点 , 并将 该 文件 所 占有 的数据 块 的状态 由已分配 修 改 为空 闲 。为 此 , x2还需 要 索 引 节 点 表 ( o eT be 这 样 的 Et I d a l) n 结 构 来 集 中存 放块 组 中所 有 文件 的索 引 节点 , 达 到统一 管理 文件 属性 提高 系统 效率 的 目的 。用户 要 求查 看 文件属 性 时 ,系统通 过 检索 索 引节 点表 便能满 足用户需 求 ;而 当用 户想 要 查看 文件 内容 时 ,系统 便根 据该 文件 索 引节 点 中包含 的数 据 块 信 息 ,在磁 盘上 找到相 应 的数据 块 显示 其存 放 的 内容 即可 。 另外 , x Et 2文件 系统还 在每 个块 组 中包 含 文件 系统 关键 部分 的副 本 ,也就 是 超级 块 和块 组描 述表 的副 本 , 以便 于原块 破坏 时再 恢复 。 x Et 2 文件 系统 硬盘 布局 结构 如 图 1 示 。通 过 图 1可 所 本—— 目标磁 盘介 质 挂载 到本 地 磁盘 的指 定 目录 文件下之 后 ,即可使用 d m e f 命令 显示 目标磁 u p 2s 盘介质 的超级块与块组 描述表信 息 ( 图 2 示 ) 如 所 。 d m ef 命 令用 于 显示 文件 系统 信息 ,其 显 u p 2s 示 内容 来 自于 超 级 块
ext文件系统原理
ext文件系统原理
EXT文件系统是Linux操作系统中使用最广泛的文件系统之一,它的设计目标是提供一种高度可靠、快速、灵活的文件系统。
EXT文件系统基于磁盘分区的结构,将硬盘空间划分为一个
个的块(block),每个块的大小通常为4KB或8KB。
文件被
分成许多块并存储在磁盘上,每个块都有一个唯一的块号。
EXT文件系统在组织磁盘空间时采用了一种树型结构,称为inode结构。
每个文件或目录都分配有一个inode,其中记录了文件或目录的相关信息(例如,所属用户、所属组、存储位置等)。
在文件系统中,所有的文件和目录都按照树形结构组织,并以根节点为起点,可以由父节点指向其子节点,而每个子节点同样也可以成为父节点,指向它的子节点。
这样,树形结构就能表达出文件和目录之间的层次关系。
EXT文件系统采用的是分离目录和文件数据的存储策略,即
文件数据和目录数据储存在不同的区域,这一策略有利于提高文件系统性能。
同时,EXT文件系统使用了全局帮助位图(Global Bitmap)的数据结构,用于标识哪些块是可用的,哪些是已经使用的块。
这种帮助位图能够将已分配的块与未分配的块区分开来,并且能够快速识别空闲块。
总之,EXT文件系统是一种高效、可靠、灵活的文件系统,
相对于其他文件系统来说有更好的性能和可靠性,适用于处理大量的小文件和大文件,被广泛应用于Linux操作系统和其他Unix操作系统中。
ext2读取文件原理
ext2读取文件原理以ext2读取文件原理为题,本文将介绍ext2文件系统是如何读取文件的。
ext2是一种常用的Linux文件系统,被广泛应用于Linux 操作系统中。
我们需要了解一下ext2文件系统的基本结构。
ext2文件系统将存储设备划分为多个块组,每个块组都包含了若干个数据块和一些元数据。
元数据包括了超级块、块位图、inode位图和inode表等。
超级块记录了整个文件系统的重要信息,如块大小、块组大小、inode数量等。
块位图用于记录数据块的使用情况,而inode位图则用于记录inode的使用情况。
inode表中存储了每个文件的元数据信息,如文件类型、权限、大小、访问时间等。
每个文件和目录都对应一个inode。
当我们要读取一个文件时,首先需要找到该文件所在的inode。
我们可以通过目录来查找文件的inode。
每个目录都包含了一系列的目录项,每个目录项都对应一个文件或子目录。
目录项中记录了文件名和对应的inode号,通过遍历目录项,我们可以找到目标文件的inode。
找到目标文件的inode之后,我们就可以通过inode中的数据块指针来读取文件的内容。
ext2文件系统中的文件数据块被组织成一棵多级索引的树状结构。
inode中的数据块指针包括了直接块指针、一级间接块指针、二级间接块指针和三级间接块指针。
直接块指针直接指向文件的数据块,而间接块指针则指向一级、二级或三级块。
通过多级间接块指针的组合,我们可以寻址到任意数据块。
在读取文件时,我们首先通过直接块指针读取文件的直接数据块。
如果文件的大小超过了直接块的容量,那么我们需要通过一级间接块指针来读取更多的数据块。
一级间接块中存储了多个二级块的地址,通过二级间接块指针,我们可以读取更多的数据块。
同样地,如果文件的大小超过了一级间接块的容量,我们就需要通过二级间接块指针来读取更多的数据块。
二级间接块中存储了多个三级块的地址,通过三级间接块指针,我们可以再次读取更多的数据块。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Ext2数据块分配跟索引节点一样,Ext2也对磁盘数据块进行分配与释放。
在详细分析相关代码之前,先引出两个重要的预备,一个是数据块寻址,一个是文件的洞1 数据块寻址每个非空的普通文件都由一组数据块组成。
这些块或者由文件内的相对位置(它们的文件块号)来标识,或者由磁盘分区内的位置(它们的逻辑块号)来标识。
从文件内的偏移量f 导出相应数据块的逻辑块号需要两个步骤:1. 从偏移量f导出文件的块号,即在偏移量f处的字符所在的块索引。
2. 把文件的块号转化为相应的逻辑块号。
因为Unix文件不包含任何控制字符,因此,导出文件的第f 个字符所在的文件块号当容易的,只是用f除以文件系统块的大小,并取整即可。
例如,让我们假定块的大小为4KB。
如果f小于4096,那么这个字符就在文件的第一数据块中,其文件的块号为O。
如果f等于或大于4096而小于8192,则这个字符就在文件块号为1的数据块中,以此类推。
得到了文件的块号是第一步。
但是,由于Ext2文件的数据块在磁盘上不必是相邻的,因此把文件的块号转化为相应的逻辑块号可不是这么直截了当的了。
因此,Ext2文件系统必须提供一种方法,用这种方法可以在磁盘上建立每个文件块号与相应逻辑块号之间的关系。
在索引节点内部部分实现了这种映射(回到了AT&T Unix的早期版本)。
这种映射也涉及一些包含额外指针的专用块,这些块用来处理大型文件的索引节点的扩展。
ext2磁盘索引节点ext2_inode的i_block字段是一个有EXT2_N_BLOCKS个元素且包含逻辑块号的数组。
在下面的讨论中,我们假定EXT2_N_BLOCKS的默认值为15(实际上到2.6.18这个值都一直是15)。
如图所示,这个数组表示一个大型数据结构的初始化部分。
正如从图中所看到的,数组的15个元素有4种不同的类型:- 最初的12个元素产生的逻辑块号与文件最初的12个块对应,即对应的文件块号从0 - 11。
- 下标12中的元素包含一个块的逻辑块号(叫做间接块),这个块中存放着一个表示逻辑块号的二级数组。
这个数组的元素对应的文件块号从12 到b/4+11,这里b是文件系统的块大小(每个逻辑块号占4个字节,因此我们在式子中用4作除数,如果块大小是4096,则该数组对应文件块号从12到1035)。
因此,内核为了查找指向一个块的指针必须先访问这个元素,然后,在这个块中找到另一个指向最终块(包含文件内容)的指针。
-下标13中的元素包含一个间接块的逻辑块号,而这个块包含逻辑块号的一个二级数组,这个二级数组的数组项依次指向三级数组,这个三级数组存放的才是文件块号对应的逻辑块号,范围从b/4+12到(b/4)^2+(b/4)+11。
如果块大小是4096,则范围是从1036到1049611。
- 最后,下标14中的元素使用三级间接索引,第四级数组中存放的才是文件块号对应的逻辑块号,范围从(b/4)^2+(b/4)+12到(b/4)^3+(b/4)^2+(b/4)+11。
在图中,块内的数字表示相应的文件块号。
箭头(表示存放在数组元素中的逻辑块号)指示了内核如何通过间接块找到包含文件实际内容的块。
注意这种机制是如何支持小文件的。
如果文件需要的数据块小于12,那么两次磁盘访问就可以检索到任何数据:一次是读磁盘索引节点i_block数组的一个元素,另一次是读所需要的数据块。
对于大文件来说,可能需要三四次的磁盘访问才能找到需要的块。
实际上,这是一种最坏的估计,因为目录项、索引节点、页高速缓存都有助于极大地减少实际访问磁盘的次数。
还要注意文件系统的块大小是如何影响寻址机制的,因为大的块允许Ext2把更多的逻辑块号存放在一个单独的块中。
例如,如果块的大小是1024字节,并且文件包含的数据最多为268KB,那么,通过直接映射可以访问文件最初的12KB数据,通过简单的间接映射可以访问剩的13KB到268KB的数据。
大于2GB的大型文件通过指定O_LARGEFILE打开标志必须在32位体系结构上进行打开。
2 文件的洞文件的洞(file hole)是普通文件的一部分,它是一些空字符但没有存放在磁盘的任何数据块中。
洞是Unix文件一直存在的一个特点。
例如,下列的Unix命令创建了第一个字节是洞的文件:[root@localhost]# echo -n "X" | dd of=/tmp/hole bs=1024 seek=6现在,/tmp/hole有6145个字符(6144个空字符加一个X 字符),然而,这个文件在磁盘上只占一个数据块。
引人文件的洞是为了避免磁盘空间的浪费。
它们因此被广泛地用在数据库应用中,更一般地说,用于在文件上进行散列的所有应用。
文件洞在Ext2中的实现是基于动态数据块的分配的:只有当进程需要向一个块写数据时,才真正把这个块分配给文件。
每个索引节点的i_size字段定义程序所看到的文件大小,包括洞,而i_blocks字段存放分配给文件有效的数据块数(以512字节为单位)。
在前面dd命令的例子中,假定/tmp/hole文件创建在块大小为4096的Ext2分区上。
其相应磁盘索引节点的i_size字段存放的数为6145,而i_blocks字段存放的数为8(因为每4096字节的逻辑块包含8个512字节的物理块)。
i_block数组的第二个元素(对应块的文件块号为1)存放已分配块的逻辑块号,而数组中的其他元素都为空(参看下图)。
3 分配数据块当内核要分配一个数据块来保存Ext2普通文件的数据时,就调用ext2_get_block()函数。
如果块不存在,该函数就自动为文件分配块。
请记住,每当内核在Ext2普通文件上执行读或写操作时就调用这个函数;显然,这个函数只在页高速缓存内没有相应的块时才被调用。
ext2_get_block()函数处理在刚才“数据块寻址”描述的数据结构,并在必要时调用ext2_alloc_block()函数在Ext2分区真正搜索一个空闲块。
如果需要,该函数还为间接寻址分配相应的块(参见本篇博文第一个图)。
为了减少文件的碎片,Ext2文件系统尽力在已分配给文件的最后一个块附近找一个新块分配给该文件。
如果失败,Ext2文件系统又在包含这个文件索引节点的块组中搜寻一个新的块。
如果还是失败,作为最后一个办法,可以从其他一个块组中获得空闲块。
Ext2文件系统使用数据块的预分配策略。
文件并不仅仅获得所需要的块,而是获得一组多达8个邻接的块。
ext2_inode_info结构的i_prealloc_count字段存放预分配给某一文件但还没有使用的数据块的数量,而i_prealloc_block字段存放下一次要使用的预分配块的逻辑块号。
当下列情况发生时,释放预分配而一直没有使用的块:当文件被关闭时,当文件被缩短时,或者当一个写操作相对于引发块预分配的写操作不是顺序的时。
ext2_alloc_block()函数接收的参数为指向索引节点对象的指针、目标(goal)和存放错误码的变量地址。
目标是一个逻辑块号,表示新块的首选位置:static unsigned long ext2_alloc_block (struct inode * inode, unsigned long goal, int *err){#ifdef EXT2FS_DEBUGstatic unsigned long alloc_hits, alloc_attempts;#endifunsigned long result;#ifdef EXT2_PREALLOCATEstruct ext2_inode_info *ei = EXT2_I(inode);write_lock(&ei->i_meta_lock);if (ei->i_prealloc_count &&(goal == ei->i_prealloc_block || goal + 1 == ei->i_prealloc_block)){result = ei->i_prealloc_block++;ei->i_prealloc_count--;write_unlock(&ei->i_meta_lock);ext2_debug ("preallocation hit (%lu/%lu)./n",++alloc_hits, ++alloc_attempts);} else {write_unlock(&ei->i_meta_lock);ext2_discard_prealloc (inode);ext2_debug ("preallocation miss(%lu/%lu)./n",alloc_hits, ++alloc_attempts);if (S_ISREG(inode->i_mode)) /* 如果是普通文件*/result = ext2_new_block (inode, goal,&ei->i_prealloc_count,&ei->i_prealloc_block, err);else /* 如果是目录或符号链接*/result = ext2_new_block(inode, goal, NULL, NULL, err);}#elseresult = ext2_new_block (inode, goal, 0, 0, err);#endifreturn result;}代码很容易看懂,如果先前有预分配,则直接返回ei->i_prealloc_block++,没有,则丢弃所有剩余的预分配块ext2_discard_prealloc(inode),并调用ext2_new_block 函数分配一个块:unsigned long ext2_new_block(struct inode *inode, unsigned long goal,u32 *prealloc_count, u32*prealloc_block, int *err){struct buffer_head *bitmap_bh = NULL;struct buffer_head *gdp_bh; /* bh2 */struct ext2_group_desc *desc;int group_no; /* i */int ret_block; /* j */int group_idx; /* k */unsigned long target_block; /* tmp */unsigned long block = 0;struct super_block *sb = inode->i_sb;struct ext2_sb_info *sbi = EXT2_SB(sb);struct ext2_super_block *es = sbi->s_es;unsigned group_size =EXT2_BLOCKS_PER_GROUP(sb);unsigned prealloc_goal = es->s_prealloc_blocks;unsigned group_alloc = 0, es_alloc, dq_alloc;int nr_scanned_groups;if (!prealloc_goal--)prealloc_goal =EXT2_DEFAULT_PREALLOC_BLOCKS - 1;if (!prealloc_count || *prealloc_count)prealloc_goal = 0;if (DQUOT_ALLOC_BLOCK(inode, 1)) {*err = -EDQUOT;goto out;}while (prealloc_goal &&DQUOT_PREALLOC_BLOCK(inode, prealloc_goal))prealloc_goal--;dq_alloc = prealloc_goal + 1;es_alloc = reserve_blocks(sb, dq_alloc);if (!es_alloc) {*err = -ENOSPC;goto out_dquot;}ext2_debug ("goal=%lu./n", goal);if (goal < le32_to_cpu(es->s_first_data_block) || goal >=le32_to_cpu(es->s_blocks_count))goal =le32_to_cpu(es->s_first_data_block);group_no = (goal -le32_to_cpu(es->s_first_data_block)) / group_size;desc = ext2_get_group_desc (sb, group_no,&gdp_bh);if (!desc) {/** gdp_bh may still be uninitialised. But group_release_blocks* will not touch it because group_alloc is zero.*/goto io_error;}group_alloc = group_reserve_blocks(sbi, group_no, desc,gdp_bh, es_alloc);if (group_alloc) {ret_block = ((goal -le32_to_cpu(es->s_first_data_block)) %group_size);brelse(bitmap_bh);bitmap_bh = read_block_bitmap(sb,group_no);if (!bitmap_bh)goto io_error;ext2_debug("goal is at %d:%d./n", group_no, ret_block);ret_block = grab_block(sb_bgl_lock(sbi, group_no),bitmap_bh->b_data,group_size, ret_block);if (ret_block >= 0)goto got_block;group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc);group_alloc = 0;}ext2_debug ("Bit not found in block group %d./n", group_no);/** Now search the rest of the groups. We assume that* i and desc correctly point to the last group visited.*/nr_scanned_groups = 0;retry:for (group_idx = 0; !group_alloc &&group_idx < sbi->s_groups_count; group_idx++) {group_no++;if (group_no >= sbi->s_groups_count)group_no = 0;desc = ext2_get_group_desc(sb, group_no,&gdp_bh);if (!desc)goto io_error;group_alloc = group_reserve_blocks(sbi, group_no, desc,gdp_bh,es_alloc);}if (!group_alloc) {*err = -ENOSPC;goto out_release;}brelse(bitmap_bh);bitmap_bh = read_block_bitmap(sb, group_no);if (!bitmap_bh)goto io_error;ret_block = grab_block(sb_bgl_lock(sbi, group_no), bitmap_bh->b_data,group_size, 0);if (ret_block < 0) {/** If a free block counter is corrupted we canloop inifintely.* Detect that here.*/nr_scanned_groups++;if (nr_scanned_groups > 2 *sbi->s_groups_count) {ext2_error(sb, "ext2_new_block","corrupted free blocks counters");goto io_error;}/** Someone else grabbed the last free block in this blockgroup* before us. Retry the scan.*/group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc);group_alloc = 0;goto retry;}got_block:ext2_debug("using block group %d(%d)/n",group_no, desc->bg_free_blocks_count);target_block = ret_block + group_no * group_size +le32_to_cpu(es->s_first_data_block);if (target_block ==le32_to_cpu(desc->bg_block_bitmap) ||target_block ==le32_to_cpu(desc->bg_inode_bitmap) ||in_range(target_block,le32_to_cpu(desc->bg_inode_table),sbi->s_itb_per_group))ext2_error (sb, "ext2_new_block","Allocating block in system zone - ""block = %lu", target_block);if (target_block >=le32_to_cpu(es->s_blocks_count)) {ext2_error (sb, "ext2_new_block","block(%d) >= blockscount(%d) - ""block_group = %d, es == %p ",ret_block,le32_to_cpu(es->s_blocks_count), group_no, es);goto io_error;}block = target_block;/* OK, we _had_ allocated something */ext2_debug("found bit %d/n", ret_block);dq_alloc--;es_alloc--;group_alloc--;/** Do block preallocation now if required.*/write_lock(&EXT2_I(inode)->i_meta_lock);if (group_alloc && !*prealloc_count) {unsigned n;for (n = 0; n < group_alloc &&++ret_block < group_size; n++) {if (ext2_set_bit_atomic(sb_bgl_lock(sbi, group_no),ret_block,(void*)bitmap_bh->b_data))break;}*prealloc_block = block + 1;*prealloc_count = n;es_alloc -= n;dq_alloc -= n;group_alloc -= n;}write_unlock(&EXT2_I(inode)->i_meta_lock);mark_buffer_dirty(bitmap_bh);if (sb->s_flags & MS_SYNCHRONOUS)sync_dirty_buffer(bitmap_bh);ext2_debug ("allocating block %d. ", block);*err = 0;out_release:group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc);release_blocks(sb, es_alloc);out_dquot:DQUOT_FREE_BLOCK(inode, dq_alloc);out:brelse(bitmap_bh);return block;io_error:*err = -EIO;goto out_release;}ext2_new_block()函数用下列策略在Ext2分区内搜寻一个空闲块:1. 如果传递给ext2_alloc_block()的首选块(目标块)是空闲的,就分配它。