文件系统如何原子地将块写入磁盘?

文件系统如何原子地将块写入磁盘?

块是文件系统提供的一个抽象,块大小是磁盘扇区大小的整数倍。假设一个文件系统使用4K作为块大小,磁盘扇区大小为512B,当文件系统向磁盘驱动程序发出写请求时,如何原子地将整个 4K 块写入磁盘(避免部分写入)? 我想知道现代内核如何解决这个问题,但我不想深入 Linux 代码库来寻找答案。任何帮助将不胜感激。

答案1

磁盘应该允许一个部门以原子方式写入。扇区大小为 512 字节,而如今较大的磁盘通常为 4096 字节。

为了避免部分写入的“块”出现问题,以特殊顺序写入所有内容非常重要。

请注意,可能存在的唯一原因是部分写成文件系统中的一部分是断电或类似的情况。

方法是:

  • 首先写入所有文件内容并验证这是否有效

  • 然后写入元数据,并确保元数据中的所有数据结构都适合单个磁盘扇区,并且不跨越扇区边界。例如,这对于作为目录内容的可变长度文件名很重要。

答案2

这取决于底层存储技术。

某些存储允许以原子方式存储特定的块大小,通常为 2 的幂,至少为 256,并且通常在 1kB-4kB 范围内。如果是这种情况,那么文件系统层可以就地替换块,前提是块的替换产生有效的系统状态。在写入文件内容时这很好(Unix 对此不提供任何原子性保证),但在写入文件系统元数据时则不然。

另一种不需要磁盘层任何合作的方法(除了知道写入一个块不会损坏其他块的内容之外)是永远不擦除现有块,但始终写入当前未使用的存储块。如果写入成功,则可以将该块的引用添加到另一个块,替换对该块的早期版本的引用;包含早期版本的块被标记为空闲。这会比较慢,因为更新一个块需要更新另一个块,而这又需要更新另一个块,等等。递归在系统保留多个副本的块处停止;如果在写入其中一个副本时发生崩溃,则会使用其他副本。如果有三个或更多副本,则可以基于多数比较来选择正确的副本,如果有两个副本,则可以基于校验和来选择正确的副本。

然后还有对数结构文件系统,块不断添加到块列表的末尾。文件系统的基本元数据是在最后一个有效块中找到的任何内容。最后一个块是通过检查块时间戳和校验和来确定的。

(注意:这个答案是关于通用文件系统实现问题的,我还没有去检查各种 Unix 变体上的各种存储介质上的各种文件系统实际上是做什么的。)

答案3

一般来说,所有现代操作系统都会有一个系统调用来将数据写入文件(在 Linux 中我们有write系统调用)。

因为所有系统调用都应该是原子的。因此写入整个块大小(仅使用 1 个系统调用)将是原子的。

相关内容