【问题标题】:What will be if I use libaio + fsync()?如果我使用 libaio + fsync() 会怎样?
【发布时间】:2021-05-10 09:03:21
【问题描述】:

我知道当我使用write() + fsync()(或O_SYNC + write(),我认为它们是相同的ref #1 ref #2)编写文件时,这意味着我正在使用阻塞同步I/ O,如果write()(with O_SYNC) 或fsync() 返回,则表示数据安全地保存在设备介质上(例如SSD 的TLC NAND)而不是设备缓存(例如SSD 中的DDRAM) )。

如果我使用libaio 会怎样? (因为我想确保libaio发出的写是在存储介质上而不是在设备缓存上。也就是说,我想当io_getevents()返回时,它可能无法确定写在存储介质上,它可能只是在设备缓存上)

  • 问题 1fsync() 是否专门用于同步 I/O?
  • 问题2fsync()io_submit()之后是未定义的行为吗?
  • 问题 3:如何使异步写入安全地持久化到设备介质而不是设备缓存(无电池支持的缓存)。

【问题讨论】:

标签: io aio fsync


【解决方案1】:

(这个答案只是从 Linux 的角度来看问题。其他操作系统可能有不同的行为/语义)

只要您等待任何未完成的异步 I/O 完成,您就可以发送您的 fsync() 并知道所有以前的 I/O 都已写入稳定存储,以了解 Linux 内核的最佳知识*.

fsync() 是否专门用于同步 I/O?

这个问题没有意义。 fsync() 适用于 Linux 已同意已“发送”的 I/O,然后还刷新设备缓存。如果您向内核异步发送 I/O,内核是否同意它已“发送”?另请参阅最后一个问题的答案...

io_submit() 之后的 fsync() 是未定义的行为吗?

从技术上讲,undefined behaviour 意味着从那时起任何事情都将被允许合法地发生(例如所谓的鼻部守护程序)。这不是这里的情况,但我认为你是在问你的第一个问题,所以那里的答案仍然成立。

如何使异步写入安全地持久化到设备介质而不是设备缓存(无电池支持的缓存)。

如果您在使用 libaio 时遇到问题,您可以手动构建屏障,方法是等待所有未完成的 I/O 完成,然后发送 fsync() 并等待或 (as mentioned in a comment)。另一种libaio 技术是在io_submit() 期间设置RWF_SYNC 标志。如果您使用的是io_uring,您将有另一个选择,因为您可以使用它的链接,并且它有一个异步的fsync 操作(IORING_OP_FSYNC)。


* 我排除了发生错误的情况,因为它们相当复杂。详细说明见Writing programs to cope with I/O errors causing lost writes on Linux

【讨论】:

  • 在另一个答案中,您提到:“使用直接 I/O io_submit() 直到其所有请求都已分配并在块层级别排队时才会返回。”那么,在调用fsync()之前是否还需要手动构建屏障?
  • @sayap 因为你怎么知道fsync() 不会超过提交的 I/O 并在它们之前返回?仅仅因为您已将一些物品排入队列,您需要另一个保证,即在您的fsync() 完成之前,不会再进行任何级别的重新订购。如果你以某种方式保证内核永远不会重新排序提交的命令(如何?)我可以转身问“你如何保证磁盘控制器不会重新排序命令”?
猜你喜欢
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 2021-06-06
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
  • 2017-09-17
相关资源
最近更新 更多