[MIT 6.S081] Lec 16: File system performance and fast crash recovery 笔记

本文深入探讨了文件系统性能和快速崩溃恢复的策略,以Linux ext3文件系统为例。预写规则确保原子性,释放规则防止数据丢失。XV6的同步写操作成为性能瓶颈,而ext3通过异步系统调用、批量执行和并发控制提升性能。在提交过程中,ext3使用新的事务来分批写入,并等待所有数据写入磁盘。崩溃恢复时,通过扫描日志确定已提交事务,并将它们的数据写回文件系统。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Lec 16: File system performance and fast crash recovery

logging 重要规则

  • write ahead rule(预写规则): 一系列写操作具有原子性, 系统需要先将写操作记录到日志中, 再将这些写操作应用到文件系统的实际位置(在做任何实际修改之前将所有更新提交到日志).
  • freeing rule(释放规则): 直到日志中所有写操作更新到文件系统之前, 都不能释放或者重用日志. 即在日志中删除一个事务之前, 必须将日志中的所有 block 都写到文件系统中.

XV6 日志的性能瓶颈

  • XV6 中的文件相关系统调用, 都需要整个事务完成后才能返回, 即 XV6 写磁盘操作是同步的(synchronized), 需要完成 end_op() 中包含的内容:
    • 将所有更新的 block 写入日志
    • 更新日志头(header block)
    • 将日志中的所有 block 写回到文件系统中
    • 清除 header block
  • 文件相关的系统调用是串行的, 一个文件系统调用的提交(commit)过程中, 其他系统调用不能对文件系统有任何更新.

ext3 文件系统数据结构

在这里插入图片描述

  • block cache: 缓存了磁盘中的一些 block, 是一种 write-back cache(回写缓存, 缓存稍后才会同步到真正的后端)
  • 事务(transaction)信息:
    • 事务的序列号(记录在 descriptor block 和 commit block 中)
    • 该事务修改的一组 block 的编号, 指向内存的 block cache
    • 一组 handle, 有关仍在并发执行的系统调用的信息
      磁盘中包括:
  • 文件系统树, 包含 inode, 目录, 文件等
  • bitmap block: 记录每个数据块是否分配
  • 日志:
    • super block: 在日志的最开始, 包含第一个有效的事务的偏移量和序列号.
    • 每个日志中的事务包含:
      • 开头是 1 个 descriptor block: 包含日志数据对应的实际 block 编号, 类似 XV6 的 header block
      • 之后是对应 block 编号的实际更新内容的 block
      • 对于完成并提交的事务在最后有一个 commit block
      • descriptor block 和 commit block 都有一个魔数(magic number)用于与数据块区分.
      • 日志的结构类似于一个循环队列, 一个时刻只有一个正在进行的事务还未从内存更新到磁盘, 而其他事务已经完成提交.

在这里插入图片描述

ext3 提升性能的方式

  • 异步(asynchronous)系统调用: 系统调用在写入磁盘前就会返回, 只更新缓存在内存中的 block, 而不等待写磁盘操作, 但可能会等待读磁盘操作
  • 批量(batching)执行: 将多个系统调用打包成一个事务
  • 并发(concurrency)

异步系统调用

  • 优点:
    • 使得系统调用能够快速返回
    • 使得大量的批量执行变得容易
  • 缺点:
    • 系统调用返回不能表示其应该完成的工作已经完成
    • 通过 fsync 系统调用等待所有数据写入磁盘后返回

批量执行

  • ext3 只有一个正在执行的事务(open transaction)
  • 一个事务可以包含多个不同的系统调用. 每隔一定时间会创建一个新事务, 之后一段时间内的系统调用都会被打包到该事务中. ext3会在所有正在进行的系统调用都完成对 block 的写操作后(即到达 stop() 函数时)才能进行提交.
  • 优点:
    • 分摊了执行事务的固有损耗. 包括写 descriptor block 和 commit block, 查找日志位置并等待机械磁盘
    • 更容易触发 write absorption(写入吸收): 即由于数据的空间局部性, 多次操作可能更新相同的 block, 因此可以减少写磁盘操作
    • disk scheduing(磁盘调度): 向磁盘提交大批量的写操作, 磁盘可以调度这些请求, 进行优化执行.

并发

  • ext3 允许多个系统调用同时执行. 在关闭并提交当前事务之前, 系统调用不必等待其它系统调用完成. 在 XV6 中若当前的事务不足够执行新的系统调用, 则新的系统调用不能继续执行.
  • ext3 可以有多个不同阶段的事务同时存在
    • 有一个打开的事务(open transaction): 用于接收当前系统调用.
    • 若干正在提交到日志的事务
    • 若干从 block cache 向文件系统中 block 写数据的事务
    • 若干正在被释放的事务

ext3 事务提交过程

  1. 阻止新的系统调用.
  2. 等待包含在事务中已经开始的系统调用结束(等待其完成更新 block cache 中的数据)
  3. 开启一个新的事务, 并将 1. 中等待的系统调用继续进行
  4. 更新(关闭)事务的 descriptor block, 其中包含所有在事务中被修改的 block 的编号
  5. 将被修改的 block 从缓存写入到磁盘的日志中. 此处写入磁盘日志的是事务结束时对于相关 block cache 的拷贝(即该事务之后的 block 更新时不会写入该事务的磁盘日志中的).
  6. 等待 4. 5. 两步写日志完成.
  7. 写 commit block
  8. 等待写 commit block 结束. 此时达到提交点(commit point).
  9. 将事务中包含的 block 写入到文件系统的实际位置
  10. 可以重用事务对应的日志空间.

ext3 文件系统恢复过程

  1. 恢复软件读取日志的 super block, 找到日志第一个有效事务的位置.
  2. 根据事务的 descriptor block 中记录的 data block 的数量, 扫描这些 data block. 若当前事务已经完成提交, 就会包含 commit block.
  3. 然后再去看 commit block 的下一个 block 是否是一个有效的 descriptor block, 然后重复 2. 操作. 若当前事务没有 commit block 或其之后不为有效的 descriptor block则停止扫描.
  4. 当前已经确定了所有已经提交的事务, 并将这些事务的 log block 写到文件系统的实际位置.
  5. 恢复完成之后, 才能运行其他程序.
  • 注: 除了 descriptor block 和 commit block 的其它 block 不会以 32 比特的魔数起始(有的话会在写日志时替换, 在写文件系统时恢复).
  • XV6 只支持一个事务中包换多个系统调用. 但是 XV6 是同步的, 即执行系统调用(写 block)和提交事务不能同时进行, 而 ext3 可以.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值