实现崩溃一致性

实现崩溃一致性

2025 南京大学《操作系统原理》
实现崩溃一致性

Systems: “先挣钱,后还债”

崩溃会导致数据丢失、目录损坏,甚至文件系统无法挂载

  • 这时候当然是送去修电脑 (File System Check) 了!

center

(这种图我都能找到???论文件系统加密的重要性)
2025 南京大学《操作系统原理》
实现崩溃一致性

File System Checking (FSCK)

根据磁盘上已有的 G(V,E)G(V, E),恢复出 “最可能” 的数据结构

center

  • 是的,这是个算法题
    • 而且一不小心,fsck 时 crash 能 “恢复” 出一个无法挂载、无法修复的文件系统 (paper)
2025 南京大学《操作系统原理》
实现崩溃一致性

吸取历史的经验和教训

还记得并发的故事吗

  • 1960s,大家争相在共享内存上实现互斥
  • Relaxed memory model
    • 软件不够,硬件来凑 😭
    • 软硬协同实现崩溃互斥/同步

存储器是同样的 “乱序执行” 模型

  • 不要实现 ad-hoc 的崩溃一致性
  • 存储系统应该也提供一条 fence 指令
    • 软硬协同实现崩溃一致性
2025 南京大学《操作系统原理》
实现崩溃一致性

实现崩溃一致性

磁盘:提供的接口

  • bwrite
    • 收到立即返回,异步写入 (eventually persistent)
  • bread
    • 如果在缓存里,立即返回数据
    • 如果不在缓存中,调度实际读操作,数据到达后再返回
  • bflush
    • 等待所有已写入的数据落盘
    • 现代存储系统可以提供更细粒度的 flush
      • SCSI: Synchronize Cache
      • SSD: 固件控制
2025 南京大学《操作系统原理》
实现崩溃一致性

重新理解 “数据结构”

视角 1: 存储实际数据结构 (链表、二叉树、……)

  • 文件系统的 “直观” 表示
  • Multi-write (crash unsafe)

视角 2: Append-only 记录所有历史操作

  • “重做” 所有操作得到数据结构的当前状态
  • 容易实现崩溃一致性

1 + 1 > 2

  • Append 更容易高效实现
2025 南京大学《操作系统原理》
实现崩溃一致性

Append-only + Lazy Update

Store buffer

  • Store 写入 CPU 本地缓存,慢慢传递给其他处理器

LSM (Log-structured Merge Trees)

center

2025 南京大学《操作系统原理》
实现崩溃一致性

用 Atomic Append 实现 Atomic Perform

实现 atomic_perform(operations)

center

  1. bread 定位到 journal 的末尾
  2. bwrite TXBegin ; operations
  3. bflush 等待数据落盘
  4. bwrite TXEnd (Commit; 实现 Atomic Append)
  5. bflush 等待数据落盘
  6. replay(operations) —— 所以也叫 “redo log”
  7. replay 数据落盘后可以删除 (标记) 日志
2025 南京大学《操作系统原理》
实现崩溃一致性

Journaling: 优化

现在磁盘需要写入双份的数据

  • 批处理 (xv6; jbd)
    • 多次系统调用的 Tx 合并成一个,减少 log 的大小
    • jbd: 定期 write back
  • Checksum (ext4)
    • 不再标记 TxBegin/TxEnd
    • 直接标记 Tx 的长度和 checksum
  • Metadata journaling (ext4 default)
    • 数据占磁盘写入的绝大部分
      • 只对 inode 和 bitmap 做 journaling 可以提高性能
    • 保证文件系统的目录结构是一致的;但数据可能丢失
2025 南京大学《操作系统原理》
实现崩溃一致性

write() 返回了,其实文件还没写到磁盘!

sync() 系列系统调用

  • sync: 同步所有文件系统中的所有数据
    • 最强,等于 performance bug
  • syncfs(fd): 同步 fd 对应的文件系统
  • fsync(fd): 同步文件 data + metadata
  • fdatasync(fd): 同步文件 data
    • 最弱,但依旧可以控制 data loss (追加写可能丢失)
    • API 设计者的难题:要不要再加一个 fddatasync() 呢?

sync (1): 系统调用的封装

  • -d data only (fdatasync), -f file system (syncfs)
2025 南京大学《操作系统原理》
实现崩溃一致性

Journaling 的代价 🌶️

从应用视角,文件系统的行为可能很 “怪异”

更为一劳永逸的方案:TxOS

  • xbegin/xend/xabort 系统调用实现跨 syscall 的 “all-or-nothing”
    • Android 干脆让应用直接用 SQLite 得了
2025 南京大学《操作系统原理》