《存储技术原理分析 基于Linux 2.6内核源代码》PDF下载

  • 购买积分:21 如何计算积分?
  • 作  者:敖青云著
  • 出 版 社:北京:电子工业出版社
  • 出版年份:2011
  • ISBN:9787121144325
  • 页数:769 页
图书介绍:本书通过对Linux 2.6内核源代码的分析,详细讨论存储技术的内在实现原理。分为三条主线:解释PCI设备、SCSI设备以及块设备的发现过程;跟踪存储I/O路径,即用户对文件的读/写请求怎么通过中间各个层次,最终到达磁盘介质;此外,还简要介绍主机适配器、块设备驱动以及文件系统等编程框架。书中将设计一些主要的场景,跟踪实现的各个层次,对其中的主要函数进行代码级的讲解。在分析每个模块时,会给出整体框架、主要数据结构之间的关系,并列出各个域的详细含义。

第一部分 存储技术第1章 存储技术概论 2

1.1 存储系统元素 2

1.1.1 磁盘驱动器 2

1.1.2 存储设备 4

1.1.3 服务器部件 7

1.1.4 存储软件 9

1.2 存储相关技术 10

1.2.1 备份技术 10

1.2.2 快照技术 13

1.2.3 连续数据保护技术 21

1.2.4 RAID技术 22

1.2.5 “多路径”技术 36

1.2.6 虚拟化技术 39

1.3 网络存储结构 40

1.3.1 直接连接存储 40

1.3.2 网络连接存储 40

1.3.3 存储区域网络 41

1.4 存储I/O通道 41

1.4.1 存储I/O物理通道 42

1.4.2 存储I/O逻辑通道 43

1.4.3 虚拟机I/O逻辑通道 44

1.5 存储应用举例 45

1.5.1 同时提供文件服务和块服务 45

1.5.2 按需扩容、随需取用延缓企业投资 45

1.5.3 计算与存储分离便于故障恢复和系统升级 45

1.5.4 为高可用性集群提供共享存储 46

1.5.5 利用快照技术恢复被病毒破坏的数据 47

1.5.6 基于文件的数据备份和远程镜像方案 47

1.5.7 利用PXE和iSCSI实现远程引导和映像恢复 48

1.5.8 虚拟机故障的检测及迁移 49

第二部分 设备 52

第2章 Linux驱动模型 52

2.1 概述 52

2.2 引用计数 53

2.3 内核对象及集合 55

2.3.1 创建或初始化内核对象 58

2.3.2 将内核对象添加到sysfs文件系统 59

2.3.3 创建、初始化、添加内核对象集 63

2.3.4 发送内核对象变化事件到用户空间 63

2.4 sysfs文件系统 69

2.4.1 构建内核对象、对象属性和对象关系的内部树 70

2.4.2 对sysfs文件的读/写转换为对属性的show和store操作 73

2.4.3 为具体内核对象定义属性的规范流程 77

2.5 kobiect编程模式 80

2.6 驱动模型对象 81

2.6.1 总线类型 82

2.6.2 设备 86

2.6.3 驱动 100

2.6.4 类 105

2.6.5 接口 107

2.7 驱动模型编程模式 108

第3章 PCI子系统 110

3.1 概述 110

3.2 PCI子系统对象 115

3.2.1 pci_bus:PCI总线 116

3.2.2 pci_dev:PCI设备 117

3.3 PCI核心初始化 121

3.4 配置访问方法 124

3.4.1 机制#1方式 126

3.4.2 PCIBIOS方式 128

3.4.3 配置访问接口 133

3.5 PCI总线扫描 133

3.5.1 PCI总线编号范例 133

3.5.2 PCI总线扫描流程 137

3.6 PCI中断路由 160

3.6.1 中断路由初始化 165

3.6.2 查找中断路由表 166

3.6.3 查找中断路由驱动 167

3.6.4 分配ISA IRQ号 171

3.7 PCI资源分配 177

3.7.1 PCI资源分配范例 178

3.7.2 PCI资源分配流程 181

3.8 PCI设备驱动编程模式 193

3.8.1 定义PCI驱动结构 194

3.8.2 定义支持设备ID列表 194

3.8.3 实现probe回调方法 196

