Ext2数据块分配

合集下载

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文件系统的区别与转换

Linux系统ext2与ext3文件系统的区别与转换
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文件系统

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参数

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详解

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  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文件系统分析

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分区格式说明

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常见的分区格式,不同的分区格式具有不同的特点和应用场景。

在实际使用中,可以根据需求选择合适的分区格式。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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&amp;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(&amp;ei-&gt;i_meta_lock);if (ei-&gt;i_prealloc_count &amp;&amp;(goal == ei-&gt;i_prealloc_block || goal + 1 == ei-&gt;i_prealloc_block)){result = ei-&gt;i_prealloc_block++;ei-&gt;i_prealloc_count--;write_unlock(&amp;ei-&gt;i_meta_lock);ext2_debug ("preallocation hit (%lu/%lu)./n",++alloc_hits, ++alloc_attempts);} else {write_unlock(&amp;ei-&gt;i_meta_lock);ext2_discard_prealloc (inode);ext2_debug ("preallocation miss(%lu/%lu)./n",alloc_hits, ++alloc_attempts);if (S_ISREG(inode-&gt;i_mode)) /* 如果是普通文件*/result = ext2_new_block (inode, goal,&amp;ei-&gt;i_prealloc_count,&amp;ei-&gt;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-&gt;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-&gt;i_sb;struct ext2_sb_info *sbi = EXT2_SB(sb);struct ext2_super_block *es = sbi-&gt;s_es;unsigned group_size =EXT2_BLOCKS_PER_GROUP(sb);unsigned prealloc_goal = es-&gt;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 &amp;&amp;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 &lt; le32_to_cpu(es-&gt;s_first_data_block) || goal &gt;=le32_to_cpu(es-&gt;s_blocks_count))goal =le32_to_cpu(es-&gt;s_first_data_block);group_no = (goal -le32_to_cpu(es-&gt;s_first_data_block)) / group_size;desc = ext2_get_group_desc (sb, group_no,&amp;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-&gt;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-&gt;b_data,group_size, ret_block);if (ret_block &gt;= 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 &amp;&amp;group_idx &lt; sbi-&gt;s_groups_count; group_idx++) {group_no++;if (group_no &gt;= sbi-&gt;s_groups_count)group_no = 0;desc = ext2_get_group_desc(sb, group_no,&amp;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-&gt;b_data,group_size, 0);if (ret_block &lt; 0) {/** If a free block counter is corrupted we canloop inifintely.* Detect that here.*/nr_scanned_groups++;if (nr_scanned_groups &gt; 2 *sbi-&gt;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-&gt;bg_free_blocks_count);target_block = ret_block + group_no * group_size +le32_to_cpu(es-&gt;s_first_data_block);if (target_block ==le32_to_cpu(desc-&gt;bg_block_bitmap) ||target_block ==le32_to_cpu(desc-&gt;bg_inode_bitmap) ||in_range(target_block,le32_to_cpu(desc-&gt;bg_inode_table),sbi-&gt;s_itb_per_group))ext2_error (sb, "ext2_new_block","Allocating block in system zone - ""block = %lu", target_block);if (target_block &gt;=le32_to_cpu(es-&gt;s_blocks_count)) {ext2_error (sb, "ext2_new_block","block(%d) &gt;= blockscount(%d) - ""block_group = %d, es == %p ",ret_block,le32_to_cpu(es-&gt;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(&amp;EXT2_I(inode)-&gt;i_meta_lock);if (group_alloc &amp;&amp; !*prealloc_count) {unsigned n;for (n = 0; n &lt; group_alloc &amp;&amp;++ret_block &lt; group_size; n++) {if (ext2_set_bit_atomic(sb_bgl_lock(sbi, group_no),ret_block,(void*)bitmap_bh-&gt;b_data))break;}*prealloc_block = block + 1;*prealloc_count = n;es_alloc -= n;dq_alloc -= n;group_alloc -= n;}write_unlock(&amp;EXT2_I(inode)-&gt;i_meta_lock);mark_buffer_dirty(bitmap_bh);if (sb-&gt;s_flags &amp; 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()的首选块(目标块)是空闲的,就分配它。

相关文档
最新文档