To answer your first question:
"Occur" refers to the whole read, from the point of the call to the point of the value being returned. All of it has to happen after the previous write, and before the next write. The same page says so:
After a write() to a regular file has successfully returned:
Any successful read() from each byte position in the file that was modified by that write shall return the data specified by the write() for that position until such byte positions are again modified.
Any subsequent successful write() to the same byte position in the file shall overwrite that file data.
POSIX makes no guarantee whatsoever on any sort of interleaving, because implementing additional guarantees is quite difficult.
Regarding the second question:
Again, refer to the above quote. If a process called write()
and write()
returned successfully, any subsequent read by any processes would reflect the written data.
So the answer is "yes, if the first write() failed".
Implementation:
ext4, and almost every other filesystem, uses a page cache. The page cache is an in-memory representation of the file's data (or a relevant part thereof). Any synchronization that needs to be done, is done using this representation. In that respect, reading and writing from the file is like reading and writing from shared memory.
The page cache, as the name suggests, is built with pages. In most implementations, a page is a region of 4k of memory, and reads and writes happen on a page basis.
This means that e.g. ext4 will serialize reads & writes on the same 4k region of the file, but a 12k write may not be atomic.
AFAICT, ext4 does not allow concurrent multiple writes on the same page, or concurrent reads & writes on the same page, but it is nowhere guaranteed.
edit: The filesystem (on-disk) block size might be smaller than a page, in which case some I/O may be done at a block-size granularity, but that is even less reliable in terms of atomicity.