3.8.4 实现remove回调方法 198

3.8.5 实现其他回调方法 199

3.8.6 注册与注销PCI驱动 199

第4章 SCSI子系统 201

4.1 概述 201

4.2 SCSI子系统对象 202

4.2.1 scsi_host_template:SCSI主机适配器模板 203

4.2.2 Scsi_Host:SCSI主机适配器 207

4.2.3 scsi_target:SCSI目标节点 210

4.2.4 scsi_device:SCSI逻辑设备 211

4.2.5 scsi_cmnd:SCSI命令 215

4.3 SCSI子系统初始化 216

4.4 添加适配器到系统 216

4.5 SCSI设备探测 222

4.5.1 探测流程入口 224

4.5.2 探测逻辑单元 232

4.5.3 添加SCSI设备 237

4.6 SCSI磁盘驱动 241

4.6.1 同步执行部分 244

4.6.2 异步执行部分 247

4.6.3 重新校验磁盘 249

4.6.4 让磁盘转起来 251

4.7 SCSI命令执行 254

4.8 SCSI错误恢复 259

4.8.1 命令进入错误恢复 261

4.8.2 错误恢复线程执行 262

4.8.3 发送错误恢复命令 275

4.9 SCSI低层驱动编程模式 279

4.9.1 定义主机适配器模板 279

4.9.2 完善探测回调处理逻辑 279

4.9.3 实现queuecommand回调函数 279

4.9.4 实现中断处理函数 283

4.9.5 实现其他回调函数 283

4.9.6 模块加载和卸载 283

第三部分 存储I/O 286

第5章 块I/O子系统 286

5.1 概述 286

5.2 块I/O子系统对象 287

5.2.1 gendisk:通用磁盘 289

5.2.2 hd_struct:分区 291

5.2.3 block_device:块设备 292

5.2.4 request_queue:请求队列 293

5.2.5 request:块设备驱动层请求 296

5.2.6 bio:通用块层请求 298

5.3 添加磁盘到系统 300

5.3.1 分配通用磁盘描述符 300

5.3.2 添加到sysfs文件系统 302

5.3.3 获取磁盘块设备描述符 305

5.3.4 打开磁盘块设备描述符 306

5.3.5 重新扫描磁盘分区 310

5.3.6 设备号映射机制 314

5.4 请求处理过程 315

5.4.1 上层向块I/O子系统提交请求 315

5.4.2 构造、排序或合并请求 320

5.4.3 SCSI策略例程逐个处理请求 327

5.4.4 为请求构造SCSI命令 334

5.4.5 为SCSI命令准备聚散列表 343

5.4.6 派发SCSI命令到低层驱动 349

5.5 I/O调度算法 352

5.5.1 为请求队列建立关联的I/O调度队列 356

5.5.2 判断bio是否可以被合并到request 356

5.5.3 将请求添加到I/O调度队列或请求队列 359

5.5.4 从I/O调度队列派发请求到请求队列 362

5.6 请求处理完成 366

5.6.1 低层驱动调用完成回调函数 366

5.6.2 引发块I/O子系统的软中断 368

5.6.3 调用请求队列的软中断回调 369

5.6.4 调用上层的完成回调函数 383

5.7 屏障I/O处理 386

5.7.1 屏障I/O接口 386

5.7.2 添加屏障请求 388

5.7.3 处理屏障请求 389

5.7.4 完成屏障请求 393

5.8 完整性保护 396

5.8.1 数据完整性对象 397

5.8.2 为块设备注册完整性能力 400

5.8.3 为bio准备完整性元数据 402

5.8.4 校验完整性元数据 406

5.8.5 修正bio基准标签 408

5.9 磁盘类设备驱动编程模式 411

5.9.1 定义磁盘类设备私有数据结构 411

5.9.2 定义和实现块设备操作表 411

5.9.3 分配和初始化磁盘类设备相关结构 411

5.9.4 为磁盘类设备准备请求队列并添加通用磁盘到系统 412

第6章 Multi-Disk(MD)模块 413

6.1 概述 413

6.2 RAID模块对象 414

6.2.1 mddev_t:RAID设备 414

6.2.2 mdk_rdev_t:成员磁盘 418

6.2.3 mdk_personality:MD个性 419

