I know that when I write files using write() + fsync() (or O_SYNC + write(), I think they are same ref #1 ref #2), it means I am using blocking synchronous I/O, and the if the write()(with O_SYNC) or fsync() returns, it means the data is safely on the device medium (e.g., TLC NAND for SSD) rather than the device cache (e.g., DDRAM in SSD).
While what if I use libaio? (because I want to make sure the write issued by libaio is on the storage medium rather than the device cache. i.e., I suppose when io_getevents() returns, it may not make sure the write is on the storage medium, and it may just on the device cache)
- Question 1: does
fsync()exclusively works for synchronous I/O? - Question 2:is
fsync()afterio_submit()an undefined behavior? - Question 3: how to make asynchronous write safely persisted to the device medium rather than device cache (no battery-backed cache).
(This answer is only looking at things from Linux perspective. Other operating systems may have different behaviour/semantics)
So long as you wait for any outstanding asynchronous I/O to be completed you will be able to then send down your
fsync()and know all previous I/O was written to stable storage to the best knowledge of the Linux kernel*.This question doesn't make sense.
fsync()works on I/O that Linux has agreed has been "sent" and then also flushes the device cache. If you asynchronously send an I/O to the kernel, has the kernel agreed it has been "sent"? Also see the answer to final question...Technically undefined behaviour would mean from then on ANYTHING would be allowed to legally happen (e.g. so called nasal daemons). That's not the case here but I think you are asking your first question so the answer there still holds.
If you're stuck using
libaioyou could manually build a barrier by waiting for all outstanding I/O to be completed and then sending anfsync()and waiting for that or (as mentioned in a comment). Anotherlibaiotechnique is to set theRWF_SYNCflag duringio_submit(). If you were usingio_uringyou would have another option because you can use its chaining and it has an asynchronousfsyncoperation (IORING_OP_FSYNC).* I'm excluding the cases where errors happen because they are rather more complicated. See Writing programs to cope with I/O errors causing lost writes on Linux for a detailed explaintion.