6.3 MD模块初始化 420

6.4 MD设备创建 423

6.4.1 从用户空间打开MD设备 424

6.4.2 用户空间发送ioctl创建MD 428

6.4.3 自动检测和运行RAID 439

6.5 MD设备请求执行 439

6.6 MD个性化编程模式 440

6.6.1 定义私有数据结构 441

6.6.2 明个性化结构 442

6.6.3 实现个性化方法 442

6.6.4 实现模块加载和卸载方法 445

6.7 RAID0模块 445

6.7.1 为RAID0设备构造条带区域 446

6.7.2 查找包含给定偏移的条带区域 451

6.7.3 映射到成员设备及其扇区偏移 451

6.8 RAID5模块 452

6.8.1 RAID5模块对象 452

6.8.2 请求执行过程 459

6.8.3 同步和恢复过程 507

第7章 Device Mapper模块 509

7.1 概述 509

7.2 Device Mapper对象 510

7.2.1 dm_table:映射表结构 512

7.2.2 dm_target:映射目标结构 513

7.2.3 mapped_device:映射设备结构 514

7.2.4 dm_dev:低层设备结构 515

7.2.5 target_type:映射目标类型 516

7.3 Device Mapper模块初始化 518

7.4 映射设备的创建 519

7.4.1 分配映射设备描述符 521

7.4.2 加载映射表 526

7.4.3 恢复映射设备 532

7.5 映射设备的请求执行 536

7.5.1 添加到延迟链表 537

7.5.2 分割与处理bio 539

7.6 核复制线程 549

7.6.1 准备复制任务 551

7.6.2 任务处理流程 553

7.7 Device Mapper目标类型编程模式 556

7.7.1 定义私有数据结构 557

7.7.2 声明目标类型结构 557

7.7.3 实现目标类型方法 557

7.7.4 实现模块加载和卸载方法 558

7.8 条带映射模块 558

7.8.1 构造函数 559

7.8.2 析构函数 562

7.8.3 映射函数 562

7.8.4 end_io函数 563

7.9 快照映射模块 563

7.9.1 快照映射对象 564

7.9.2 快照源构造 569

7.9.3 快照构造 570

7.9.4 快照源读/写 577

7.9.5 快照读/写 585

7.9.6 例外仓库 588

第8章 文件系统 593

8.1 概述 593

8.2 文件系统对象 595

8.2.1 file_system_type:文件系统类型 596

8.2.2 super_block:VFS超级块 597

8.2.3 inode:VFS索引节点 602

8.2.4 dentry:VFS目录项 610

8.2.5 vfsmount:文件系统装载 612

8.3 装载文件系统 614

8.3.1 mount系统调用的处理流程 618

8.3.2 构建子文件系统装载实例 621

8.3.3 关联文件系统的超级块实例 623

8.3.4 调用回调函数填充超级块 626

8.3.5 装载到全局文件系统树 630

8.4 路径查找 632

8.4.1 路径查找入口 635

8.4.2 逐个分量解析 637

8.4.3 解析单个分量 642

8.4.4 上溯通过装载点 645

8.4.5 下溯通过装载点 646

8.4.6 处理符号链接 646

8.5 打开文件 651

8.5.1 open系统调用的处理流程 653

8.5.2 解析路径最后一个分量 658

8.5.3 填充文件描述符的内容 662

8.6 读文件 665

8.6.1 read系统调用的处理流程 670

8.6.2 基于缓冲页面构造I/O请求 683

8.6.3 直接针对页面构造I/O请求 690

8.6.4 从文件块编号推导磁盘块编号 696

8.7 写文件 700

8.7.1 write系统调用的处理流程 700

8.7.2 通知为缓冲写请求作准备 707

8.7.3 通知数据已复制到缓冲区 712

8.8 冲刷文件 715

8.8.1 BDI相关对象 715

8.8.2 注册后备设备信息 719

8.8.3 forker线程执行流程 721

8.8.4 flusher线程执行流程 723

8.8.5 同步相关系统调用 749

8.9 块设备文件 761

8.9.1 块设备的主inode和次inode 762

8.9.2 对块设备文件的操作转换为对块设备的操作 764

8.9.3 对块设备文件的读/写作用于块设备之上 767

8.10 文件系统编程模式 767

主要参考文献 769

图1-1 磁盘驱动器的物理组件 3

图1-2 SSD驱动器的框图 4

图1-3 SAS磁盘柜的前视图和后视图 5

图1-4 控制器SAS磁盘柜内部框图 5

图1-5 NAS网络结构 6

图1-6 iSCSI层次 6

图1-7 NAS/iSCSI集成存储系统模块示意图 7

图1-8 SAS主机适配器框图 8

图1-9 适配器硬件、固件及驱动之间的关系 8

图1-10 网络适配器、TOE网络适配器和iSCSI适配器 9

图1-11 直接连接备份模型 11

图1-12 网络连接备份模型 11

图1-13 脱局域网备份模型 12

图1-14 脱服务器备份模型 12

图1-15 备份过程中可能导致的数据不一致问题 13

图1-16 创建快照 14

图1-17 首次写源卷 15

图1-18 后续写源卷 15

图1-19 卖源卷 15

图1-20 读快照卷——未命中 16

图1-21 卖快照卷——命中 16

图1-22 快照回滚 17

图1-23 回滚和前滚 17

图1-24 写时转向 18

图1-25 拆分镜像备份过程 19

图1-26 做快照时刷新应用程序缓存 20

图1-27 连续数据保护范例 21

图1-28 条带化模型 23

图1-29 RAID0布局 24

图1-30 RAID1布局 24

图1-31 RAID1在正常和降级状态下的读/写操作 25

图1-32 RAID2布局 25

图1-33 RAID3布局 26

图1-34 RAID3在正常和降级状态下的读/写操作 26

图1-35 RAID4布局 27

图1-36 RAID5布局 27

图1-37 RAID5校验分布算法 28

图1-38 RAID5在正常和降级状态下的读操作 28

图1-39 RAID5在正常状态下的写操作 29

图1-40 RAID5在降级状态下的写操作 29

图1-41 RAID6的P+Q方案 30

图1-42 RAID6的EVEN-ODD方案中水平校验计算 31

图1-43 RAID6的EVEN-ODD方案中对角校验计算 32

图1-44 利用RAID6的EVEN-ODD算法恢复两个数据磁盘故障 33

图1-45 RAID6恢复实例——正常布局 34

图1-46 RAID6恢复实例——磁盘故障 34

图1-47 RAID6恢复实例——第一轮 34

图1-48 RAID6恢复实例——第二轮 34

图1-49 RAID6恢复实例——第三轮 35

图1-50 RAID6恢复实例——第四轮 35

图1-51 RAID6恢复实例——第五轮 35

图1-52 RAID6恢复实例——回到正常状态 35

图1-53 RAID6的DH1方案 36

图1-54 RAID6的DH2方案 36

图1-55 “多路径”硬件配置(从左到右依次为①、②、③、④) 37

图1-56 “多路径”软件的实现层次 38

图1-57 存储虚拟化分类 39

图1-58 存储技术分类 40

图1-59 Intel北桥/南桥架构 41

图1-60 应用服务器的存储I/O物理通道 42

图1-61 网络存储子系统的存储I/O物理通道 43

图1-62 存储I/O逻辑通道 44

图1-63 虚拟机存储栈 45

图1-64 存储设备同时提供文件服务和块服务 45

图1-65 即插即用的在线存储扩容 46

图1-66 计算与存储分离便于应用服务器故障恢复和系统升级 46

图1-67 为高可用性集群提供共享存储 47

图1-68 利用快照技术恢复被病毒破坏的数据 47

图1-69 基于文件的数据备份和远程镜像 48

图1-70 利用PXE和iSCSI实现远程引导和映像恢复 48

图1-71 虚拟机故障的检测和迁移 49

图2-1 Linux驱动模型 52

图2-2 使用container of宏获得已知成员指针的宿主对象指针 54

图2-3 传统方式下的双循环链表结构 56

图2-4 Linux内核中的双循环链表结构 56

图2-5 kset和kobject的关系图 57

图2-6 uevent环境数据 68

图2-7 内部树的节点 70

图2-8 sysfs文件系统的装载实例 73

图2-9 sysfs文件系统的目录项表示 74

图2-10 为具体内核对象定义属性的规范优流程 78

图2-11 Linux驱动模型对象之间的关系 82

图2-12 设置设备内嵌内核对象的父对象 95

图2-13 PCI驱动和SCSI驱动的probe回调函数 100

图3-1 PCI体系结构 110

图3-2 类型00h的配置空间头 112

图3-3 映射到内存空间的基地址寄存器 113

图3-4 映射到I/O空间的基地址寄存器 113

图3-5 类型01h的配置空间头 113

图3-6 配置地址寄存器的布局 114

图3-7 类型0的PCI配置事务 115

图3-8 类型1的PCI配置事务 115

图3-9 PCI子系统对象之间的关系 116

图3-10 PCI子系统的驱动模型对象关系 121

图3-11 Linux初始化代码使用的某些内存节 123

图3-12 PCI总线编号实例一——拓扑结构 134

图3-13 PCI总线编号实例一——第一轮 134

图3-14 PCI总线编号实例一——第二轮 134

图3-15 PCI总线编号实例一——第三轮 135

图3-16 PCI总线编号实例一——第四轮 135

图3-17 PCI总线编号实例二——拓扑结构 136

图3-18 PCI总线编号实例二——第一轮 136

图3-19 PCI总线编号实例二——第二轮 137

图3-20 PCI总线扫描函数调用流程 138

图3-21 根总线创建时的驱动模型设备关系 142

图3-22 根总线上发现设备时的驱动模型设备关系 149

图3-23 桥设备后发现PCI总线时的驱动模型设备关系 157

图3-24 非根PCI总线上发现设备时的驱动模型设备关系 158

图3-25 PCI总线的sysfs 159

图3-26 PCI中断通过可编程中断路由器路由到8259A 162

图3-27 从PCI设备中断路由到ISA IRQ编号 164

图3-28 热插设备由于桥设备的资源窗口被耗尽而无法启动 178

图3-29 PCI设备资源分配——拓扑结构 178

图3-30 PCI设备资源分配实例一——第一轮 179

图3-31 PCI设备资源分配实例一——第二轮 179

图3-32 PCI设备资源分配实例一——第三轮 179

图3-33 PCI设备资源分配实例一——第四轮 180

图3-34 PCI设备资源分配实例二——第一轮 180

图3-35 PCI设备资源分配实例二——第二轮 181

图3-36 resource表示各种类型的资源 182

图3-37 资源分配实例 183

图3-38 PCI资源保留函数调用流程 184

图3-39 资源区间冲突可能 187

图3-40 PCI资源分配函数调用流程 189

图3-41 PCI驱动支持静态ID列表和动态ID列表 195

图4-1 Linux SCSI子系统的分层架构 201

图4-2 Linux SCSI模型 202

图4-3 SCSI对象之间的关系 203

图4-4 SCSI主机适配器的驱动模型对象关系 210

图4-5 SCSI目标节点的驱动模型对象关系 211

图4-6 SCSI设备的驱动模型对象关系 214

图4-7 一次性分配SCSI主机适配器的公有部分和私有部分 219

图4-8 SCSI总线的sysfs 219

图4-9 SCSI子系统的驱动模型设备关系 223

图4-10 scsi scan host函数调用流程 224

图4-11 与SCSI磁盘有关的各种结构 243

图4-12 为SCSI磁盘生成主设备号和次设备号 246

图4-13 SCSI设备及其派生的SCSI磁盘之间的驱动模型设备关系 247

图4-14 缓存对DMA操作的影响 280

图4-15 驱动和设备固件之间的消息交互机制 282

图5-1 Linux块I/O子系统的分层架构 286

图5-2 通用磁盘、分区和块设备描述符 288

图5-3 request queue、request、bio和bio vec的关系 288

图5-4 磁盘类设备、通用磁盘及请求队列描述符 290

图5-5 逐个segment执行bio 299

图5-6 SCSI设备及其派生的通用磁盘之间的驱动模型设备关系 304

图5-7 通用设备及其分区之间的驱动模型设备关系 314

图5-8 设备号映射域 315

图5-9 反弹缓冲区的使用 324

图5-10 向前合并、向后合并和无法合并 325

图5-11 提交请求到通用块层 326

图5-12 Linux块层的Plugging/Unplugging模型 327

图5-13 聚散列表 344

图5-14 bio执行过程中的两次合并 349

图5-15 请求队列、调度器队列和调度器类型 354

图5-16 最后期限I/O调度算法的四个队列 355

图5-17 屏障I/O的两个目的:排序和冲刷 386

图5-18 DIF及DIX数据完整性保护 396

图5-19 520字节的扇区包含512字节的数据和8字节的DIF三元组 397

图5-20 完整性对象关系 399

图5-21 DIX和DIF操作:粗框表示保护路径 400

图6-1 MD模块的分层架构 413

图6-2 MD对象之间的关系 414

图6-3 RAID超级块在成员磁盘上的存储位置 434

图6-4 Linear MD的私有配置结构 441

图6-5 RAID0的条带区域示例 445

图6-6 RAID0 MD的私有配置结构 446

图6-7 RAID0设备的扇区映射 452

图6-8 RAID5 MD的私有配置结构 453

图6-9 Linux RAID5条带基本概念 456

图6-10 根据扇区编号计算数据磁盘和校验磁盘的编号及在其上的扇区编号(RAID4/5) 464

图6-11 根据扇区编号计算数据磁盘和校验磁盘的编号及在其上的扇区编号(RAID6) 464

图6-12 通用块层请求被链接到条带设备的towrite链表 470

图6-13 判断条带/设备是否被覆写 472

图7-1 Device Mapper及LVM的实现层次 509

图7-2 Device Mapper的对象关系 511

图7-3 映射表的偏移数组和目标数组布局 513

图7-4 映射设备通过hash cell链入两个哈希表 522

图7-5 用于用户空间和内核空间IOCTL交换的结构 529

图7-6 计算映射目标运行的最大I/O长度 544

图7-7 将整个bio、多个segment或一个segment的一部分映射到映射目标 545

图7-8 线性映射的私有配置结构 557

图7-9 条带映射的私有配置结构 559

图7-10 条带映射目标扇区的计算 563

图7-11 快照映射中的设备 564

图7-12 快照映射中快照的私有配置结构 565

图7-13 快照映射中快照源的私有配置结构 565

图7-14 从“通用结构”到“个性结构”的编程模式 589

图7-15 COW设备的布局 591

图8-1 Linux文件系统的分层架构 594

图8-2 Minux文件系统磁盘布局 595

图8-3 Linux VFS对象之间的关系 596

图8-4 VFS和具体文件系统的超级块 598

图8-5 VFS和具体文件系统的inode 602

图8-6 VFS和具体文件系统的dentry 610

图8-7 文件系统装载实例的四个必备要素 614

图8-8 文件系统的装载关系 615

图8-9 装载点原来的子树被隐藏 615

图8-10 两个文件系统装载到同一个装载点 616

图8-11 一个文件系统装载到两个不同的装载点 617

图8-12 装载到文件系统的两个不同装载实例的同一装载点 618

图8-13 Minix文件系统的内存超级块 630

图8-14 路径查找 632

图8-15 路径查找中的循环和递归过程 633

图8-16 查找给定名字的子目录项 644

图8-17 符号链接 647

图8-18 硬链接 647

图8-19 打开常规文件时内核关联 653

图8-20 打开字符设备文件时内核关联 665

图8-21 Minix文件系统的地址空间关联 667

图8-22 通过页面缓存读取数据 680

图8-23 缓冲头和缓冲页面 683

图8-24 一个页面的逻辑块映射到磁盘块的各种情况 696

图8-25 Minix文件系统数据块寻址 696

图8-26 Minix文件系统下从文件块编号推导磁盘块编号 698

图8-27 写入范围和当前缓冲区块的六种完全情况 711

图8-28 已复制的字节数不等于准备好的字节数 713

图8-29 BDI相关对象之间的关系 716

图8-30 在回写控制指定和不指定超级块的情况下的inode冲刷方式 733

图8-31 页面索引和文件长度比较 744

图8-32 Minux文件系统的地址空间分布 755

图8-33 块设备文件的inode 762

图8-34 bdev文件系统的装载实例 763

图8-35 块设备的主inode和次inode 763

图8-36 块设备文件的地址空间 764